@ant-design/icons#UsergroupAddOutlined TypeScript Examples

The following examples show how to use @ant-design/icons#UsergroupAddOutlined. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx    From dashboard with Apache License 2.0 5 votes vote down vote up
GroupChatSelect: React.FC<GroupChatTreeSelectProps> = (props) => {
  const { value, onChange, allGroupChats, ...rest } = props;
  const [groupChatSelectionVisible, setGroupChatSelectionVisible] = useState(false);
  const allGroupChatMap = _.keyBy<GroupChatOption>(allGroupChats, 'ext_chat_id');

  return (
    <>
      <Select
        {...rest}
        mode='multiple'
        placeholder='请选择群聊'
        allowClear={true}
        value={value}
        open={false}
        maxTagCount={5}
        tagRender={(tagProps) => {
          // @ts-ignore
          const groupChat: GroupChatOption = allGroupChatMap[tagProps.value];
          return (
            <span className={'ant-select-selection-item'}>
              <span className={styles.selectedItem}>
                <div className={styles.avatar}>
                  <UsergroupAddOutlined style={{ color: 'rgba(0,0,0,0.65)' }} />
                </div>
                <div className='flex-col align-left'>
                  <span>{groupChat?.name}</span>
                </div>
              </span>
              <span
                className='ant-select-selection-item-remove'
                style={{ marginLeft: 3 }}
                onClick={(e) => {
                  e.preventDefault();
                  e.stopPropagation();
                  // @ts-ignore
                  onChange(value.filter((extGroupChatID: string) => extGroupChatID !== groupChat?.ext_chat_id));
                }}
              >
                <CloseOutlined />
              </span>
            </span>
          );
        }}
        onClear={() => {
          // @ts-ignore
          onChange([]);
        }}
        onClick={() => {
          setGroupChatSelectionVisible(!groupChatSelectionVisible);
        }}
      />

      <GroupChatSelectionModal
        visible={groupChatSelectionVisible}
        setVisible={setGroupChatSelectionVisible}
        defaultCheckedGroupChats={value?.map((extGroupChatID: string) => allGroupChatMap[extGroupChatID])}
        onFinish={(values) => {
          // @ts-ignore
          onChange(values.map((groupChat) => groupChat.ext_chat_id));
        }}
        allGroupChats={allGroupChats}
      />
    </>
  );
}
Example #2
Source File: commandPaletteLogic.ts    From posthog-foss with MIT License 4 votes vote down vote up
commandPaletteLogic = kea<
    commandPaletteLogicType<
        Command,
        CommandFlow,
        CommandRegistrations,
        CommandResult,
        CommandResultDisplayable,
        RegExpCommandPairs
    >
>({
    path: ['lib', 'components', 'CommandPalette', 'commandPaletteLogic'],
    connect: {
        actions: [personalAPIKeysLogic, ['createKey']],
        values: [teamLogic, ['currentTeam'], userLogic, ['user']],
        logic: [preflightLogic], // used in afterMount, which does not auto-connect
    },
    actions: {
        hidePalette: true,
        showPalette: true,
        togglePalette: true,
        setInput: (input: string) => ({ input }),
        onArrowUp: true,
        onArrowDown: (maxIndex: number) => ({ maxIndex }),
        onMouseEnterResult: (index: number) => ({ index }),
        onMouseLeaveResult: true,
        executeResult: (result: CommandResult) => ({ result }),
        activateFlow: (flow: CommandFlow | null) => ({ flow }),
        backFlow: true,
        registerCommand: (command: Command) => ({ command }),
        deregisterCommand: (commandKey: string) => ({ commandKey }),
        setCustomCommand: (commandKey: string) => ({ commandKey }),
        deregisterScope: (scope: string) => ({ scope }),
    },
    reducers: {
        isPaletteShown: [
            false,
            {
                hidePalette: () => false,
                showPalette: () => true,
                togglePalette: (previousState) => !previousState,
            },
        ],
        keyboardResultIndex: [
            0,
            {
                setInput: () => 0,
                executeResult: () => 0,
                activateFlow: () => 0,
                backFlow: () => 0,
                onArrowUp: (previousIndex) => (previousIndex > 0 ? previousIndex - 1 : 0),
                onArrowDown: (previousIndex, { maxIndex }) => (previousIndex < maxIndex ? previousIndex + 1 : maxIndex),
            },
        ],
        hoverResultIndex: [
            null as number | null,
            {
                activateFlow: () => null,
                backFlow: () => null,
                onMouseEnterResult: (_, { index }) => index,
                onMouseLeaveResult: () => null,
                onArrowUp: () => null,
                onArrowDown: () => null,
            },
        ],
        input: [
            '',
            {
                setInput: (_, { input }) => input,
                activateFlow: () => '',
                backFlow: () => '',
                executeResult: () => '',
            },
        ],
        activeFlow: [
            null as CommandFlow | null,
            {
                activateFlow: (currentFlow, { flow }) =>
                    flow ? { ...flow, scope: flow.scope ?? currentFlow?.scope, previousFlow: currentFlow } : null,
                backFlow: (currentFlow) => currentFlow?.previousFlow ?? null,
            },
        ],
        rawCommandRegistrations: [
            {} as CommandRegistrations,
            {
                registerCommand: (commands, { command }) => {
                    return { ...commands, [command.key]: command }
                },
                deregisterCommand: (commands, { commandKey }) => {
                    const { [commandKey]: _, ...cleanedCommands } = commands // eslint-disable-line
                    return cleanedCommands
                },
            },
        ],
    },

    listeners: ({ actions, values }) => ({
        showPalette: () => {
            posthog.capture('palette shown', { isMobile: isMobile() })
        },
        togglePalette: () => {
            if (values.isPaletteShown) {
                posthog.capture('palette shown', { isMobile: isMobile() })
            }
        },
        executeResult: ({ result }: { result: CommandResult }) => {
            if (result.executor === true) {
                actions.activateFlow(null)
                actions.hidePalette()
            } else {
                const possibleFlow = result.executor?.() || null
                actions.activateFlow(possibleFlow)
                if (!possibleFlow) {
                    actions.hidePalette()
                }
            }
            // Capture command execution, without useless data
            // eslint-disable-next-line @typescript-eslint/no-unused-vars
            const { icon, index, ...cleanedResult }: Record<string, any> = result
            // eslint-disable-next-line @typescript-eslint/no-unused-vars
            const { resolver, ...cleanedCommand } = cleanedResult.source
            cleanedResult.source = cleanedCommand
            cleanedResult.isMobile = isMobile()
            posthog.capture('palette command executed', cleanedResult)
        },
        deregisterScope: ({ scope }) => {
            for (const command of Object.values(values.commandRegistrations)) {
                if (command.scope === scope) {
                    actions.deregisterCommand(command.key)
                }
            }
        },
        setInput: async ({ input }, breakpoint) => {
            await breakpoint(300)
            if (input.length > 8) {
                const response = await api.get('api/person/?key_identifier=' + encodeURIComponent(input))
                const person = response.results[0]
                if (person) {
                    actions.registerCommand({
                        key: `person-${person.distinct_ids[0]}`,
                        resolver: [
                            {
                                icon: UserOutlined,
                                display: `View person ${input}`,
                                executor: () => {
                                    const { push } = router.actions
                                    push(urls.person(person.distinct_ids[0]))
                                },
                            },
                        ],
                        scope: GLOBAL_COMMAND_SCOPE,
                    })
                }
            }
        },
    }),
    selectors: {
        isSqueak: [
            (selectors) => [selectors.input],
            (input: string) => {
                return input.trim().toLowerCase() === 'squeak'
            },
        ],
        activeResultIndex: [
            (selectors) => [selectors.keyboardResultIndex, selectors.hoverResultIndex],
            (keyboardResultIndex: number, hoverResultIndex: number | null) => {
                return hoverResultIndex ?? keyboardResultIndex
            },
        ],
        commandRegistrations: [
            (selectors) => [
                selectors.rawCommandRegistrations,
                dashboardsModel.selectors.nameSortedDashboards,
                teamLogic.selectors.currentTeam,
            ],
            (rawCommandRegistrations: CommandRegistrations, dashboards: DashboardType[]): CommandRegistrations => ({
                ...rawCommandRegistrations,
                custom_dashboards: {
                    key: 'custom_dashboards',
                    resolver: dashboards.map((dashboard: DashboardType) => ({
                        key: `dashboard_${dashboard.id}`,
                        icon: LineChartOutlined,
                        display: `Go to Dashboard: ${dashboard.name}`,
                        executor: () => {
                            const { push } = router.actions
                            push(urls.dashboard(dashboard.id))
                        },
                    })),
                    scope: GLOBAL_COMMAND_SCOPE,
                },
            }),
        ],
        regexpCommandPairs: [
            (selectors) => [selectors.commandRegistrations],
            (commandRegistrations: CommandRegistrations) => {
                const array: RegExpCommandPairs = []
                for (const command of Object.values(commandRegistrations)) {
                    if (command.prefixes) {
                        array.push([new RegExp(`^\\s*(${command.prefixes.join('|')})(?:\\s+(.*)|$)`, 'i'), command])
                    } else {
                        array.push([null, command])
                    }
                }
                return array
            },
        ],
        commandSearchResults: [
            (selectors) => [
                selectors.isPaletteShown,
                selectors.regexpCommandPairs,
                selectors.input,
                selectors.activeFlow,
                selectors.isSqueak,
            ],
            (
                isPaletteShown: boolean,
                regexpCommandPairs: RegExpCommandPairs,
                argument: string,
                activeFlow: CommandFlow | null,
                isSqueak: boolean
            ) => {
                if (!isPaletteShown || isSqueak) {
                    return []
                }
                if (activeFlow) {
                    return resolveCommand(activeFlow, argument)
                }
                let directResults: CommandResult[] = []
                let prefixedResults: CommandResult[] = []
                for (const [regexp, command] of regexpCommandPairs) {
                    if (regexp) {
                        const match = argument.match(regexp)
                        if (match && match[1]) {
                            prefixedResults = [...prefixedResults, ...resolveCommand(command, match[2], match[1])]
                        }
                    }
                    directResults = [...directResults, ...resolveCommand(command, argument)]
                }
                const allResults = directResults.concat(prefixedResults)
                let fusableResults: CommandResult[] = []
                let guaranteedResults: CommandResult[] = []
                for (const result of allResults) {
                    if (result.guarantee) {
                        guaranteedResults.push(result)
                    } else {
                        fusableResults.push(result)
                    }
                }
                fusableResults = uniqueBy(fusableResults, (result) => result.display)
                guaranteedResults = uniqueBy(guaranteedResults, (result) => result.display)
                const fusedResults = argument
                    ? new Fuse(fusableResults, {
                          keys: ['display', 'synonyms'],
                      })
                          .search(argument)
                          .slice(0, RESULTS_MAX)
                          .map((result) => result.item)
                    : sample(fusableResults, RESULTS_MAX - guaranteedResults.length)
                return guaranteedResults.concat(fusedResults)
            },
        ],
        commandSearchResultsGrouped: [
            (selectors) => [selectors.commandSearchResults, selectors.activeFlow],
            (commandSearchResults: CommandResult[], activeFlow: CommandFlow | null) => {
                const resultsGrouped: {
                    [scope: string]: CommandResult[]
                } = {}
                if (activeFlow) {
                    resultsGrouped[activeFlow.scope ?? '?'] = []
                }
                for (const result of commandSearchResults) {
                    const scope: string = result.source.scope ?? '?'
                    if (!(scope in resultsGrouped)) {
                        resultsGrouped[scope] = []
                    } // Ensure there's an array to push to
                    resultsGrouped[scope].push({ ...result })
                }
                let rollingGroupIndex = 0
                let rollingResultIndex = 0
                const resultsGroupedInOrder: [string, CommandResultDisplayable[]][] = []
                for (const [group, results] of Object.entries(resultsGrouped)) {
                    resultsGroupedInOrder.push([group, []])
                    for (const result of results) {
                        resultsGroupedInOrder[rollingGroupIndex][1].push({ ...result, index: rollingResultIndex++ })
                    }
                    rollingGroupIndex++
                }
                return resultsGroupedInOrder
            },
        ],
    },

    events: ({ actions }) => ({
        afterMount: () => {
            const { push } = router.actions

            const goTo: Command = {
                key: 'go-to',
                scope: GLOBAL_COMMAND_SCOPE,
                prefixes: ['open', 'visit'],
                resolver: [
                    {
                        icon: FundOutlined,
                        display: 'Go to Dashboards',
                        executor: () => {
                            push(urls.dashboards())
                        },
                    },
                    {
                        icon: RiseOutlined,
                        display: 'Go to Insights',
                        executor: () => {
                            push(urls.savedInsights())
                        },
                    },
                    {
                        icon: RiseOutlined,
                        display: 'Go to Trends',
                        executor: () => {
                            // TODO: Don't reset insight on change
                            push(urls.insightNew({ insight: InsightType.TRENDS }))
                        },
                    },
                    {
                        icon: FunnelPlotOutlined,
                        display: 'Go to Funnels',
                        executor: () => {
                            // TODO: Don't reset insight on change
                            push(urls.insightNew({ insight: InsightType.FUNNELS }))
                        },
                    },
                    {
                        icon: GatewayOutlined,
                        display: 'Go to Retention',
                        executor: () => {
                            // TODO: Don't reset insight on change
                            push(urls.insightNew({ insight: InsightType.RETENTION }))
                        },
                    },
                    {
                        icon: InteractionOutlined,
                        display: 'Go to Paths',
                        executor: () => {
                            // TODO: Don't reset insight on change
                            push(urls.insightNew({ insight: InsightType.PATHS }))
                        },
                    },
                    {
                        icon: ContainerOutlined,
                        display: 'Go to Events',
                        executor: () => {
                            push(urls.events())
                        },
                    },
                    {
                        icon: AimOutlined,
                        display: 'Go to Actions',
                        executor: () => {
                            push(urls.actions())
                        },
                    },
                    {
                        icon: UserOutlined,
                        display: 'Go to Persons',
                        synonyms: ['people'],
                        executor: () => {
                            push(urls.persons())
                        },
                    },
                    {
                        icon: UsergroupAddOutlined,
                        display: 'Go to Cohorts',
                        executor: () => {
                            push(urls.cohorts())
                        },
                    },
                    {
                        icon: FlagOutlined,
                        display: 'Go to Feature Flags',
                        synonyms: ['feature flags', 'a/b tests'],
                        executor: () => {
                            push(urls.featureFlags())
                        },
                    },
                    {
                        icon: MessageOutlined,
                        display: 'Go to Annotations',
                        executor: () => {
                            push(urls.annotations())
                        },
                    },
                    {
                        icon: TeamOutlined,
                        display: 'Go to Team members',
                        synonyms: ['organization', 'members', 'invites', 'teammates'],
                        executor: () => {
                            push(urls.organizationSettings())
                        },
                    },
                    {
                        icon: ProjectOutlined,
                        display: 'Go to Project settings',
                        executor: () => {
                            push(urls.projectSettings())
                        },
                    },
                    {
                        icon: SmileOutlined,
                        display: 'Go to My settings',
                        synonyms: ['account'],
                        executor: () => {
                            push(urls.mySettings())
                        },
                    },
                    {
                        icon: ApiOutlined,
                        display: 'Go to Plugins',
                        synonyms: ['integrations'],
                        executor: () => {
                            push(urls.plugins())
                        },
                    },
                    {
                        icon: DatabaseOutlined,
                        display: 'Go to System status page',
                        synonyms: ['redis', 'celery', 'django', 'postgres', 'backend', 'service', 'online'],
                        executor: () => {
                            push(urls.systemStatus())
                        },
                    },
                    {
                        icon: PlusOutlined,
                        display: 'Create action',
                        executor: () => {
                            push(urls.createAction())
                        },
                    },
                    {
                        icon: LogoutOutlined,
                        display: 'Log out',
                        executor: () => {
                            userLogic.actions.logout()
                        },
                    },
                ],
            }

            const debugClickhouseQueries: Command = {
                key: 'debug-clickhouse-queries',
                scope: GLOBAL_COMMAND_SCOPE,
                resolver:
                    userLogic.values.user?.is_staff ||
                    userLogic.values.user?.is_impersonated ||
                    preflightLogic.values.preflight?.is_debug ||
                    preflightLogic.values.preflight?.instance_preferences?.debug_queries
                        ? {
                              icon: PlusOutlined,
                              display: 'Debug queries (ClickHouse)',
                              executor: () => {
                                  debugCHQueries()
                              },
                          }
                        : [],
            }

            const calculator: Command = {
                key: 'calculator',
                scope: GLOBAL_COMMAND_SCOPE,
                resolver: (argument) => {
                    // don't try evaluating if there's no argument or if it's a plain number already
                    if (!argument || !isNaN(+argument)) {
                        return null
                    }
                    try {
                        const result = +Parser.evaluate(argument)
                        return isNaN(result)
                            ? null
                            : {
                                  icon: CalculatorOutlined,
                                  display: `= ${result}`,
                                  guarantee: true,
                                  executor: () => {
                                      copyToClipboard(result.toString(), 'calculation result')
                                  },
                              }
                    } catch {
                        return null
                    }
                },
            }

            const openUrls: Command = {
                key: 'open-urls',
                scope: GLOBAL_COMMAND_SCOPE,
                prefixes: ['open', 'visit'],
                resolver: (argument) => {
                    const results: CommandResultTemplate[] = (teamLogic.values.currentTeam?.app_urls ?? []).map(
                        (url: string) => ({
                            icon: LinkOutlined,
                            display: `Open ${url}`,
                            synonyms: [`Visit ${url}`],
                            executor: () => {
                                open(url)
                            },
                        })
                    )
                    if (argument && isURL(argument)) {
                        results.push({
                            icon: LinkOutlined,
                            display: `Open ${argument}`,
                            synonyms: [`Visit ${argument}`],
                            executor: () => {
                                open(argument)
                            },
                        })
                    }
                    results.push({
                        icon: LinkOutlined,
                        display: 'Open PostHog Docs',
                        synonyms: ['technical documentation'],
                        executor: () => {
                            open('https://posthog.com/docs')
                        },
                    })
                    return results
                },
            }

            const createPersonalApiKey: Command = {
                key: 'create-personal-api-key',
                scope: GLOBAL_COMMAND_SCOPE,
                resolver: {
                    icon: KeyOutlined,
                    display: 'Create Personal API Key',
                    executor: () => ({
                        instruction: 'Give your key a label',
                        icon: TagOutlined,
                        scope: 'Creating Personal API Key',
                        resolver: (argument) => {
                            if (argument?.length) {
                                return {
                                    icon: KeyOutlined,
                                    display: `Create Key "${argument}"`,
                                    executor: () => {
                                        personalAPIKeysLogic.actions.createKey(argument)
                                        push(urls.mySettings(), {}, 'personal-api-keys')
                                    },
                                }
                            }
                            return null
                        },
                    }),
                },
            }

            const createDashboard: Command = {
                key: 'create-dashboard',
                scope: GLOBAL_COMMAND_SCOPE,
                resolver: {
                    icon: FundOutlined,
                    display: 'Create Dashboard',
                    executor: () => ({
                        instruction: 'Name your new dashboard',
                        icon: TagOutlined,
                        scope: 'Creating Dashboard',
                        resolver: (argument) => {
                            if (argument?.length) {
                                return {
                                    icon: FundOutlined,
                                    display: `Create Dashboard "${argument}"`,
                                    executor: () => {
                                        dashboardsModel.actions.addDashboard({ name: argument, show: true })
                                    },
                                }
                            }
                            return null
                        },
                    }),
                },
            }

            const shareFeedback: Command = {
                key: 'share-feedback',
                scope: GLOBAL_COMMAND_SCOPE,
                resolver: {
                    icon: CommentOutlined,
                    display: 'Share Feedback',
                    synonyms: ['send opinion', 'ask question', 'message posthog', 'github issue'],
                    executor: () => ({
                        scope: 'Sharing Feedback',
                        resolver: [
                            {
                                display: 'Send Message Directly to PostHog',
                                icon: CommentOutlined,
                                executor: () => ({
                                    instruction: "What's on your mind?",
                                    icon: CommentOutlined,
                                    resolver: (argument) => ({
                                        icon: SendOutlined,
                                        display: 'Send',
                                        executor: !argument?.length
                                            ? undefined
                                            : () => {
                                                  posthog.capture('palette feedback', { message: argument })
                                                  return {
                                                      resolver: {
                                                          icon: CheckOutlined,
                                                          display: 'Message Sent!',
                                                          executor: true,
                                                      },
                                                  }
                                              },
                                    }),
                                }),
                            },
                            {
                                icon: VideoCameraOutlined,
                                display: 'Schedule Quick Call',
                                executor: () => {
                                    open('https://calendly.com/posthog-feedback')
                                },
                            },
                            {
                                icon: ExclamationCircleOutlined,
                                display: 'Create GitHub Issue',
                                executor: () => {
                                    open('https://github.com/PostHog/posthog/issues/new/choose')
                                },
                            },
                        ],
                    }),
                },
            }

            actions.registerCommand(goTo)
            actions.registerCommand(openUrls)
            actions.registerCommand(debugClickhouseQueries)
            actions.registerCommand(calculator)
            actions.registerCommand(createPersonalApiKey)
            actions.registerCommand(createDashboard)
            actions.registerCommand(shareFeedback)
        },
        beforeUnmount: () => {
            actions.deregisterCommand('go-to')
            actions.deregisterCommand('open-urls')
            actions.deregisterCommand('debug-clickhouse-queries')
            actions.deregisterCommand('calculator')
            actions.deregisterCommand('create-personal-api-key')
            actions.deregisterCommand('create-dashboard')
            actions.deregisterCommand('share-feedback')
        },
    }),
})
Example #3
Source File: OnboardingSetup.tsx    From posthog-foss with MIT License 4 votes vote down vote up
export function OnboardingSetup(): JSX.Element {
    const {
        stepProjectSetup,
        stepInstallation,
        projectModalShown,
        stepVerification,
        currentSection,
        teamInviteAvailable,
        progressPercentage,
        slackCalled,
    } = useValues(onboardingSetupLogic)
    const { switchToNonDemoProject, setProjectModalShown, completeOnboarding, callSlack } =
        useActions(onboardingSetupLogic)
    const { showInviteModal } = useActions(inviteLogic)

    const { currentTeam, currentTeamLoading } = useValues(teamLogic)
    const { updateCurrentTeam } = useActions(teamLogic)
    const { currentOrganizationLoading } = useValues(organizationLogic)

    const UTM_TAGS = 'utm_medium=in-product&utm_campaign=onboarding-setup-2822'

    return (
        <div className="onboarding-setup">
            {currentSection ? (
                <>
                    <Row gutter={16}>
                        <Col span={18}>
                            <PageHeader
                                title="Setup"
                                caption="Get your PostHog instance up and running with all the bells and whistles"
                            />
                        </Col>
                        <Col span={6} style={{ display: 'flex', alignItems: 'center' }}>
                            <Progress percent={progressPercentage} strokeColor="var(--purple)" strokeWidth={16} />
                        </Col>
                    </Row>

                    <Collapse defaultActiveKey={currentSection} expandIconPosition="right" accordion>
                        <Panel
                            header={
                                <PanelHeader
                                    title="Event Ingestion"
                                    caption="First things first, you need to connect PostHog to your website. You’ll be able to add more sources later."
                                    stepNumber={1}
                                />
                            }
                            key="1"
                        >
                            <div className="step-list">
                                <OnboardingStep
                                    label="Set up project"
                                    icon={<ProjectOutlined />}
                                    title="Step 1"
                                    identifier="set-up-project"
                                    completed={stepProjectSetup}
                                    handleClick={() => setProjectModalShown(true)}
                                />
                                <OnboardingStep
                                    label="Install PostHog"
                                    icon={<CodeOutlined />}
                                    title="Step 2"
                                    identifier="install-posthog"
                                    disabled={!stepProjectSetup}
                                    completed={stepInstallation}
                                    handleClick={() => switchToNonDemoProject('/ingestion')}
                                />
                                <OnboardingStep
                                    label="Verify your events"
                                    icon={<CheckOutlined />}
                                    title="Step 3"
                                    identifier="verify-events"
                                    disabled={!stepProjectSetup || !stepInstallation}
                                    completed={stepVerification}
                                    handleClick={() => switchToNonDemoProject('/ingestion/verify')}
                                />
                            </div>
                        </Panel>
                        <Panel
                            header={
                                <PanelHeader
                                    title="Configuration"
                                    caption="Tune the settings of PostHog to make sure it works best for you and your team."
                                    stepNumber={2}
                                />
                            }
                            key="2"
                            collapsible={currentSection < 2 ? 'disabled' : undefined}
                        >
                            <div className="step-list">
                                <OnboardingStep
                                    title="Enable session recording"
                                    icon={<PlaySquareOutlined />}
                                    identifier="session-recording"
                                    handleClick={() =>
                                        updateCurrentTeam({
                                            session_recording_opt_in: !currentTeam?.session_recording_opt_in,
                                        })
                                    }
                                    caption={
                                        <>
                                            Play user interactions as if you were right there with them.{' '}
                                            <Link
                                                to={`https://posthog.com/docs/features/session-recording?${UTM_TAGS}`}
                                                rel="noopener"
                                                target="_blank"
                                            >
                                                Learn more
                                            </Link>
                                            .
                                        </>
                                    }
                                    customActionElement={
                                        <div style={{ fontWeight: 'bold' }}>
                                            {currentTeam?.session_recording_opt_in ? (
                                                <span style={{ color: 'var(--success)' }}>Enabled</span>
                                            ) : (
                                                <span style={{ color: 'var(--danger)' }}>Disabled</span>
                                            )}
                                            <Switch
                                                checked={currentTeam?.session_recording_opt_in}
                                                loading={currentTeamLoading}
                                                style={{ marginLeft: 6 }}
                                            />
                                        </div>
                                    }
                                    analyticsExtraArgs={{
                                        new_session_recording_enabled: !currentTeam?.session_recording_opt_in,
                                    }}
                                />
                                <OnboardingStep
                                    title="Join us on Slack"
                                    icon={<SlackOutlined />}
                                    identifier="slack"
                                    handleClick={() => {
                                        callSlack()
                                        window.open(`https://posthog.com/slack?s=app&${UTM_TAGS}`, '_blank')
                                    }}
                                    caption="Fastest way to reach the PostHog team and the community."
                                    customActionElement={
                                        <Button type={slackCalled ? 'default' : 'primary'} icon={<SlackOutlined />}>
                                            Join us
                                        </Button>
                                    }
                                />
                                {teamInviteAvailable && (
                                    <OnboardingStep
                                        title="Invite your team members"
                                        icon={<UsergroupAddOutlined />}
                                        identifier="invite-team"
                                        handleClick={showInviteModal}
                                        caption="Spread the knowledge, share insights with everyone in your team."
                                        customActionElement={
                                            <Button type="primary" icon={<PlusOutlined />}>
                                                Invite my team
                                            </Button>
                                        }
                                    />
                                )}
                            </div>
                            <div className="text-center" style={{ marginTop: 32 }}>
                                <Button
                                    type="default"
                                    onClick={completeOnboarding}
                                    loading={currentOrganizationLoading}
                                    data-attr="onboarding-setup-complete"
                                >
                                    Finish setup
                                </Button>
                            </div>
                        </Panel>
                    </Collapse>
                    <CreateProjectModal
                        isVisible={projectModalShown}
                        onClose={() => setProjectModalShown(false)}
                        title="Set up your first project"
                        caption={
                            <div className="mb">
                                <div>
                                    Enter a <b>name</b> for your first project
                                </div>
                                <div className="text-muted">
                                    It's helpful to separate your different apps in multiple projects. Read more about
                                    our recommendations and{' '}
                                    <Link
                                        to={`https://posthog.com/docs/features/organizations?${UTM_TAGS}`}
                                        rel="noopener"
                                        target="_blank"
                                    >
                                        best practices <IconOpenInNew />
                                    </Link>
                                </div>
                            </div>
                        }
                    />
                </>
            ) : (
                <div className="already-completed">
                    <CheckCircleOutlined className="completed-icon" />{' '}
                    <h2 className="">Your organization is set up!</h2>
                    <div className="text-muted">
                        Looks like your organization is good to go. If you still need some help, check out{' '}
                        <Link
                            to={`https://posthog.com/docs?${UTM_TAGS}&utm_message=onboarding-completed`}
                            target="_blank"
                        >
                            our docs <IconOpenInNew />
                        </Link>
                    </div>
                    <div style={{ marginTop: 32 }}>
                        <LinkButton type="primary" to="/" data-attr="onbording-completed-insights">
                            Go to insights <ArrowRightOutlined />
                        </LinkButton>
                    </div>
                </div>
            )}
        </div>
    )
}
Example #4
Source File: PersonsModal.tsx    From posthog-foss with MIT License 4 votes vote down vote up
export function PersonsModal({
    visible,
    view,
    filters,
    onSaveCohort,
    showModalActions = true,
    aggregationTargetLabel,
}: PersonsModalProps): JSX.Element {
    const {
        people,
        loadingMorePeople,
        firstLoadedPeople,
        searchTerm,
        isInitialLoad,
        clickhouseFeaturesEnabled,
        peopleParams,
        actorLabel,
        sessionRecordingId,
    } = useValues(personsModalLogic)
    const {
        hidePeople,
        loadMorePeople,
        setFirstLoadedActors,
        setPersonsModalFilters,
        setSearchTerm,
        switchToDataPoint,
        openRecordingModal,
        closeRecordingModal,
    } = useActions(personsModalLogic)
    const { preflight } = useValues(preflightLogic)
    const { featureFlags } = useValues(featureFlagLogic)

    const title = useMemo(
        () =>
            isInitialLoad ? (
                `Loading ${aggregationTargetLabel.plural}…`
            ) : filters.shown_as === 'Stickiness' ? (
                <>
                    <PropertyKeyInfo value={people?.label || ''} disablePopover /> stickiness on day {people?.day}
                </>
            ) : filters.display === 'ActionsBarValue' || filters.display === 'ActionsPie' ? (
                <PropertyKeyInfo value={people?.label || ''} disablePopover />
            ) : filters.insight === InsightType.FUNNELS ? (
                <>
                    {(people?.funnelStep ?? 0) >= 0 ? 'Completed' : 'Dropped off at'} step{' '}
                    {Math.abs(people?.funnelStep ?? 0)} • <PropertyKeyInfo value={people?.label || ''} disablePopover />{' '}
                    {!!people?.breakdown_value ? `• ${people.breakdown_value}` : ''}
                </>
            ) : filters.insight === InsightType.PATHS ? (
                <>
                    {people?.pathsDropoff ? 'Dropped off after' : 'Completed'} step{' '}
                    <PropertyKeyInfo value={people?.label.replace(/(^[0-9]+_)/, '') || ''} disablePopover />
                </>
            ) : (
                <>
                    {capitalizeFirstLetter(actorLabel)} list on{' '}
                    <DateDisplay interval={filters.interval || 'day'} date={people?.day?.toString() || ''} />
                </>
            ),
        [filters, people, isInitialLoad]
    )

    const flaggedInsights = featureFlags[FEATURE_FLAGS.NEW_INSIGHT_COHORTS]
    const isDownloadCsvAvailable: boolean = view === InsightType.TRENDS && showModalActions && !!people?.action
    const isSaveAsCohortAvailable =
        clickhouseFeaturesEnabled &&
        (view === InsightType.TRENDS ||
            view === InsightType.STICKINESS ||
            (!!flaggedInsights && (view === InsightType.FUNNELS || view === InsightType.PATHS))) && // make sure flaggedInsights isn't evaluated as undefined
        showModalActions

    const colorList = getChartColors('white', people?.crossDataset?.length)
    const showCountedByTag = !!people?.crossDataset?.find(({ action }) => action?.math && action.math !== 'total')
    const hasMultipleSeries = !!people?.crossDataset?.find(({ action }) => action?.order)
    return (
        <>
            {!!sessionRecordingId && <SessionPlayerDrawer onClose={closeRecordingModal} />}
            <Modal
                title={title}
                visible={visible}
                onCancel={hidePeople}
                footer={
                    people &&
                    people.count > 0 &&
                    (isDownloadCsvAvailable || isSaveAsCohortAvailable) && (
                        <>
                            {isDownloadCsvAvailable && (
                                <Button
                                    icon={<DownloadOutlined />}
                                    href={api.actions.determinePeopleCsvUrl(
                                        {
                                            label: people.label,
                                            action: people.action,
                                            date_from: people.day,
                                            date_to: people.day,
                                            breakdown_value: people.breakdown_value,
                                        },
                                        filters
                                    )}
                                    style={{ marginRight: 8 }}
                                    data-attr="person-modal-download-csv"
                                >
                                    Download CSV
                                </Button>
                            )}
                            {isSaveAsCohortAvailable && (
                                <Button
                                    onClick={onSaveCohort}
                                    icon={<UsergroupAddOutlined />}
                                    data-attr="person-modal-save-as-cohort"
                                >
                                    Save as cohort
                                </Button>
                            )}
                        </>
                    )
                }
                width={600}
                className="person-modal"
            >
                {isInitialLoad ? (
                    <div style={{ padding: 16 }}>
                        <Skeleton active />
                    </div>
                ) : (
                    people && (
                        <>
                            {!preflight?.is_clickhouse_enabled && (
                                <Input.Search
                                    allowClear
                                    enterButton
                                    placeholder="Search for persons by email, name, or ID"
                                    onChange={(e) => {
                                        setSearchTerm(e.target.value)
                                        if (!e.target.value) {
                                            setFirstLoadedActors(firstLoadedPeople)
                                        }
                                    }}
                                    value={searchTerm}
                                    onSearch={(term) =>
                                        term
                                            ? setPersonsModalFilters(term, people, filters)
                                            : setFirstLoadedActors(firstLoadedPeople)
                                    }
                                />
                            )}
                            {featureFlags[FEATURE_FLAGS.MULTI_POINT_PERSON_MODAL] &&
                                !!people.crossDataset?.length &&
                                people.seriesId !== undefined && (
                                    <div className="data-point-selector">
                                        <Select value={people.seriesId} onChange={(_id) => switchToDataPoint(_id)}>
                                            {people.crossDataset.map((dataPoint) => (
                                                <Select.Option
                                                    value={dataPoint.id}
                                                    key={`${dataPoint.action?.id}${dataPoint.breakdown_value}`}
                                                >
                                                    <InsightLabel
                                                        seriesColor={colorList[dataPoint.id]}
                                                        action={dataPoint.action}
                                                        breakdownValue={
                                                            dataPoint.breakdown_value === ''
                                                                ? 'None'
                                                                : dataPoint.breakdown_value?.toString()
                                                        }
                                                        showCountedByTag={showCountedByTag}
                                                        hasMultipleSeries={hasMultipleSeries}
                                                    />
                                                </Select.Option>
                                            ))}
                                        </Select>
                                    </div>
                                )}
                            <div className="user-count-subheader">
                                <IconPersonFilled style={{ fontSize: '1.125rem', marginRight: '0.5rem' }} />
                                <span>
                                    This list contains{' '}
                                    <b>
                                        {people.count} unique {aggregationTargetLabel.plural}
                                    </b>
                                    {peopleParams?.pointValue !== undefined &&
                                        (!peopleParams.action?.math || peopleParams.action?.math === 'total') && (
                                            <>
                                                {' '}
                                                who performed the event{' '}
                                                <b>
                                                    {peopleParams.pointValue} total{' '}
                                                    {pluralize(peopleParams.pointValue, 'time', undefined, false)}
                                                </b>
                                            </>
                                        )}
                                    .
                                </span>
                            </div>
                            {people.count > 0 ? (
                                <LemonTable
                                    columns={
                                        [
                                            {
                                                title: 'Person',
                                                key: 'person',
                                                render: function Render(_, actor: ActorType) {
                                                    return <ActorRow actor={actor} />
                                                },
                                            },
                                            {
                                                width: 0,
                                                title: 'Recordings',
                                                key: 'recordings',
                                                render: function Render(_, actor: ActorType) {
                                                    if (
                                                        actor.matched_recordings?.length &&
                                                        actor.matched_recordings?.length > 0
                                                    ) {
                                                        return (
                                                            <MultiRecordingButton
                                                                sessionRecordings={actor.matched_recordings}
                                                                onOpenRecording={(sessionRecording) => {
                                                                    openRecordingModal(sessionRecording.session_id)
                                                                }}
                                                            />
                                                        )
                                                    }
                                                },
                                            },
                                        ] as LemonTableColumns<ActorType>
                                    }
                                    className="persons-table"
                                    rowKey="id"
                                    expandable={{
                                        expandedRowRender: function RenderPropertiesTable({ properties }) {
                                            return Object.keys(properties).length ? (
                                                <PropertiesTable properties={properties} />
                                            ) : (
                                                'This person has no properties.'
                                            )
                                        },
                                    }}
                                    embedded
                                    showHeader={false}
                                    dataSource={people.people}
                                    nouns={['person', 'persons']}
                                />
                            ) : (
                                <div className="person-row-container person-row">
                                    We couldn't find any matching {aggregationTargetLabel.plural} for this data point.
                                </div>
                            )}
                            {people?.next && (
                                <div
                                    style={{
                                        margin: '1rem',
                                        textAlign: 'center',
                                    }}
                                >
                                    <Button
                                        type="primary"
                                        style={{ color: 'white' }}
                                        onClick={loadMorePeople}
                                        loading={loadingMorePeople}
                                    >
                                        Load more {aggregationTargetLabel.plural}
                                    </Button>
                                </div>
                            )}
                        </>
                    )
                )}
            </Modal>
        </>
    )
}
Example #5
Source File: Icon.tsx    From html2sketch with MIT License 4 votes vote down vote up
IconSymbol: FC = () => {
  return (
    <Row>
      {/*<CaretUpOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/1.CaretUpOutlined'}*/}
      {/*/>*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.MailOutlined'}*/}
      {/*/>*/}
      {/*<StepBackwardOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.StepBackwardOutlined'}*/}
      {/*/>*/}
      {/*<StepForwardOutlined*/}
      {/*  className="icon"*/}
      {/*  symbolName={'1.General/2.Icons/2.StepBackwardOutlined'}*/}
      {/*/>*/}
      <StepForwardOutlined />
      <ShrinkOutlined />
      <ArrowsAltOutlined />
      <DownOutlined />
      <UpOutlined />
      <LeftOutlined />
      <RightOutlined />
      <CaretUpOutlined />
      <CaretDownOutlined />
      <CaretLeftOutlined />
      <CaretRightOutlined />
      <VerticalAlignTopOutlined />
      <RollbackOutlined />
      <FastBackwardOutlined />
      <FastForwardOutlined />
      <DoubleRightOutlined />
      <DoubleLeftOutlined />
      <VerticalLeftOutlined />
      <VerticalRightOutlined />
      <VerticalAlignMiddleOutlined />
      <VerticalAlignBottomOutlined />
      <ForwardOutlined />
      <BackwardOutlined />
      <EnterOutlined />
      <RetweetOutlined />
      <SwapOutlined />
      <SwapLeftOutlined />
      <SwapRightOutlined />
      <ArrowUpOutlined />
      <ArrowDownOutlined />
      <ArrowLeftOutlined />
      <ArrowRightOutlined />
      <LoginOutlined />
      <LogoutOutlined />
      <MenuFoldOutlined />
      <MenuUnfoldOutlined />
      <BorderBottomOutlined />
      <BorderHorizontalOutlined />
      <BorderInnerOutlined />
      <BorderOuterOutlined />
      <BorderLeftOutlined />
      <BorderRightOutlined />
      <BorderTopOutlined />
      <BorderVerticleOutlined />
      <PicCenterOutlined />
      <PicLeftOutlined />
      <PicRightOutlined />
      <RadiusBottomleftOutlined />
      <RadiusBottomrightOutlined />
      <RadiusUpleftOutlined />
      <RadiusUprightOutlined />
      <FullscreenOutlined />
      <FullscreenExitOutlined />
      <QuestionOutlined />
      <PauseOutlined />
      <MinusOutlined />
      <PauseCircleOutlined />
      <InfoOutlined />
      <CloseOutlined />
      <ExclamationOutlined />
      <CheckOutlined />
      <WarningOutlined />
      <IssuesCloseOutlined />
      <StopOutlined />
      <EditOutlined />
      <CopyOutlined />
      <ScissorOutlined />
      <DeleteOutlined />
      <SnippetsOutlined />
      <DiffOutlined />
      <HighlightOutlined />
      <AlignCenterOutlined />
      <AlignLeftOutlined />
      <AlignRightOutlined />
      <BgColorsOutlined />
      <BoldOutlined />
      <ItalicOutlined />
      <UnderlineOutlined />
      <StrikethroughOutlined />
      <RedoOutlined />
      <UndoOutlined />
      <ZoomInOutlined />
      <ZoomOutOutlined />
      <FontColorsOutlined />
      <FontSizeOutlined />
      <LineHeightOutlined />
      <SortAscendingOutlined />
      <SortDescendingOutlined />
      <DragOutlined />
      <OrderedListOutlined />
      <UnorderedListOutlined />
      <RadiusSettingOutlined />
      <ColumnWidthOutlined />
      <ColumnHeightOutlined />
      <AreaChartOutlined />
      <PieChartOutlined />
      <BarChartOutlined />
      <DotChartOutlined />
      <LineChartOutlined />
      <RadarChartOutlined />
      <HeatMapOutlined />
      <FallOutlined />
      <RiseOutlined />
      <StockOutlined />
      <BoxPlotOutlined />
      <FundOutlined />
      <SlidersOutlined />
      <AndroidOutlined />
      <AppleOutlined />
      <WindowsOutlined />
      <IeOutlined />
      <ChromeOutlined />
      <GithubOutlined />
      <AliwangwangOutlined />
      <DingdingOutlined />
      <WeiboSquareOutlined />
      <WeiboCircleOutlined />
      <TaobaoCircleOutlined />
      <Html5Outlined />
      <WeiboOutlined />
      <TwitterOutlined />
      <WechatOutlined />
      <AlipayCircleOutlined />
      <TaobaoOutlined />
      <SkypeOutlined />
      <FacebookOutlined />
      <CodepenOutlined />
      <CodeSandboxOutlined />
      <AmazonOutlined />
      <GoogleOutlined />
      <AlipayOutlined />
      <AntDesignOutlined />
      <AntCloudOutlined />
      <ZhihuOutlined />
      <SlackOutlined />
      <SlackSquareOutlined />
      <BehanceSquareOutlined />
      <DribbbleOutlined />
      <DribbbleSquareOutlined />
      <InstagramOutlined />
      <YuqueOutlined />
      <AlibabaOutlined />
      <YahooOutlined />
      <RedditOutlined />
      <SketchOutlined />
      <AccountBookOutlined />
      <AlertOutlined />
      <ApartmentOutlined />
      <ApiOutlined />
      <QqOutlined />
      <MediumWorkmarkOutlined />
      <GitlabOutlined />
      <MediumOutlined />
      <GooglePlusOutlined />
      <AppstoreAddOutlined />
      <AppstoreOutlined />
      <AudioOutlined />
      <AudioMutedOutlined />
      <AuditOutlined />
      <BankOutlined />
      <BarcodeOutlined />
      <BarsOutlined />
      <BellOutlined />
      <BlockOutlined />
      <BookOutlined />
      <BorderOutlined />
      <BranchesOutlined />
      <BuildOutlined />
      <BulbOutlined />
      <CalculatorOutlined />
      <CalendarOutlined />
      <CameraOutlined />
      <CarOutlined />
      <CarryOutOutlined />
      <CiCircleOutlined />
      <CiOutlined />
      <CloudOutlined />
      <ClearOutlined />
      <ClusterOutlined />
      <CodeOutlined />
      <CoffeeOutlined />
      <CompassOutlined />
      <CompressOutlined />
      <ContactsOutlined />
      <ContainerOutlined />
      <ControlOutlined />
      <CopyrightCircleOutlined />
      <CopyrightOutlined />
      <CreditCardOutlined />
      <CrownOutlined />
      <CustomerServiceOutlined />
      <DashboardOutlined />
      <DatabaseOutlined />
      <DeleteColumnOutlined />
      <DeleteRowOutlined />
      <DisconnectOutlined />
      <DislikeOutlined />
      <DollarCircleOutlined />
      <DollarOutlined />
      <DownloadOutlined />
      <EllipsisOutlined />
      <EnvironmentOutlined />
      <EuroCircleOutlined />
      <EuroOutlined />
      <ExceptionOutlined />
      <ExpandAltOutlined />
      <ExpandOutlined />
      <ExperimentOutlined />
      <ExportOutlined />
      <EyeOutlined />
      <FieldBinaryOutlined />
      <FieldNumberOutlined />
      <FieldStringOutlined />
      <DesktopOutlined />
      <DingtalkOutlined />
      <FileAddOutlined />
      <FileDoneOutlined />
      <FileExcelOutlined />
      <FileExclamationOutlined />
      <FileOutlined />
      <FileImageOutlined />
      <FileJpgOutlined />
      <FileMarkdownOutlined />
      <FilePdfOutlined />
      <FilePptOutlined />
      <FileProtectOutlined />
      <FileSearchOutlined />
      <FileSyncOutlined />
      <FileTextOutlined />
      <FileUnknownOutlined />
      <FileWordOutlined />
      <FilterOutlined />
      <FireOutlined />
      <FlagOutlined />
      <FolderAddOutlined />
      <FolderOutlined />
      <FolderOpenOutlined />
      <ForkOutlined />
      <FormatPainterOutlined />
      <FrownOutlined />
      <FunctionOutlined />
      <FunnelPlotOutlined />
      <GatewayOutlined />
      <GifOutlined />
      <GiftOutlined />
      <GlobalOutlined />
      <GoldOutlined />
      <GroupOutlined />
      <HddOutlined />
      <HeartOutlined />
      <HistoryOutlined />
      <HomeOutlined />
      <HourglassOutlined />
      <IdcardOutlined />
      <ImportOutlined />
      <InboxOutlined />
      <InsertRowAboveOutlined />
      <InsertRowBelowOutlined />
      <InsertRowLeftOutlined />
      <InsertRowRightOutlined />
      <InsuranceOutlined />
      <InteractionOutlined />
      <KeyOutlined />
      <LaptopOutlined />
      <LayoutOutlined />
      <LikeOutlined />
      <LineOutlined />
      <LinkOutlined />
      <Loading3QuartersOutlined />
      <LoadingOutlined />
      <LockOutlined />
      <MailOutlined />
      <ManOutlined />
      <MedicineBoxOutlined />
      <MehOutlined />
      <MenuOutlined />
      <MergeCellsOutlined />
      <MessageOutlined />
      <MobileOutlined />
      <MoneyCollectOutlined />
      <MonitorOutlined />
      <MoreOutlined />
      <NodeCollapseOutlined />
      <NodeExpandOutlined />
      <NodeIndexOutlined />
      <NotificationOutlined />
      <NumberOutlined />
      <PaperClipOutlined />
      <PartitionOutlined />
      <PayCircleOutlined />
      <PercentageOutlined />
      <PhoneOutlined />
      <PictureOutlined />
      <PoundCircleOutlined />
      <PoundOutlined />
      <PoweroffOutlined />
      <PrinterOutlined />
      <ProfileOutlined />
      <ProjectOutlined />
      <PropertySafetyOutlined />
      <PullRequestOutlined />
      <PushpinOutlined />
      <QrcodeOutlined />
      <ReadOutlined />
      <ReconciliationOutlined />
      <RedEnvelopeOutlined />
      <ReloadOutlined />
      <RestOutlined />
      <RobotOutlined />
      <RocketOutlined />
      <SafetyCertificateOutlined />
      <SafetyOutlined />
      <ScanOutlined />
      <ScheduleOutlined />
      <SearchOutlined />
      <SecurityScanOutlined />
      <SelectOutlined />
      <SendOutlined />
      <SettingOutlined />
      <ShakeOutlined />
      <ShareAltOutlined />
      <ShopOutlined />
      <ShoppingCartOutlined />
      <ShoppingOutlined />
      <SisternodeOutlined />
      <SkinOutlined />
      <SmileOutlined />
      <SolutionOutlined />
      <SoundOutlined />
      <SplitCellsOutlined />
      <StarOutlined />
      <SubnodeOutlined />
      <SyncOutlined />
      <TableOutlined />
      <TabletOutlined />
      <TagOutlined />
      <TagsOutlined />
      <TeamOutlined />
      <ThunderboltOutlined />
      <ToTopOutlined />
      <ToolOutlined />
      <TrademarkCircleOutlined />
      <TrademarkOutlined />
      <TransactionOutlined />
      <TrophyOutlined />
      <UngroupOutlined />
      <UnlockOutlined />
      <UploadOutlined />
      <UsbOutlined />
      <UserAddOutlined />
      <UserDeleteOutlined />
      <UserOutlined />
      <UserSwitchOutlined />
      <UsergroupAddOutlined />
      <UsergroupDeleteOutlined />
      <VideoCameraOutlined />
      <WalletOutlined />
      <WifiOutlined />
      <BorderlessTableOutlined />
      <WomanOutlined />
      <BehanceOutlined />
      <DropboxOutlined />
      <DeploymentUnitOutlined />
      <UpCircleOutlined />
      <DownCircleOutlined />
      <LeftCircleOutlined />
      <RightCircleOutlined />
      <UpSquareOutlined />
      <DownSquareOutlined />
      <LeftSquareOutlined />
      <RightSquareOutlined />
      <PlayCircleOutlined />
      <QuestionCircleOutlined />
      <PlusCircleOutlined />
      <PlusSquareOutlined />
      <MinusSquareOutlined />
      <MinusCircleOutlined />
      <InfoCircleOutlined />
      <ExclamationCircleOutlined />
      <CloseCircleOutlined />
      <CloseSquareOutlined />
      <CheckCircleOutlined />
      <CheckSquareOutlined />
      <ClockCircleOutlined />
      <FormOutlined />
      <DashOutlined />
      <SmallDashOutlined />
      <YoutubeOutlined />
      <CodepenCircleOutlined />
      <AliyunOutlined />
      <PlusOutlined />
      <LinkedinOutlined />
      <AimOutlined />
      <BugOutlined />
      <CloudDownloadOutlined />
      <CloudServerOutlined />
      <CloudSyncOutlined />
      <CloudUploadOutlined />
      <CommentOutlined />
      <ConsoleSqlOutlined />
      <EyeInvisibleOutlined />
      <FileGifOutlined />
      <DeliveredProcedureOutlined />
      <FieldTimeOutlined />
      <FileZipOutlined />
      <FolderViewOutlined />
      <FundProjectionScreenOutlined />
      <FundViewOutlined />
      <MacCommandOutlined />
      <PlaySquareOutlined />
      <OneToOneOutlined />
      <RotateLeftOutlined />
      <RotateRightOutlined />
      <SaveOutlined />
      <SwitcherOutlined />
      <TranslationOutlined />
      <VerifiedOutlined />
      <VideoCameraAddOutlined />
      <WhatsAppOutlined />

      {/*</Col>*/}
    </Row>
  );
}
Example #6
Source File: NavBarMobile.tsx    From foodie with MIT License 4 votes vote down vote up
NavBarMobile: React.FC<IProps> = ({ theme, isAuth, auth, openModal }) => {
    const [isOpenSearch, setOpenSearch] = useState(false);
    const [isOpenMenu, setOpenMenu] = useState(false);
    const { pathname } = useLocation();
    const history = useHistory();

    const onClickMenuItem = () => {
        setOpenMenu(false);
    }

    const clickSearchItemCallback = (user: IUser) => {
        setOpenSearch(false);
        history.push(`/user/${user.username}`);
    }

    return isOpenSearch ? (
        <div className="fixed top-0 left-0 flex w-full items-center bg-indigo-700 z-9999 py-2 pr-2 shadow-xl">
            <div
                className="p-2 rounded-full flex items-center justify-center cursor-pointer hover:bg-indigo-500"
                onClick={() => setOpenSearch(false)}
            >
                <ArrowLeftOutlined className="text-white" style={{ fontSize: '18px' }} />
            </div>
            <SearchInput
                clickItemCallback={clickSearchItemCallback}
                inputClassName="w-full"
            />
        </div>
    ) : (
        <nav className="contain flex justify-between z-9999 align-center w-100 border-b border-transparent bg-white dark:bg-indigo-1000 text-gray-700 h-60px py-2 fixed top-0 left-0 w-full shadow-md laptop:shadow-sm dark:border-gray-800">
            <div className="flex items-center space-x-8">
                {/* ---- LOGO -------- */}
                <Link
                    to={{
                        pathname: '/',
                        state: { from: pathname }
                    }}
                >
                    <img
                        src={logo}
                        alt=""
                        className="w-24"
                        style={{ filter: `brightness(${theme === 'dark' ? 3.5 : 1})` }}
                    />
                </Link>
            </div>
            {/* ---- NAVICONS FOR MOBILE ---- */}
            <div className="flex items-center space-x-4 laptop:hidden">
                {isAuth && (
                    <>
                        <div
                            className="p-2 rounded-full flex items-center justify-center cursor-pointer hover:bg-gray-200  dark:hover:bg-indigo-1100"
                        >
                            <Messages isAuth={isAuth} />
                        </div>
                        <div
                            className="p-2 rounded-full flex items-center justify-center cursor-pointer hover:bg-gray-200  dark:hover:bg-indigo-1100"
                        >
                            <Notification isAuth={isAuth} />
                        </div>
                    </>
                )}
                <div
                    className="p-2 rounded-full flex items-center justify-center cursor-pointer hover:bg-gray-200 dark:text-white dark:hover:bg-indigo-1100"
                    onClick={() => setOpenSearch(true)}
                >
                    <SearchOutlined style={{ fontSize: '20px' }} />
                </div>
                <div
                    className="p-2 rounded-full flex items-center justify-center cursor-pointer hover:bg-gray-200  dark:text-white dark:hover:bg-indigo-1100"
                    onClick={() => setOpenMenu(true)}
                >
                    <MenuOutlined style={{ fontSize: '20px' }} />
                </div>
            </div>
            {/* ---- NAV DRAWER FOR MOBILE --- */}
            <div className={`flex  flex-col w-full h-screen fixed top-0 right-0 transition-transform  transform ${isOpenMenu ? 'translate-x-0' : 'translate-x-full'} bg-white dark:bg-indigo-1000 laptop:hidden`}>
                <div className="flex items-center justify-between px-4">
                    <div className="flex items-center space-x-4">
                        <h1 className="dark:text-white">Menu</h1>
                        <ThemeToggler />
                    </div>
                    <div
                        className="p-2 rounded-full flex items-center justify-center cursor-pointer hover:bg-gray-200 dark:text-white dark:hover:bg-indigo-1100"
                        onClick={() => setOpenMenu(false)}
                    >
                        <CloseOutlined style={{ fontSize: '20px' }} />
                    </div>
                </div>
                {isAuth ? (
                    <ul className="divide-y divide-gray-100 dark:divide-gray-800">
                        <li className="px-4 py-3 pb-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100">
                            <Link
                                className="flex font-medium dark:text-indigo-400"
                                onClick={onClickMenuItem}
                                to={`/user/${auth.username}`}
                            >
                                <Avatar url={auth.profilePicture?.url} size="lg" className="mr-2" />
                                <div className="flex flex-col">
                                    <span>{auth.username}</span>
                                    <span className="text-gray-400 text-xs">View Profile</span>
                                </div>
                            </Link>
                        </li>
                        <li className="p-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100">
                            <Link
                                className="flex items-center text-black dark:text-white"
                                onClick={onClickMenuItem}
                                to={`/user/${auth.username}/following`}
                            >
                                <TeamOutlined className="text-indigo-700 dark:text-indigo-400" style={{ fontSize: '30px', marginRight: '25px' }} />
                                <h6 className="text-sm">Following</h6>
                            </Link>
                        </li>
                        <li className="p-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100">
                            <Link
                                className="flex items-center text-black dark:text-white"
                                onClick={onClickMenuItem}
                                to={`/user/${auth.username}/followers`}
                            >
                                <TeamOutlined className="text-indigo-700 dark:text-indigo-400" style={{ fontSize: '30px', marginRight: '25px' }} />
                                <h6 className="text-sm">Followers</h6>
                            </Link>
                        </li>
                        <li className="p-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100">
                            <Link
                                className="flex items-center text-black dark:text-white"
                                onClick={onClickMenuItem}
                                to={`/user/${auth.username}/bookmarks`}
                            >
                                <StarOutlined className="text-indigo-700 dark:text-indigo-400" style={{ fontSize: '30px', marginRight: '25px' }} />
                                <h6 className="text-sm">Bookmarks</h6>
                            </Link>
                        </li>
                        <li className="p-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100">
                            <Link
                                className="flex items-center text-black dark:text-white"
                                onClick={onClickMenuItem}
                                to={SUGGESTED_PEOPLE}
                            >
                                <UsergroupAddOutlined className="text-indigo-700 dark:text-indigo-400" style={{ fontSize: '30px', marginRight: '25px' }} />
                                <h6 className="text-sm">Suggested People</h6>
                            </Link>
                        </li>
                        <li className="p-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100">
                            <div
                                className="flex items-center text-black dark:text-white"
                                onClick={() => {
                                    openModal();
                                    setOpenMenu(false);
                                }}
                            >
                                <LogoutOutlined className="text-red-500" style={{ fontSize: '30px', marginRight: '25px' }} />
                                <h6 className="text-sm text-red-500">Logout</h6>
                            </div>
                        </li>
                    </ul>
                ) : (
                    <ul className="divide-y divide-gray-100 dark:divide-gray-800">
                        <li className="px-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100 flex items-center justify-start">
                            <ArrowRightOutlined className="dark:text-white" />
                            <Link
                                className="p-4 font-medium dark:text-indigo-400 flex-grow"
                                to={LOGIN}
                            >
                                Login
                                    </Link>
                        </li>
                        <li className="px-4 cursor-pointer hover:bg-indigo-100 dark:hover:bg-indigo-1100 flex items-center justify-start">
                            <ArrowRightOutlined className="dark:text-white" />
                            <Link
                                className="p-4 font-medium dark:text-indigo-400 flex-grow"
                                to={REGISTER}
                            >
                                Register
                                    </Link>
                        </li>
                    </ul>
                )}
                {/* --- COPYRIGHT -- */}
                <span className="text-gray-400 text-xs absolute bottom-8 left-0 right-0 mx-auto text-center">
                    &copy;Copyright {new Date().getFullYear()} Foodie
                    </span>
            </div>
        </nav>
    )
}
Example #7
Source File: index.tsx    From anew-server with MIT License 4 votes vote down vote up
HostList: React.FC = () => {
    const { initialState } = useModel('@@initialState');
    if (!initialState || !initialState.DictObj) {
        return null;
    }
    const authType: optionsType[] = initialState.DictObj.auth_type.map((item: any) => ({ label: item.dict_value, value: item.dict_key }));
    const hostType: optionsType[] = initialState.DictObj.host_type.map((item: any) => ({ label: item.dict_value, value: item.dict_key }));
    const [createVisible, setCreateVisible] = useState<boolean>(false);
    const [updateVisible, setUpdateVisible] = useState<boolean>(false);
    const [recordVisible, setRecordVisible] = useState<boolean>(false);
    const actionRef = useRef<ActionType>();
    const [formValues, setFormValues] = useState<API.HostList>();
    const [hostGroup, setHostGroup] = useState<API.HostGroupList[]>([]);
    const [group_id, setGroupId] = useState<string>();
    const [hostId, setHostId] = useState<number>();
    const access = useAccess();
    const { consoleWin, setConsoleWin } = useModel('global');

    const handleDelete = (record: API.Ids) => {
        if (!record) return;
        if (Array.isArray(record.ids) && !record.ids.length) return;
        const content = `您是否要删除这${Array.isArray(record.ids) ? record.ids.length : ''}项?`;
        Modal.confirm({
            title: '注意',
            content,
            onOk: () => {
                deleteHost(record).then((res) => {
                    if (res.code === 200 && res.status === true) {
                        message.success(res.message);
                        if (actionRef.current) {
                            actionRef.current.reload();
                        }
                    }
                });
            },
            onCancel() { },
        });
    };

    const saveTtys = (val: API.TtyList) => {
        let hosts = JSON.parse(localStorage.getItem('TABS_TTY_HOSTS') as string)
        if (hosts) {
            hosts.push(val)
        } else {
            hosts = []
            hosts.push(val)
        }
        localStorage.setItem('TABS_TTY_HOSTS', JSON.stringify(hosts));
    }

    useEffect(() => {
        queryHostGroups({ all: true, not_null: true }).then((res) => {
            if (Array.isArray(res.data.data)) {
                setHostGroup([{ id: 0, name: '所有主机' }, ...res.data.data]);
            }
        });
    }, []);

    const columns: ProColumns<API.HostList>[] = [
        {
            title: '主机名',
            dataIndex: 'host_name',
        },
        {
            title: '地址',
            dataIndex: 'ip_address',
        },
        {
            title: '端口',
            dataIndex: 'port',
        },
        {
            title: '主机类型',
            dataIndex: 'host_type',
            valueType: 'select',
            fieldProps: {
                options: hostType,
            },
        },
        {
            title: '认证类型',
            dataIndex: 'auth_type',
            valueType: 'select',
            fieldProps: {
                options: authType,
            },
        },
        {
            title: '创建人',
            dataIndex: 'creator',
        },
        {
            title: '操作',
            dataIndex: 'option',
            valueType: 'option',
            render: (_, record) => (
                <>
                    <Tooltip title="控制台">
                        <CodeTwoTone
                            style={{ fontSize: '17px', color: 'blue' }}
                            onClick={() => {
                                let actKey = "tty1"
                                let hosts = JSON.parse(localStorage.getItem('TABS_TTY_HOSTS') as string) || []
                                if (hosts) {
                                    actKey = "tty" + (hosts.length + 1).toString()
                                }
                                const hostsObj: API.TtyList = { hostname: record.host_name, ipaddr: record.ip_address, port: record.port, id: record.id.toString(), actKey: actKey, secKey: null }
                                saveTtys(hostsObj)
                                if (consoleWin) {
                                    if (!consoleWin.closed) {
                                        consoleWin.focus();
                                    } else {
                                        setConsoleWin(window.open('/asset/console', 'consoleTrm'));
                                    }
                                } else {
                                    setConsoleWin(window.open('/asset/console', 'consoleTrm'));
                                }
                            }}
                        />
                    </Tooltip>

                    {/* <Divider type="vertical" />
                <Tooltip title="详情">
                  <FileDoneOutlined
                    style={{ fontSize: '17px', color: '#52c41a' }}
                    onClick={() => {
                      setFormValues(record);
                      handleDescModalVisible(true);
                    }}
                  />
                </Tooltip> */}
                    <Divider type="vertical" />
                    <TableDropdown
                        key="actionGroup"
                        onSelect={(key) => {
                            switch (key) {
                                case 'delete':
                                    handleDelete({ ids: [record.id] });
                                    break;
                                case 'edit':
                                    setFormValues(record);
                                    setUpdateVisible(true);
                                    break;
                                case 'record':
                                    setHostId(record.id)
                                    setRecordVisible(true);
                                    break;
                            }
                        }}
                        menus={[
                            { key: 'edit', name: '修改' },
                            { key: 'record', name: '操作录像' },
                            { key: 'delete', name: '删除' },
                        ]}
                    />
                </>
            ),
        },
    ];

    return (
        <PageHeaderWrapper>
            {/* 权限控制显示内容 */}
            {access.hasPerms(['admin', 'host:list']) && <ProTable
                actionRef={actionRef}
                rowKey="id"
                toolBarRender={(action, { selectedRows }) => [
                    <Access accessible={access.hasPerms(['admin', 'host:create'])}>
                        <Button key="1" type="primary" onClick={() => setCreateVisible(true)}>
                            <PlusOutlined /> 新建
                        </Button>
                    </Access>,
                    selectedRows && selectedRows.length > 0 && (
                        <Access accessible={access.hasPerms(['admin', 'host:delete'])}>
                            <Button
                                key="2"
                                type="primary"
                                onClick={() => handleDelete({ ids: selectedRows.map((item) => item.id) })}
                                danger
                            >
                                <DeleteOutlined /> 删除
                            </Button>
                        </Access>
                    ),
                ]}
                tableAlertRender={({ selectedRowKeys, selectedRows }) => (
                    <div>
                        已选择{' '}
                        <a
                            style={{
                                fontWeight: 600,
                            }}
                        >
                            {selectedRowKeys.length}
                        </a>{' '}
                        项&nbsp;&nbsp;
                    </div>
                )}
                request={async (params) => queryHosts({ params }).then((res) => res.data)}
                params={{ group_id, }}
                columns={columns}
                rowSelection={{}}
                tableRender={(_, dom) => hostGroup.length > 1 ? (
                    <div style={{ display: 'flex', width: '100%', }}>
                        <Menu
                            onSelect={(e) => {
                                if (e.key === '0') {
                                    setGroupId('');
                                } else {
                                    setGroupId(e.key);
                                }
                            }}
                            style={{ width: 156 }}
                            defaultSelectedKeys={['0']}
                            defaultOpenKeys={['sub1']}
                            mode="inline"
                        >
                            <Menu.SubMenu
                                key="sub1"
                                title={
                                    <span>
                                        <UsergroupAddOutlined />
                                        <span>主机分组</span>
                                    </span>
                                }
                            >
                                {hostGroup &&
                                    hostGroup.map((item) => <Menu.Item key={item.id}>{item.name}</Menu.Item>)}
                            </Menu.SubMenu>
                        </Menu>
                        <div style={{ flex: 1, }}>
                            {dom}
                        </div>
                    </div>
                ) : <div style={{ flex: 1, }}>
                    {dom}
                </div>}
            />}
            {createVisible && (
                <CreateForm
                    actionRef={actionRef}
                    handleChange={setCreateVisible}
                    modalVisible={createVisible}
                />
            )}
            {updateVisible && (
                <UpdateForm
                    actionRef={actionRef}
                    handleChange={setUpdateVisible}
                    modalVisible={updateVisible}
                    values={formValues}
                />
            )}
            {recordVisible && (
                <RecordModal
                    handleChange={setRecordVisible}
                    modalVisible={recordVisible}
                    hostId={hostId}
                />
            )}
        </PageHeaderWrapper>
    );
}