@ant-design/icons#StopOutlined TypeScript Examples

The following examples show how to use @ant-design/icons#StopOutlined. 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: PasswordResetComplete.tsx    From posthog-foss with MIT License 6 votes vote down vote up
export function PasswordResetComplete(): JSX.Element {
    const { validatedResetToken, validatedResetTokenLoading } = useValues(passwordResetLogic)
    const invalidLink = !validatedResetTokenLoading && !validatedResetToken?.success
    return (
        <div className="bridge-page password-reset-complete">
            <Row>
                <Col span={24} className="auth-main-content">
                    <WelcomeLogo view="login" />
                    <div className="inner">
                        {invalidLink && (
                            <div className="text-center">
                                <StopOutlined style={{ color: 'var(--muted)', fontSize: '4em' }} />
                            </div>
                        )}
                        <h2 className="subtitle" style={{ justifyContent: 'center' }}>
                            {invalidLink ? 'Unable to reset' : 'Set a new password'}
                        </h2>
                        {validatedResetTokenLoading ? (
                            <Skeleton paragraph={{ rows: 2 }} />
                        ) : !validatedResetToken?.token ? (
                            <ResetInvalid />
                        ) : (
                            <NewPasswordForm />
                        )}
                    </div>
                </Col>
            </Row>
        </div>
    )
}
Example #2
Source File: MITMChromeLauncher.tsx    From yakit with GNU Affero General Public License v3.0 6 votes vote down vote up
ChromeLauncherButton: React.FC<MITMChromeLauncherProp> = React.memo((props: MITMChromeLauncherProp) => {
    const [started, setStarted] = useState(false);

    useEffect(() => {
        const id = setInterval(() => {
            ipcRenderer.invoke("IsChromeLaunched").then(e => {
                setStarted(e)
            })
        }, 500)
        return () => {
            clearInterval(id);
        }
    }, [])

    return <Button.Group>
        <Button
            type={"primary"}
            onClick={() => {
                startChrome(props.host, props.port)
            }}
            icon={<ChromeFilled/>}
        >免配置启动</Button>
        {started && <Popconfirm
            title={"关闭所有免配置 Chrome"}
            onConfirm={() => {
                ipcRenderer.invoke("StopAllChrome").then(() => {
                    info("关闭所有免配置 Chrome 成功")
                }).catch(e => {
                    failed(`关闭所有 Chrome 失败: ${e}`)
                })
            }}
        >
            <Button danger={true}
                    type={"primary"}
                    icon={<StopOutlined/>}
            />
        </Popconfirm>}
    </Button.Group>
})
Example #3
Source File: index.tsx    From posthog-foss with MIT License 4 votes vote down vote up
export function AsyncMigrations(): JSX.Element {
    const { user } = useValues(userLogic)
    const { asyncMigrations, asyncMigrationsLoading, activeTab, asyncMigrationSettings } =
        useValues(asyncMigrationsLogic)
    const { triggerMigration, forceStopMigration, loadAsyncMigrations, setActiveTab } = useActions(asyncMigrationsLogic)

    const columns = [
        {
            title: '',
            render: function RenderTriggerButton(asyncMigration: AsyncMigration): JSX.Element {
                const status = asyncMigration.status
                return (
                    <Tooltip title={tooltipMessageForStatus[status]}>
                        {status === 0 ? (
                            <PlayCircleOutlined
                                className="migration-btn success"
                                onClick={() => triggerMigration(asyncMigration.id)}
                            />
                        ) : status === 1 ? (
                            <StopOutlined
                                className="migration-btn danger"
                                onClick={() => forceStopMigration(asyncMigration.id)}
                            />
                        ) : status === 2 ? (
                            <CheckCircleOutlined className="success" />
                        ) : status === 3 || status === 4 ? (
                            <RedoOutlined
                                className="migration-btn warning"
                                onClick={() => triggerMigration(asyncMigration.id)}
                            />
                        ) : status === 5 ? (
                            <Spinner size="sm" />
                        ) : null}
                    </Tooltip>
                )
            },
        },
        {
            title: 'Migration name',
            dataIndex: 'name',
        },
        {
            title: 'Description',
            render: function RenderError(asyncMigration: AsyncMigration): JSX.Element {
                const description = asyncMigration.description
                return (
                    <small>
                        <span>{description.slice(0, 40)}</span>
                        {description.length > 40 ? (
                            <a
                                onClick={() => {
                                    Modal.info({
                                        title: `'${asyncMigration.name}' description`,
                                        content: <pre>{description}</pre>,
                                        icon: <InfoCircleOutlined />,
                                        okText: 'Close',
                                        width: '80%',
                                    })
                                }}
                            >
                                {` [...]`}
                            </a>
                        ) : null}
                    </small>
                )
            },
        },
        {
            title: 'Progress',
            dataIndex: 'progress',
            render: function RenderMigrationProgress(progress: number): JSX.Element {
                return (
                    <div>
                        <Progress percent={progress} />
                    </div>
                )
            },
        },
        {
            title: 'Status',
            dataIndex: 'status',
            render: function RenderMigrationStatus(status: number): JSX.Element {
                return <div>{migrationStatusNumberToMessage[status]}</div>
            },
        },
        {
            title: 'Error',
            render: function RenderError(asyncMigration: AsyncMigration): JSX.Element {
                const error = asyncMigration.last_error || ''
                return (
                    <small>
                        <span>{error.slice(0, 40)}</span>
                        {error.length > 40 ? (
                            <a
                                onClick={() => {
                                    Modal.info({
                                        title: `Error on migration '${asyncMigration.name}'`,
                                        content: <pre>{error}</pre>,
                                        icon: <InfoCircleOutlined />,
                                        okText: 'Close',
                                        width: '80%',
                                    })
                                }}
                            >
                                {` [...]`}
                            </a>
                        ) : null}
                    </small>
                )
            },
        },
        {
            title: 'Last operation index',
            dataIndex: 'current_operation_index',
        },
        {
            title: 'Last query ID',
            dataIndex: 'current_query_id',
            render: function RenderQueryId(queryId: string): JSX.Element {
                return (
                    <div>
                        <small>{queryId}</small>
                    </div>
                )
            },
        },
        {
            title: 'Celery task ID',
            dataIndex: 'celery_task_id',
            render: function RenderCeleryTaskId(celeryTaskId: string): JSX.Element {
                return (
                    <div>
                        <small>{celeryTaskId}</small>
                    </div>
                )
            },
        },
        {
            title: 'Started at',
            dataIndex: 'started_at',
            render: function RenderStartedAt(startedAt: string): JSX.Element {
                return <div>{humanFriendlyDetailedTime(startedAt)}</div>
            },
        },
        {
            title: 'Finished at',
            dataIndex: 'finished_at',
            render: function RenderFinishedAt(finishedAt: string): JSX.Element {
                return <div>{humanFriendlyDetailedTime(finishedAt)}</div>
            },
        },
    ]
    return (
        <div className="async-migrations-scene">
            {user?.is_staff ? (
                <>
                    <PageHeader
                        title="Async Migrations"
                        caption={
                            <>
                                <p>Manage async migrations in your instance.</p>
                                <p>
                                    Read about async migrations on our{' '}
                                    <a href="https://posthog.com/docs/self-host/configure/async-migrations">
                                        dedicated docs page
                                    </a>
                                    .
                                </p>
                            </>
                        }
                    />

                    <Tabs activeKey={activeTab} onChange={(t) => setActiveTab(t as AsyncMigrationsTab)}>
                        <TabPane tab="Management" key={AsyncMigrationsTab.Management} />
                        <TabPane tab="Settings" key={AsyncMigrationsTab.Settings} />
                    </Tabs>

                    {activeTab === AsyncMigrationsTab.Management ? (
                        <>
                            <div className="mb float-right">
                                <Button
                                    icon={asyncMigrationsLoading ? <Spinner size="sm" /> : <RedoOutlined />}
                                    onClick={loadAsyncMigrations}
                                >
                                    Refresh
                                </Button>
                            </div>
                            <Space />
                            <Table
                                pagination={false}
                                loading={asyncMigrationsLoading}
                                columns={columns}
                                dataSource={asyncMigrations}
                            />
                        </>
                    ) : activeTab === AsyncMigrationsTab.Settings ? (
                        <>
                            <br />
                            {asyncMigrationSettings.map((setting) => {
                                return (
                                    <div key={setting.key}>
                                        <SettingUpdateField setting={setting} />
                                    </div>
                                )
                            })}
                        </>
                    ) : null}
                </>
            ) : (
                <PageHeader
                    title="Async Migrations"
                    caption={
                        <>
                            <p>
                                Only users with staff access can manage async migrations. Please contact your instance
                                admin.
                            </p>
                            <p>
                                If you're an admin and don't have access, set <code>is_staff=true</code> for your user
                                on the PostgreSQL <code>posthog_user</code> table.
                            </p>
                        </>
                    }
                />
            )}
        </div>
    )
}
Example #4
Source File: NewPropertyComponent.tsx    From posthog-foss with MIT License 4 votes vote down vote up
NewPropertyComponent = (): JSX.Element => {
    const initialState = { creating: false, propertyType: 'string' } as NewPropertyInterface
    const [state, setState] = useState(initialState)
    const { editProperty } = useActions(personsLogic)

    const saveProperty = (): void => {
        if (state.key && state.value !== undefined) {
            editProperty(state.key, state.value)
            setState(initialState)
        }
    }

    return (
        <>
            <div className="mb">
                <div className="text-right">
                    <Button
                        data-attr="add-prop-button"
                        onClick={() => setState({ ...state, creating: true })}
                        type="primary"
                        icon={<PlusOutlined />}
                    >
                        New property
                    </Button>
                </div>
            </div>
            <Modal
                visible={state.creating}
                destroyOnClose
                onCancel={() => setState(initialState)}
                title="Adding new property"
                okText={
                    <>
                        <SaveOutlined style={{ marginRight: 4 }} />
                        Save Property
                    </>
                }
                okButtonProps={{ disabled: !state.key || state.value === undefined }}
                onOk={saveProperty}
            >
                <div className="input-set">
                    <label htmlFor="propertyKey">Key</label>
                    <Input
                        id="propertyKey"
                        autoFocus
                        placeholder="try email, first_name, is_verified, membership_level, total_revenue"
                        onChange={(e) => setState({ ...state, key: e.target.value })}
                    />
                </div>
                <div className="input-set">
                    <label htmlFor="propertyType">Type of Property</label>
                    <div>
                        <Radio.Group
                            value={state.propertyType}
                            onChange={(e) =>
                                setState({
                                    ...state,
                                    propertyType: e.target.value,
                                    value: e.target.value === 'string' ? undefined : 'true',
                                })
                            }
                            id="propertyType"
                            buttonStyle="solid"
                        >
                            <Radio.Button value="string">Text or Number</Radio.Button>
                            <Radio.Button value="boolean">Boolean or Null</Radio.Button>
                        </Radio.Group>
                    </div>
                </div>

                <div className="input-set">
                    <label htmlFor="propertyValue">Value</label>
                    {state.propertyType === 'boolean' ? (
                        <div>
                            <Radio.Group
                                value={state.value}
                                onChange={(e) =>
                                    setState({
                                        ...state,
                                        value: e.target.value,
                                    })
                                }
                                id="propertyValue"
                                buttonStyle="solid"
                            >
                                <Radio.Button value="true" defaultChecked>
                                    <CheckOutlined /> True
                                </Radio.Button>
                                <Radio.Button value="false">
                                    <CloseOutlined /> False
                                </Radio.Button>
                                <Radio.Button value="null">
                                    <StopOutlined /> Null
                                </Radio.Button>
                            </Radio.Group>
                        </div>
                    ) : (
                        <Input
                            placeholder="try [email protected], gold, 1"
                            onChange={(e) => setState({ ...state, value: e.target.value })}
                            id="propertyValue"
                            onKeyDown={(e) => e.key === 'Enter' && saveProperty()}
                        />
                    )}
                </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: index.tsx    From ql with MIT License 4 votes vote down vote up
Config = () => {
  const columns = [
    {
      title: '序号',
      align: 'center' as const,
      render: (text: string, record: any, index: number) => {
        return <span style={{ cursor: 'text' }}>{index + 1} </span>;
      },
    },
    {
      title: '昵称',
      dataIndex: 'nickname',
      key: 'nickname',
      align: 'center' as const,
      width: '15%',
      render: (text: string, record: any, index: number) => {
        const match = record.value.match(/pt_pin=([^; ]+)(?=;?)/);
        const val = (match && match[1]) || '未匹配用户名';
        return (
          <span style={{ cursor: 'text' }}>{record.nickname || val} </span>
        );
      },
    },
    {
      title: '值',
      dataIndex: 'value',
      key: 'value',
      align: 'center' as const,
      width: '50%',
      render: (text: string, record: any) => {
        return (
          <span
            style={{
              textAlign: 'left',
              display: 'inline-block',
              wordBreak: 'break-all',
              cursor: 'text',
            }}
          >
            {text}
          </span>
        );
      },
    },
    {
      title: '状态',
      key: 'status',
      dataIndex: 'status',
      align: 'center' as const,
      width: '15%',
      render: (text: string, record: any, index: number) => {
        return (
          <Space size="middle" style={{ cursor: 'text' }}>
            <Tag
              color={StatusColor[record.status] || StatusColor[3]}
              style={{ marginRight: 0 }}
            >
              {Status[record.status]}
            </Tag>
            {record.status !== Status.已禁用 && (
              <Tooltip title="刷新">
                <a onClick={() => refreshStatus(record, index)}>
                  <SyncOutlined />
                </a>
              </Tooltip>
            )}
          </Space>
        );
      },
    },
    {
      title: '操作',
      key: 'action',
      align: 'center' as const,
      render: (text: string, record: any, index: number) => (
        <Space size="middle">
          <Tooltip title="编辑">
            <a onClick={() => editCookie(record, index)}>
              <EditOutlined />
            </a>
          </Tooltip>
          <Tooltip title={record.status === Status.已禁用 ? '启用' : '禁用'}>
            <a onClick={() => enabledOrDisabledCookie(record, index)}>
              {record.status === Status.已禁用 ? (
                <CheckCircleOutlined />
              ) : (
                <StopOutlined />
              )}
            </a>
          </Tooltip>
          <Tooltip title="删除">
            <a onClick={() => deleteCookie(record, index)}>
              <DeleteOutlined />
            </a>
          </Tooltip>
        </Space>
      ),
    },
  ];
  const [width, setWidth] = useState('100%');
  const [marginLeft, setMarginLeft] = useState(0);
  const [marginTop, setMarginTop] = useState(-72);
  const [value, setValue] = useState<any[]>([]);
  const [loading, setLoading] = useState(true);
  const [isModalVisible, setIsModalVisible] = useState(false);
  const [editedCookie, setEditedCookie] = useState();
  const [selectedRowIds, setSelectedRowIds] = useState<string[]>([]);

  const getCookies = () => {
    setLoading(true);
    request
      .get(`${config.apiPrefix}cookies`)
      .then((data: any) => {
        setValue(data.data);
      })
      .finally(() => setLoading(false));
  };

  const refreshStatus = (record: any, index: number) => {
    request
      .get(`${config.apiPrefix}cookies/${record._id}/refresh`)
      .then(async (data: any) => {
        if (data.data && data.data.value) {
          (value as any).splice(index, 1, data.data);
          setValue([...(value as any)] as any);
        } else {
          message.error('更新状态失败');
        }
      });
  };

  const enabledOrDisabledCookie = (record: any, index: number) => {
    Modal.confirm({
      title: `确认${record.status === Status.已禁用 ? '启用' : '禁用'}`,
      content: (
        <>
          确认{record.status === Status.已禁用 ? '启用' : '禁用'}
          Cookie{' '}
          <Text style={{ wordBreak: 'break-all' }} type="warning">
            {record.value}
          </Text>{' '}
          吗
        </>
      ),
      onOk() {
        request
          .put(
            `${config.apiPrefix}cookies/${
              record.status === Status.已禁用 ? 'enable' : 'disable'
            }`,
            {
              data: [record._id],
            },
          )
          .then((data: any) => {
            if (data.code === 200) {
              message.success(
                `${record.status === Status.已禁用 ? '启用' : '禁用'}成功`,
              );
              const newStatus =
                record.status === Status.已禁用 ? Status.未获取 : Status.已禁用;
              const result = [...value];
              result.splice(index, 1, {
                ...record,
                status: newStatus,
              });
              setValue(result);
            } else {
              message.error(data);
            }
          });
      },
      onCancel() {
        console.log('Cancel');
      },
    });
  };

  const addCookie = () => {
    setEditedCookie(null as any);
    setIsModalVisible(true);
  };

  const editCookie = (record: any, index: number) => {
    setEditedCookie(record);
    setIsModalVisible(true);
  };

  const deleteCookie = (record: any, index: number) => {
    Modal.confirm({
      title: '确认删除',
      content: (
        <>
          确认删除Cookie{' '}
          <Text style={{ wordBreak: 'break-all' }} type="warning">
            {record.value}
          </Text>{' '}
          吗
        </>
      ),
      onOk() {
        request
          .delete(`${config.apiPrefix}cookies`, { data: [record._id] })
          .then((data: any) => {
            if (data.code === 200) {
              message.success('删除成功');
              const result = [...value];
              result.splice(index, 1);
              setValue(result);
            } else {
              message.error(data);
            }
          });
      },
      onCancel() {
        console.log('Cancel');
      },
    });
  };

  const handleCancel = (cookies?: any[]) => {
    setIsModalVisible(false);
    if (cookies && cookies.length > 0) {
      handleCookies(cookies);
    }
  };

  const handleCookies = (cookies: any[]) => {
    const result = [...value];
    for (let i = 0; i < cookies.length; i++) {
      const cookie = cookies[i];
      const index = value.findIndex((x) => x._id === cookie._id);
      if (index === -1) {
        result.push(cookie);
      } else {
        result.splice(index, 1, {
          ...cookie,
        });
      }
    }
    setValue(result);
  };

  const components = {
    body: {
      row: DragableBodyRow,
    },
  };

  const moveRow = useCallback(
    (dragIndex, hoverIndex) => {
      if (dragIndex === hoverIndex) {
        return;
      }
      const dragRow = value[dragIndex];
      const newData = [...value];
      newData.splice(dragIndex, 1);
      newData.splice(hoverIndex, 0, dragRow);
      setValue([...newData]);
      request
        .put(`${config.apiPrefix}cookies/${dragRow._id}/move`, {
          data: { fromIndex: dragIndex, toIndex: hoverIndex },
        })
        .then((data: any) => {
          if (data.code !== 200) {
            message.error(data);
          }
        });
    },
    [value],
  );

  const onSelectChange = (selectedIds: any[]) => {
    setSelectedRowIds(selectedIds);
  };

  const rowSelection = {
    selectedRowIds,
    onChange: onSelectChange,
  };

  const delCookies = () => {
    Modal.confirm({
      title: '确认删除',
      content: <>确认删除选中的Cookie吗</>,
      onOk() {
        request
          .delete(`${config.apiPrefix}cookies`, { data: selectedRowIds })
          .then((data: any) => {
            if (data.code === 200) {
              message.success('批量删除成功');
              setSelectedRowIds([]);
              getCookies();
            } else {
              message.error(data);
            }
          });
      },
      onCancel() {
        console.log('Cancel');
      },
    });
  };

  const operateCookies = (operationStatus: number) => {
    Modal.confirm({
      title: `确认${OperationName[operationStatus]}`,
      content: <>确认{OperationName[operationStatus]}选中的Cookie吗</>,
      onOk() {
        request
          .put(`${config.apiPrefix}cookies/${OperationPath[operationStatus]}`, {
            data: selectedRowIds,
          })
          .then((data: any) => {
            if (data.code === 200) {
              getCookies();
            } else {
              message.error(data);
            }
          });
      },
      onCancel() {
        console.log('Cancel');
      },
    });
  };

  useEffect(() => {
    if (document.body.clientWidth < 768) {
      setWidth('auto');
      setMarginLeft(0);
      setMarginTop(0);
    } else {
      setWidth('100%');
      setMarginLeft(0);
      setMarginTop(-72);
    }
    getCookies();
  }, []);

  return (
    <PageContainer
      className="session-wrapper"
      title="Session管理"
      extra={[
        <Button key="2" type="primary" onClick={() => addCookie()}>
          添加Cookie
        </Button>,
      ]}
      header={{
        style: {
          padding: '4px 16px 4px 15px',
          position: 'sticky',
          top: 0,
          left: 0,
          zIndex: 20,
          marginTop,
          width,
          marginLeft,
        },
      }}
    >
      {selectedRowIds.length > 0 && (
        <div style={{ marginBottom: 16 }}>
          <Button
            type="primary"
            style={{ marginBottom: 5 }}
            onClick={delCookies}
          >
            批量删除
          </Button>
          <Button
            type="primary"
            onClick={() => operateCookies(0)}
            style={{ marginLeft: 8, marginBottom: 5 }}
          >
            批量启用
          </Button>
          <Button
            type="primary"
            onClick={() => operateCookies(1)}
            style={{ marginLeft: 8, marginRight: 8 }}
          >
            批量禁用
          </Button>
          <span style={{ marginLeft: 8 }}>
            已选择
            <a>{selectedRowIds?.length}</a>项
          </span>
        </div>
      )}
      <DndProvider backend={HTML5Backend}>
        <Table
          columns={columns}
          rowSelection={rowSelection}
          pagination={false}
          dataSource={value}
          rowKey="_id"
          size="middle"
          scroll={{ x: 768 }}
          components={components}
          loading={loading}
          onRow={(record, index) => {
            return {
              index,
              moveRow,
            } as any;
          }}
        />
      </DndProvider>
      <CookieModal
        visible={isModalVisible}
        handleCancel={handleCancel}
        cookie={editedCookie}
      />
    </PageContainer>
  );
}
Example #7
Source File: index.tsx    From ql with MIT License 4 votes vote down vote up
Crontab = () => {
  const columns = [
    {
      title: '任务名',
      dataIndex: 'name',
      key: 'name',
      align: 'center' as const,
      render: (text: string, record: any) => (
        <span>{record.name || record._id}</span>
      ),
    },
    {
      title: '任务',
      dataIndex: 'command',
      key: 'command',
      width: '40%',
      align: 'center' as const,
      render: (text: string, record: any) => {
        return (
          <span
            style={{
              textAlign: 'left',
              width: '100%',
              display: 'inline-block',
              wordBreak: 'break-all',
            }}
          >
            {text}
          </span>
        );
      },
    },
    {
      title: '任务定时',
      dataIndex: 'schedule',
      key: 'schedule',
      align: 'center' as const,
    },
    {
      title: '状态',
      key: 'status',
      dataIndex: 'status',
      align: 'center' as const,
      render: (text: string, record: any) => (
        <>
          {(!record.isDisabled || record.status !== CrontabStatus.idle) && (
            <>
              {record.status === CrontabStatus.idle && (
                <Tag icon={<ClockCircleOutlined />} color="default">
                  空闲中
                </Tag>
              )}
              {record.status === CrontabStatus.running && (
                <Tag
                  icon={<Loading3QuartersOutlined spin />}
                  color="processing"
                >
                  运行中
                </Tag>
              )}
              {record.status === CrontabStatus.queued && (
                <Tag icon={<FieldTimeOutlined />} color="default">
                  队列中
                </Tag>
              )}
            </>
          )}
          {record.isDisabled === 1 && record.status === CrontabStatus.idle && (
            <Tag icon={<CloseCircleOutlined />} color="error">
              已禁用
            </Tag>
          )}
        </>
      ),
    },
    {
      title: '操作',
      key: 'action',
      align: 'center' as const,
      render: (text: string, record: any, index: number) => (
        <Space size="middle">
          {record.status === CrontabStatus.idle && (
            <Tooltip title="运行">
              <a
                onClick={() => {
                  runCron(record, index);
                }}
              >
                <PlayCircleOutlined />
              </a>
            </Tooltip>
          )}
          {record.status !== CrontabStatus.idle && (
            <Tooltip title="停止">
              <a
                onClick={() => {
                  stopCron(record, index);
                }}
              >
                <PauseCircleOutlined />
              </a>
            </Tooltip>
          )}
          <Tooltip title="日志">
            <a
              onClick={() => {
                setLogCron({ ...record, timestamp: Date.now() });
              }}
            >
              <FileTextOutlined />
            </a>
          </Tooltip>
          <MoreBtn key="more" record={record} index={index} />
        </Space>
      ),
    },
  ];

  const [width, setWidth] = useState('100%');
  const [marginLeft, setMarginLeft] = useState(0);
  const [marginTop, setMarginTop] = useState(-72);
  const [value, setValue] = useState<any[]>([]);
  const [loading, setLoading] = useState(true);
  const [isModalVisible, setIsModalVisible] = useState(false);
  const [editedCron, setEditedCron] = useState();
  const [searchText, setSearchText] = useState('');
  const [isLogModalVisible, setIsLogModalVisible] = useState(false);
  const [logCron, setLogCron] = useState<any>();
  const [selectedRowIds, setSelectedRowIds] = useState<string[]>([]);
  const [currentPage, setCurrentPage] = useState(1);
  const [pageSize, setPageSize] = useState(20);

  const getCrons = () => {
    setLoading(true);
    request
      .get(`${config.apiPrefix}crons?searchValue=${searchText}`)
      .then((data: any) => {
        setValue(
          data.data.sort((a: any, b: any) => {
            const sortA = a.isDisabled ? 4 : a.status;
            const sortB = b.isDisabled ? 4 : b.status;
            return CrontabSort[sortA] - CrontabSort[sortB];
          }),
        );
      })
      .finally(() => setLoading(false));
  };

  const addCron = () => {
    setEditedCron(null as any);
    setIsModalVisible(true);
  };

  const editCron = (record: any, index: number) => {
    setEditedCron(record);
    setIsModalVisible(true);
  };

  const delCron = (record: any, index: number) => {
    Modal.confirm({
      title: '确认删除',
      content: (
        <>
          确认删除定时任务{' '}
          <Text style={{ wordBreak: 'break-all' }} type="warning">
            {record.name}
          </Text>{' '}
          吗
        </>
      ),
      onOk() {
        request
          .delete(`${config.apiPrefix}crons`, { data: [record._id] })
          .then((data: any) => {
            if (data.code === 200) {
              message.success('删除成功');
              const result = [...value];
              result.splice(index + pageSize * (currentPage - 1), 1);
              setValue(result);
            } else {
              message.error(data);
            }
          });
      },
      onCancel() {
        console.log('Cancel');
      },
    });
  };

  const runCron = (record: any, index: number) => {
    Modal.confirm({
      title: '确认运行',
      content: (
        <>
          确认运行定时任务{' '}
          <Text style={{ wordBreak: 'break-all' }} type="warning">
            {record.name}
          </Text>{' '}
          吗
        </>
      ),
      onOk() {
        request
          .put(`${config.apiPrefix}crons/run`, { data: [record._id] })
          .then((data: any) => {
            if (data.code === 200) {
              const result = [...value];
              result.splice(index + pageSize * (currentPage - 1), 1, {
                ...record,
                status: CrontabStatus.running,
              });
              setValue(result);
            } else {
              message.error(data);
            }
          });
      },
      onCancel() {
        console.log('Cancel');
      },
    });
  };

  const stopCron = (record: any, index: number) => {
    Modal.confirm({
      title: '确认停止',
      content: (
        <>
          确认停止定时任务{' '}
          <Text style={{ wordBreak: 'break-all' }} type="warning">
            {record.name}
          </Text>{' '}
          吗
        </>
      ),
      onOk() {
        request
          .put(`${config.apiPrefix}crons/stop`, { data: [record._id] })
          .then((data: any) => {
            if (data.code === 200) {
              const result = [...value];
              result.splice(index + pageSize * (currentPage - 1), 1, {
                ...record,
                pid: null,
                status: CrontabStatus.idle,
              });
              setValue(result);
            } else {
              message.error(data);
            }
          });
      },
      onCancel() {
        console.log('Cancel');
      },
    });
  };

  const enabledOrDisabledCron = (record: any, index: number) => {
    Modal.confirm({
      title: `确认${record.isDisabled === 1 ? '启用' : '禁用'}`,
      content: (
        <>
          确认{record.isDisabled === 1 ? '启用' : '禁用'}
          定时任务{' '}
          <Text style={{ wordBreak: 'break-all' }} type="warning">
            {record.name}
          </Text>{' '}
          吗
        </>
      ),
      onOk() {
        request
          .put(
            `${config.apiPrefix}crons/${
              record.isDisabled === 1 ? 'enable' : 'disable'
            }`,
            {
              data: [record._id],
            },
          )
          .then((data: any) => {
            if (data.code === 200) {
              const newStatus = record.isDisabled === 1 ? 0 : 1;
              const result = [...value];
              result.splice(index + pageSize * (currentPage - 1), 1, {
                ...record,
                isDisabled: newStatus,
              });
              setValue(result);
            } else {
              message.error(data);
            }
          });
      },
      onCancel() {
        console.log('Cancel');
      },
    });
  };

  const MoreBtn: React.FC<{
    record: any;
    index: number;
  }> = ({ record, index }) => (
    <Dropdown
      arrow
      trigger={['click']}
      overlay={
        <Menu onClick={({ key }) => action(key, record, index)}>
          <Menu.Item key="edit" icon={<EditOutlined />}>
            编辑
          </Menu.Item>
          <Menu.Item
            key="enableordisable"
            icon={
              record.isDisabled === 1 ? (
                <CheckCircleOutlined />
              ) : (
                <StopOutlined />
              )
            }
          >
            {record.isDisabled === 1 ? '启用' : '禁用'}
          </Menu.Item>
          {record.isSystem !== 1 && (
            <Menu.Item key="delete" icon={<DeleteOutlined />}>
              删除
            </Menu.Item>
          )}
        </Menu>
      }
    >
      <a>
        <EllipsisOutlined />
      </a>
    </Dropdown>
  );

  const action = (key: string | number, record: any, index: number) => {
    switch (key) {
      case 'edit':
        editCron(record, index);
        break;
      case 'enableordisable':
        enabledOrDisabledCron(record, index);
        break;
      case 'delete':
        delCron(record, index);
        break;
      default:
        break;
    }
  };

  const handleCancel = (cron?: any) => {
    setIsModalVisible(false);
    if (cron) {
      handleCrons(cron);
    }
  };

  const onSearch = (value: string) => {
    setSearchText(value);
  };

  const handleCrons = (cron: any) => {
    const index = value.findIndex((x) => x._id === cron._id);
    const result = [...value];
    if (index === -1) {
      result.push(cron);
    } else {
      result.splice(index, 1, {
        ...cron,
      });
    }
    setValue(result);
  };

  const getCronDetail = (cron: any) => {
    request
      .get(`${config.apiPrefix}crons/${cron._id}`)
      .then((data: any) => {
        console.log(value);
        const index = value.findIndex((x) => x._id === cron._id);
        console.log(index);
        const result = [...value];
        result.splice(index, 1, {
          ...cron,
          ...data.data,
        });
        setValue(result);
      })
      .finally(() => setLoading(false));
  };

  const onSelectChange = (selectedIds: any[]) => {
    setSelectedRowIds(selectedIds);
  };

  const rowSelection = {
    selectedRowIds,
    onChange: onSelectChange,
    selections: [
      Table.SELECTION_ALL,
      Table.SELECTION_INVERT,
      Table.SELECTION_NONE,
    ],
  };

  const delCrons = () => {
    Modal.confirm({
      title: '确认删除',
      content: <>确认删除选中的定时任务吗</>,
      onOk() {
        request
          .delete(`${config.apiPrefix}crons`, { data: selectedRowIds })
          .then((data: any) => {
            if (data.code === 200) {
              message.success('批量删除成功');
              setSelectedRowIds([]);
              getCrons();
            } else {
              message.error(data);
            }
          });
      },
      onCancel() {
        console.log('Cancel');
      },
    });
  };

  const operateCrons = (operationStatus: number) => {
    Modal.confirm({
      title: `确认${OperationName[operationStatus]}`,
      content: <>确认{OperationName[operationStatus]}选中的定时任务吗</>,
      onOk() {
        request
          .put(`${config.apiPrefix}crons/${OperationPath[operationStatus]}`, {
            data: selectedRowIds,
          })
          .then((data: any) => {
            if (data.code === 200) {
              getCrons();
            } else {
              message.error(data);
            }
          });
      },
      onCancel() {
        console.log('Cancel');
      },
    });
  };

  const onPageChange = (page: number, pageSize: number | undefined) => {
    setCurrentPage(page);
    setPageSize(pageSize as number);
    localStorage.setItem('pageSize', pageSize + '');
  };

  useEffect(() => {
    if (logCron) {
      localStorage.setItem('logCron', logCron._id);
      setIsLogModalVisible(true);
    }
  }, [logCron]);

  useEffect(() => {
    getCrons();
  }, [searchText]);

  useEffect(() => {
    if (document.body.clientWidth < 768) {
      setWidth('auto');
      setMarginLeft(0);
      setMarginTop(0);
    } else {
      setWidth('100%');
      setMarginLeft(0);
      setMarginTop(-72);
    }
    setPageSize(parseInt(localStorage.getItem('pageSize') || '20'));
  }, []);

  return (
    <PageContainer
      className="ql-container-wrapper crontab-wrapper"
      title="定时任务"
      extra={[
        <Search
          placeholder="请输入名称或者关键词"
          style={{ width: 'auto' }}
          enterButton
          loading={loading}
          onSearch={onSearch}
        />,
        <Button key="2" type="primary" onClick={() => addCron()}>
          添加定时
        </Button>,
      ]}
      header={{
        style: {
          padding: '4px 16px 4px 15px',
          position: 'sticky',
          top: 0,
          left: 0,
          zIndex: 20,
          marginTop,
          width,
          marginLeft,
        },
      }}
    >
      {selectedRowIds.length > 0 && (
        <div style={{ marginBottom: 16 }}>
          <Button type="primary" style={{ marginBottom: 5 }} onClick={delCrons}>
            批量删除
          </Button>
          <Button
            type="primary"
            onClick={() => operateCrons(0)}
            style={{ marginLeft: 8, marginBottom: 5 }}
          >
            批量启用
          </Button>
          <Button
            type="primary"
            onClick={() => operateCrons(1)}
            style={{ marginLeft: 8, marginRight: 8 }}
          >
            批量禁用
          </Button>
          <Button
            type="primary"
            style={{ marginRight: 8 }}
            onClick={() => operateCrons(2)}
          >
            批量运行
          </Button>
          <Button type="primary" onClick={() => operateCrons(3)}>
            批量停止
          </Button>
          <span style={{ marginLeft: 8 }}>
            已选择
            <a>{selectedRowIds?.length}</a>项
          </span>
        </div>
      )}
      <Table
        columns={columns}
        pagination={{
          hideOnSinglePage: true,
          current: currentPage,
          onChange: onPageChange,
          pageSize: pageSize,
          showSizeChanger: true,
          defaultPageSize: 20,
          showTotal: (total: number, range: number[]) =>
            `第 ${range[0]}-${range[1]} 条/总共 ${total} 条`,
        }}
        dataSource={value}
        rowKey="_id"
        size="middle"
        scroll={{ x: 768 }}
        loading={loading}
        rowSelection={rowSelection}
      />
      <CronLogModal
        visible={isLogModalVisible}
        handleCancel={() => {
          getCronDetail(logCron);
          setIsLogModalVisible(false);
        }}
        cron={logCron}
      />
      <CronModal
        visible={isModalVisible}
        handleCancel={handleCancel}
        cron={editedCron}
      />
    </PageContainer>
  );
}
Example #8
Source File: Header.tsx    From slim with Apache License 2.0 4 votes vote down vote up
render (): React.ReactNode {
    var user = null
    if (this.props.user !== undefined) {
      const userMenuItems = []
      if (this.props.onUserLogout !== undefined) {
        userMenuItems.push(
          {
            label: 'Logout',
            key: 'user-logout',
            onClick: () => {
              if (this.props.onUserLogout !== undefined) {
                this.props.onUserLogout()
              }
            }
          }
        )
      }
      const userMenu = <Menu items={userMenuItems} />
      user = (
        <Dropdown overlay={userMenu} trigger={['click']}>
          <Button
            icon={UserOutlined}
            onClick={e => e.preventDefault()}
            label={`${this.props.user.name} (${this.props.user.email})`}
          />
        </Dropdown>
      )
    }

    let worklistButton
    if (this.props.showWorklistButton) {
      worklistButton = (
        <NavLink to='/'>
          <Button icon={UnorderedListOutlined} tooltip='Go to worklist' />
        </NavLink>
      )
    }

    const infoButton = (
      <Button
        icon={InfoOutlined}
        tooltip='Get app info'
        onClick={this.handleInfoButtonClick}
      />
    )

    let serverSelectionButton
    if (this.props.showServerSelectionButton) {
      serverSelectionButton = (
        <Button
          icon={ApiOutlined}
          tooltip='Select server'
          onClick={this.handleServerSelectionButtonClick}
        />
      )
    }

    const handleServerSelectionInput = (event: any): void => {
      const value = event.target.value
      let isDisabled = true
      if (value != null) {
        try {
          const url = new URL(value)
          if (url.protocol.startsWith('http') && url.pathname.length > 0) {
            isDisabled = false
          }
        } catch (TypeError) {}
      }
      this.setState({
        selectedServerUrl: value,
        isServerSelectionDisabled: isDisabled
      })
    }

    const handleServerSelectionCancellation = (event: any): void => {
      this.setState({
        selectedServerUrl: undefined,
        isServerSelectionModalVisible: false,
        isServerSelectionDisabled: true
      })
    }

    const handleServerSelection = (event: any): void => {
      const url = this.state.selectedServerUrl
      let closeModal = false
      if (url != null && url !== '') {
        if (url.startsWith('http://') || url.startsWith('https://')) {
          this.props.onServerSelection({ url })
          closeModal = true
        }
      }
      this.setState({
        selectedServerUrl: undefined,
        isServerSelectionModalVisible: !closeModal,
        isServerSelectionDisabled: true
      })
    }

    const logoUrl = process.env.PUBLIC_URL + '/logo.svg'

    return (
      <>
        <Layout.Header style={{ width: '100%', padding: '0 14px' }}>
          <Row>
            <Col>
              <Space align='center' direction='horizontal'>
                <img
                  src={logoUrl}
                  alt=''
                  style={{ height: '64px', margin: '-14px' }}
                />
              </Space>
            </Col>
            <Col flex='auto' />
            <Col>
              <Space direction='horizontal'>
                {worklistButton}
                {infoButton}
                {serverSelectionButton}
                {user}
              </Space>
            </Col>
          </Row>
        </Layout.Header>

        <Modal
          visible={this.state.isServerSelectionModalVisible}
          title='Select DICOMweb server'
          onOk={handleServerSelection}
          onCancel={handleServerSelectionCancellation}
        >
          <Input
            placeholder='Enter base URL of DICOMweb Study Service'
            onChange={handleServerSelectionInput}
            onPressEnter={handleServerSelection}
            addonAfter={
              this.state.isServerSelectionDisabled
                ? <StopOutlined style={{ color: 'rgba(0,0,0,.45)' }} />
                : <CheckOutlined style={{ color: 'rgba(0,0,0,.45)' }} />
            }
          />
        </Modal>
      </>
    )
  }
Example #9
Source File: Stats.tsx    From leek with Apache License 2.0 4 votes vote down vote up
function Stats(stats: any) {
  return [
    {
      number: stats.SEEN_TASKS,
      text: "Total Tasks",
      icon: <UnorderedListOutlined />,
      tooltip: "Seen tasks names",
    },
    {
      number: stats.SEEN_WORKERS,
      text: "Total Workers",
      icon: <RobotFilled />,
      tooltip: "The total offline/online and beat workers",
    },
    {
      number: stats.PROCESSED_EVENTS,
      text: "Events Processed",
      icon: <ThunderboltOutlined />,
      tooltip: "The total processed events",
    },
    {
      number: stats.PROCESSED_TASKS,
      text: "Tasks Processed",
      icon: <SyncOutlined />,
      tooltip: "The total processed tasks",
    },
    {
      number: stats.QUEUED,
      text: "Tasks Queued",
      icon: <EllipsisOutlined />,
      tooltip: "The total tasks in the queues",
    },
    {
      number: stats.RETRY,
      text: "To Retry",
      icon: <RetweetOutlined style={{ color: STATES_COLORS.RETRY }} />,
      tooltip: "Tasks that are failed and waiting for retry",
    },
    {
      number: stats.RECEIVED,
      text: "Received",
      icon: <SendOutlined style={{ color: STATES_COLORS.RECEIVED }} />,
      tooltip: "Tasks were received by a worker. but not yet started",
    },
    {
      number: stats.STARTED,
      text: "Started",
      icon: <LoadingOutlined style={{ color: STATES_COLORS.STARTED }} />,
      tooltip:
        "Tasks that were started by a worker and still active, set (task_track_started) to True on worker level to report started tasks",
    },
    {
      number: stats.SUCCEEDED,
      text: "Succeeded",
      icon: <CheckCircleOutlined style={{ color: STATES_COLORS.SUCCEEDED }} />,
      tooltip: "Tasks that were succeeded",
    },
    {
      number: stats.RECOVERED,
      text: "Recovered",
      icon: <IssuesCloseOutlined style={{ color: STATES_COLORS.RECOVERED }} />,
      tooltip: "Tasks that were succeeded after retries.",
    },
    {
      number: stats.FAILED,
      text: "Failed",
      icon: <WarningOutlined style={{ color: STATES_COLORS.FAILED }} />,
      tooltip: "Tasks that were failed",
    },
    {
      number: stats.CRITICAL,
      text: "Critical",
      icon: <CloseCircleOutlined style={{ color: STATES_COLORS.CRITICAL }} />,
      tooltip: "Tasks that were failed after max retries.",
    },
    {
      number: stats.REJECTED,
      text: "Rejected",
      icon: <RollbackOutlined style={{ color: STATES_COLORS.REJECTED }} />,
      tooltip:
        "Tasks that were rejected by workers and requeued, or moved to a dead letter queue",
    },
    {
      number: stats.REVOKED,
      text: "Revoked",
      icon: <StopOutlined style={{ color: STATES_COLORS.REVOKED }} />,
      tooltip: "Tasks that were revoked by workers, but still in the queue.",
    },
  ];
}
Example #10
Source File: QueueListSharedComponents.tsx    From office-hours with GNU General Public License v3.0 4 votes vote down vote up
export function QueueInfoColumn({
  queueId,
  isStaff,
  buttons,
}: QueueInfoColumnProps): ReactElement {
  const { queue, mutateQueue } = useQueue(queueId);

  const disableQueue = async () => {
    await API.queues.disable(queueId);
    await mutateQueue();
    message.success("Successfully disabled queue: " + queue.room);
    await Router.push("/");
  };

  const clearQueue = async () => {
    await API.queues.clean(queueId);
    await mutateQueue();
    message.success("Successfully cleaned queue: " + queue.room);
  };

  const confirmDisable = () => {
    confirm({
      title: `Please Confirm!`,
      icon: <ExclamationCircleOutlined />,
      style: { whiteSpace: "pre-wrap" },
      content: `Please confirm that you want to disable the queue: ${queue.room}.\n
      This queue will no longer appear in the app, and any students currently in the queue will be removed.`,
      onOk() {
        disableQueue();
      },
    });
  };

  return (
    <InfoColumnContainer>
      <QueueInfo>
        <QueueRoomGroup>
          <QueueTitle data-cy="room-title">
            {queue?.room} {queue?.isDisabled && <b>(disabled)</b>}
          </QueueTitle>
          {!queue.allowQuestions && (
            <Tooltip title="This queue is no longer accepting questions">
              <StopOutlined
                data-cy="stopQuestions"
                style={{ color: "red", fontSize: "24px", marginLeft: "8px" }}
              />
            </Tooltip>
          )}
        </QueueRoomGroup>

        {queue?.isProfessorQueue && (
          <QueuePropertyRow>
            <Tag color="blue">Professor Queue</Tag>
          </QueuePropertyRow>
        )}
      </QueueInfo>
      {queue?.notes && (
        <QueuePropertyRow>
          <NotificationOutlined />
          <QueueText>
            <Linkify
              componentDecorator={(decoratedHref, decoratedText, key) => (
                <a
                  target="_blank"
                  rel="noopener noreferrer"
                  href={decoratedHref}
                  key={key}
                >
                  {decoratedText}
                </a>
              )}
            >
              <QueuePropertyText>{queue.notes}</QueuePropertyText>
            </Linkify>
          </QueueText>
        </QueuePropertyRow>
      )}
      <QueueUpToDateInfo queueId={queueId} />
      {buttons}
      <StaffH2>Staff</StaffH2>
      <TAStatuses queueId={queueId} />
      {isStaff && (
        <QueueManagementBox>
          <Popconfirm
            title={
              "Are you sure you want to clear all students from the queue?"
            }
            okText="Yes"
            cancelText="No"
            placement="top"
            arrowPointAtCenter={true}
            onConfirm={clearQueue}
          >
            <ClearQueueButton>Clear Queue</ClearQueueButton>
          </Popconfirm>
          <DisableQueueButton
            onClick={confirmDisable}
            data-cy="queue-disable-button"
            disabled={queue?.isDisabled}
          >
            {queue?.isDisabled ? `Queue deleted` : `Delete Queue`}
          </DisableQueueButton>
        </QueueManagementBox>
      )}
    </InfoColumnContainer>
  );
}
Example #11
Source File: QueueCard.tsx    From office-hours with GNU General Public License v3.0 4 votes vote down vote up
QueueCard = ({
  queue,
  isTA,
  updateQueueNotes,
}: QueueCard): ReactElement => {
  const [editingNotes, setEditingNotes] = useState(false);
  const [updatedNotes, setUpdatedNotes] = useState(queue.notes);
  const router = useRouter();
  const { cid } = router.query;

  const staffList = queue.staffList;

  const handleUpdate = () => {
    setEditingNotes(false);
    updateQueueNotes(queue, updatedNotes);
  };

  return (
    <PaddedCard
      headStyle={{
        background: queue.isOpen ? "#25426C" : "#25426cbf",
        color: "#FFFFFF",
        borderRadius: "6px 6px 0 0",
      }}
      className={"open-queue-card"}
      title={<span>{queue.room} </span>}
      extra={
        <span>
          <QueueSizeSpan>{queue.queueSize}</QueueSizeSpan> in queue
        </span>
      }
    >
      <QueueInfoRow>
        <HeaderDiv>
          <QuestionNumberSpan>{queue.staffList.length}</QuestionNumberSpan>{" "}
          staff checked in
        </HeaderDiv>
        <RightQueueInfoRow>
          <Space direction="vertical" align="end" size="middle">
            <QueueInfoTags>
              {queue?.isProfessorQueue && (
                <Tag color="blue" style={{ margin: 0 }}>
                  Professor Queue
                </Tag>
              )}
              {queue.isOpen && !queue.allowQuestions && (
                <Tooltip title="This queue is no longer accepting questions">
                  <Tag
                    icon={<StopOutlined />}
                    color="error"
                    style={{ margin: "0px 0px 0px 8px" }}
                  >
                    Not Accepting Questions
                  </Tag>
                </Tooltip>
              )}
            </QueueInfoTags>
            <Link
              href="/course/[cid]/queue/[qid]"
              as={`/course/${cid}/queue/${queue.id}`}
            >
              <OpenQueueButton
                style={{}}
                size="large"
                data-cy="open-queue-button"
              >
                Open Queue
              </OpenQueueButton>
            </Link>
          </Space>
        </RightQueueInfoRow>
      </QueueInfoRow>
      {
        staffList.length > 1 && (
          <HeaderText>checked-in staff</HeaderText>
        ) /*todo: add better text*/
      }

      <Row justify="space-between" align="middle">
        <div>
          {staffList.map((staffMember) => (
            <Tooltip key={staffMember.id} title={staffMember.name}>
              <StyledKOHAvatar
                size={96}
                photoURL={staffMember.photoURL}
                name={staffMember.name}
              />
            </Tooltip>
          ))}
        </div>
        <QueueCardDivider />
        {editingNotes ? (
          <NotesDiv>
            <NotesInput
              defaultValue={queue.notes}
              value={updatedNotes}
              onChange={(e) => setUpdatedNotes(e.target.value as any)}
            />
          </NotesDiv>
        ) : queue.notes ? (
          <div>
            <Linkify
              componentDecorator={(decoratedHref, decoratedText, key) => (
                <a
                  target="_blank"
                  rel="noopener noreferrer"
                  href={decoratedHref}
                  key={key}
                >
                  {decoratedText}
                </a>
              )}
            >
              <Notes>
                <NotificationOutlined /> <i>{queue.notes}</i>
              </Notes>
            </Linkify>
          </div>
        ) : (
          <div>
            <i> no notes provided</i>
          </div>
        )}
        <RightQueueNotesRow>
          {editingNotes && (
            <SaveButton onClick={handleUpdate} size="large">
              Save Changes
            </SaveButton>
          )}
          {!editingNotes && (
            <QueueCardButtonRow>
              {isTA && (
                <EditNotesButton
                  size="large"
                  onClick={() => {
                    setEditingNotes(true);
                  }}
                >
                  Edit Notes
                </EditNotesButton>
              )}
            </QueueCardButtonRow>
          )}
        </RightQueueNotesRow>
      </Row>
    </PaddedCard>
  );
}