@ant-design/icons#RollbackOutlined TypeScript Examples

The following examples show how to use @ant-design/icons#RollbackOutlined. 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 web-pdm with Apache License 2.0 6 votes vote down vote up
IconRenders = {

    undo: <RollbackOutlined />,
    redo: <RollbackOutlined style={{ transform: 'scaleX(-1)' }} />,
    min: <ZoomOutOutlined />,
    max: <ZoomInOutlined />,
    full: <BorderOutlined />,
    miniMap: <PictureFilled />,
    miniMapNo: <PictureOutlined />,
    dagreLayout: <PartitionOutlined />,
    relationLayout: <UngroupOutlined />,
    reload: <ReloadOutlined />,
    image: <DownloadOutlined />,
    darkness: <SnippetsFilled />,
    light: <SnippetsOutlined />,
    colorClose: <BgColorsOutlined />,
    colorOpen: <BgColorsOutlined />
}
Example #2
Source File: out.tsx    From web-pdm with Apache License 2.0 6 votes vote down vote up
IconRenders = {

    undo: <RollbackOutlined />,
    redo: <RollbackOutlined style={{ transform: 'scaleX(-1)' }} />,
    min: <ZoomOutOutlined />,
    max: <ZoomInOutlined />,
    full: <BorderOutlined />,
    miniMap: <PictureFilled />,
    miniMapNo: <PictureOutlined />,
    dagreLayout: <PartitionOutlined />,
    relationLayout: <UngroupOutlined />,
    reload: <ReloadOutlined />,
    image: <DownloadOutlined />,
    darkness: <SnippetsFilled />,
    light: <SnippetsOutlined />,
    colorClose: <BgColorsOutlined />,
    colorOpen: <BgColorsOutlined />
}
Example #3
Source File: add.tsx    From fe-v5 with Apache License 2.0 5 votes vote down vote up
Add = (props: any) => {
  const history = useHistory();
  const { curBusiItem } = useSelector<RootState, CommonStoreState>((state) => state.common);
  const { t } = useTranslation();
  const handleSubmit = (values: any) => {
    request(`${api.tasktpls(curBusiItem.id)}`, {
      method: 'POST',
      body: JSON.stringify(values),
    }).then(() => {
      message.success(t('msg.create.success'));
      props.history.push({
        pathname: `/job-tpls`,
      });
    });
  };

  return (
    <PageLayout hideCluster title={
      <>
        <RollbackOutlined className='back' onClick={() => history.push('/job-tpls')} />
        自愈脚本
      </>
    }>
      <div style={{ padding: 10 }}>
        <Card
          title="创建自愈脚本"
        >
        <TplForm
          onSubmit={handleSubmit}
          footer={
            <div>
              <Button type="primary" htmlType="submit" style={{ marginRight: 8 }}> 
                {t('form.submit')}
              </Button>
            </div>
          }
        />
        </Card>
      </div>
    </PageLayout>
  )
}
Example #4
Source File: clone.tsx    From fe-v5 with Apache License 2.0 5 votes vote down vote up
Add = (props: any) => {
  const history = useHistory();
  const id = _.get(props, 'match.params.id');
  const { curBusiItem } = useSelector<RootState, CommonStoreState>((state) => state.common);
  const { t } = useTranslation();
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState({} as Tpl);

  const handleSubmit = (values: any) => {
    request(`${api.tasktpls(curBusiItem.id)}`, {
      method: 'POST',
      body: JSON.stringify(values),
    }).then(() => {
      message.success(t('msg.create.success'));
      props.history.push({
        pathname: `/job-tpls`,
      });
    });
  };

  useEffect(() => {
    if (id) {
      setLoading(true);
      request(`${api.tasktpl(curBusiItem.id)}/${id}`).then((data) => {
        const { dat } = data;
        setData({
          ...dat.tpl,
          hosts: dat.hosts,
          grp: dat.grp,
        });
      }).finally(() => {
        setLoading(false);
      });
    }
  }, [id, curBusiItem.id]);

  return (
    <PageLayout hideCluster title={
      <>
        <RollbackOutlined className='back' onClick={() => history.push('/job-tpls')} />
        自愈脚本
      </>
    }>
      <div style={{ padding: 10 }}>
        <Card
          title="克隆自愈脚本"
        >
          <Spin spinning={loading}>
            {
              data.title ?
              <TplForm
                onSubmit={handleSubmit}
                initialValues={data}
                footer={
                  <div>
                    <Button type="primary" htmlType="submit" style={{ marginRight: 8 }}> 
                      {t('form.submit')}
                    </Button>
                  </div>
                }
              /> : null
            }
          </Spin>
        </Card>
      </div>
    </PageLayout>
  )
}
Example #5
Source File: modify.tsx    From fe-v5 with Apache License 2.0 5 votes vote down vote up
Modify = (props: any) => {
  const history = useHistory();
  const id = _.get(props, 'match.params.id');
  const { curBusiItem } = useSelector<RootState, CommonStoreState>((state) => state.common);
  const { t } = useTranslation();
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState<any>({});
  const handleSubmit = (values: any) => {
    request(`${api.tasktpl(curBusiItem.id)}/${id}`, {
      method: 'PUT',
      body: JSON.stringify(values),
    }).then(() => {
      message.success(t('msg.modify.success'));
      props.history.push({
        pathname: `/job-tpls`,
      });
    });
  };

  useEffect(() => {
    if (id) {
      setLoading(true);
      request(`${api.tasktpl(curBusiItem.id)}/${id}`).then((data) => {
        const { dat } = data;
        setData({
          ...dat.tpl,
          hosts: dat.hosts,
          grp: dat.grp,
        });
      }).finally(() => {
        setLoading(false);
      });
    }
  }, [id, curBusiItem.id]);

  return (
    <PageLayout hideCluster title={
      <>
        <RollbackOutlined className='back' onClick={() => history.push('/job-tpls')} />
        自愈脚本
      </>
    }>
      <div style={{ padding: 10 }}>
        <Card
          title="修改自愈脚本"
        >
        <Spin spinning={loading}>
          {
            data.title ?
            <TplForm
              onSubmit={handleSubmit}
              initialValues={data}
              footer={
                <Button type="primary" htmlType="submit">
                  {t('form.submit')}
                </Button>
              }
            /> : null
          }
        </Spin>
        </Card>
      </div>
    </PageLayout>
  )
}
Example #6
Source File: PluginDrawer.tsx    From posthog-foss with MIT License 4 votes vote down vote up
export function PluginDrawer(): JSX.Element {
    const { user } = useValues(userLogic)
    const { preflight } = useValues(preflightLogic)
    const { editingPlugin, loading, editingSource, editingPluginInitialChanges } = useValues(pluginsLogic)
    const { editPlugin, savePluginConfig, uninstallPlugin, setEditingSource, generateApiKeysIfNeeded, patchPlugin } =
        useActions(pluginsLogic)

    const [form] = Form.useForm()

    const [invisibleFields, setInvisibleFields] = useState<string[]>([])
    const [requiredFields, setRequiredFields] = useState<string[]>([])

    useEffect(() => {
        if (editingPlugin) {
            form.setFieldsValue({
                ...(editingPlugin.pluginConfig.config || defaultConfigForPlugin(editingPlugin)),
                __enabled: editingPlugin.pluginConfig.enabled,
                ...editingPluginInitialChanges,
            })
            generateApiKeysIfNeeded(form)
        } else {
            form.resetFields()
        }
        updateInvisibleAndRequiredFields()
    }, [editingPlugin?.id, editingPlugin?.config_schema])

    const updateInvisibleAndRequiredFields = (): void => {
        determineAndSetInvisibleFields()
        determineAndSetRequiredFields()
    }

    const determineAndSetInvisibleFields = (): void => {
        const fieldsToSetAsInvisible = []
        for (const field of Object.values(getConfigSchemaArray(editingPlugin?.config_schema || {}))) {
            if (!field.visible_if || !field.key) {
                continue
            }
            const shouldBeVisible = field.visible_if.every(
                ([targetFieldName, targetFieldValue]: Array<string | undefined>) =>
                    doFieldRequirementsMatch(form, targetFieldName, targetFieldValue)
            )

            if (!shouldBeVisible) {
                fieldsToSetAsInvisible.push(field.key)
            }
        }
        setInvisibleFields(fieldsToSetAsInvisible)
    }

    const determineAndSetRequiredFields = (): void => {
        const fieldsToSetAsRequired = []
        for (const field of Object.values(getConfigSchemaArray(editingPlugin?.config_schema || {}))) {
            if (!field.required_if || !Array.isArray(field.required_if) || !field.key) {
                continue
            }
            const shouldBeRequired = field.required_if.every(
                ([targetFieldName, targetFieldValue]: Array<string | undefined>) =>
                    doFieldRequirementsMatch(form, targetFieldName, targetFieldValue)
            )
            if (shouldBeRequired) {
                fieldsToSetAsRequired.push(field.key)
            }
        }

        setRequiredFields(fieldsToSetAsRequired)
    }

    const isValidChoiceConfig = (fieldConfig: PluginConfigChoice): boolean => {
        return (
            Array.isArray(fieldConfig.choices) &&
            !!fieldConfig.choices.length &&
            !fieldConfig.choices.find((c) => typeof c !== 'string') &&
            !fieldConfig.secret
        )
    }

    const isValidField = (fieldConfig: PluginConfigSchema): boolean =>
        fieldConfig.type !== 'choice' || isValidChoiceConfig(fieldConfig)

    return (
        <>
            <Drawer
                forceRender={true}
                visible={!!editingPlugin}
                onClose={() => editPlugin(null)}
                width="min(90vw, 500px)"
                title={editingPlugin?.name}
                data-attr="plugin-drawer"
                footer={
                    <div style={{ display: 'flex' }}>
                        <Space style={{ flexGrow: 1 }}>
                            {editingPlugin &&
                                !editingPlugin.is_global &&
                                canInstallPlugins(user?.organization, editingPlugin.organization_id) && (
                                    <Popconfirm
                                        placement="topLeft"
                                        title="Are you sure you wish to uninstall this plugin completely?"
                                        onConfirm={() => uninstallPlugin(editingPlugin.name)}
                                        okText="Uninstall"
                                        cancelText="Cancel"
                                        className="plugins-popconfirm"
                                    >
                                        <Button
                                            style={{ color: 'var(--danger)', padding: 4 }}
                                            type="text"
                                            icon={<DeleteOutlined />}
                                            data-attr="plugin-uninstall"
                                        >
                                            Uninstall
                                        </Button>
                                    </Popconfirm>
                                )}
                            {preflight?.cloud &&
                                editingPlugin &&
                                canGloballyManagePlugins(user?.organization) &&
                                (editingPlugin.is_global ? (
                                    <Tooltip
                                        title={
                                            <>
                                                This plugin can currently be used by other organizations in this
                                                instance of PostHog. This action will <b>disable and hide it</b> for all
                                                organizations other than yours.
                                            </>
                                        }
                                    >
                                        <Button
                                            type="text"
                                            icon={<RollbackOutlined />}
                                            onClick={() => patchPlugin(editingPlugin.id, { is_global: false })}
                                            style={{ padding: 4 }}
                                        >
                                            Make local
                                        </Button>
                                    </Tooltip>
                                ) : (
                                    <Tooltip
                                        title={
                                            <>
                                                This action will mark this plugin as installed for{' '}
                                                <b>all organizations</b> in this instance of PostHog.
                                            </>
                                        }
                                    >
                                        <Button
                                            type="text"
                                            icon={<GlobalOutlined />}
                                            onClick={() => patchPlugin(editingPlugin.id, { is_global: true })}
                                            style={{ padding: 4 }}
                                        >
                                            Make global
                                        </Button>
                                    </Tooltip>
                                ))}
                        </Space>
                        <Space>
                            <Button onClick={() => editPlugin(null)} data-attr="plugin-drawer-cancel">
                                Cancel
                            </Button>
                            <Button
                                type="primary"
                                loading={loading}
                                onClick={form.submit}
                                data-attr="plugin-drawer-save"
                            >
                                Save
                            </Button>
                        </Space>
                    </div>
                }
            >
                <Form form={form} layout="vertical" name="basic" onFinish={savePluginConfig}>
                    {editingPlugin ? (
                        <div>
                            <div style={{ display: 'flex', marginBottom: 16 }}>
                                <PluginImage
                                    pluginType={editingPlugin.plugin_type}
                                    url={editingPlugin.url}
                                    size="large"
                                />
                                <div style={{ flexGrow: 1, paddingLeft: 16 }}>
                                    {endWithPunctation(editingPlugin.description)}
                                    <div style={{ marginTop: 5 }}>
                                        {editingPlugin?.plugin_type === 'local' && editingPlugin.url ? (
                                            <LocalPluginTag url={editingPlugin.url} title="Installed Locally" />
                                        ) : editingPlugin.plugin_type === 'source' ? (
                                            <SourcePluginTag />
                                        ) : null}
                                        {editingPlugin.url && (
                                            <a href={editingPlugin.url}>
                                                <i>⤷ Learn more</i>
                                            </a>
                                        )}
                                    </div>
                                    <div style={{ display: 'flex', alignItems: 'center', marginTop: 5 }}>
                                        <Form.Item
                                            fieldKey="__enabled"
                                            name="__enabled"
                                            style={{ display: 'inline-block', marginBottom: 0 }}
                                            data-attr="plugin-enabled-switch"
                                        >
                                            <EnabledDisabledSwitch />
                                        </Form.Item>
                                    </div>
                                </div>
                            </div>

                            {editingPlugin.plugin_type === 'source' ? (
                                <div>
                                    <Button
                                        type={editingSource ? 'default' : 'primary'}
                                        icon={<CodeOutlined />}
                                        onClick={() => setEditingSource(!editingSource)}
                                        data-attr="plugin-edit-source"
                                    >
                                        Edit Source
                                    </Button>
                                </div>
                            ) : null}

                            {editingPlugin.capabilities && Object.keys(editingPlugin.capabilities).length > 0 ? (
                                <>
                                    <h3 className="l3" style={{ marginTop: 32 }}>
                                        Capabilities
                                    </h3>

                                    <div style={{ marginTop: 5 }}>
                                        {[
                                            ...editingPlugin.capabilities.methods,
                                            ...editingPlugin.capabilities.scheduled_tasks,
                                        ]
                                            .filter(
                                                (capability) => !['setupPlugin', 'teardownPlugin'].includes(capability)
                                            )
                                            .map((capability) => (
                                                <Tooltip title={capabilitiesInfo[capability] || ''} key={capability}>
                                                    <Tag className="plugin-capabilities-tag">{capability}</Tag>
                                                </Tooltip>
                                            ))}
                                        {editingPlugin.capabilities.jobs.map((jobName) => (
                                            <Tooltip title="Custom job" key={jobName}>
                                                <Tag className="plugin-capabilities-tag">{jobName}</Tag>
                                            </Tooltip>
                                        ))}
                                    </div>
                                </>
                            ) : null}

                            {editingPlugin.pluginConfig.id && (
                                <PluginJobOptions
                                    plugin={editingPlugin}
                                    pluginConfigId={editingPlugin.pluginConfig.id}
                                />
                            )}

                            <h3 className="l3" style={{ marginTop: 32 }}>
                                Configuration
                            </h3>
                            {getConfigSchemaArray(editingPlugin.config_schema).length === 0 ? (
                                <div>This plugin is not configurable.</div>
                            ) : null}
                            {getConfigSchemaArray(editingPlugin.config_schema).map((fieldConfig, index) => (
                                <React.Fragment key={fieldConfig.key || `__key__${index}`}>
                                    {fieldConfig.markdown && (
                                        <ReactMarkdown source={fieldConfig.markdown} linkTarget="_blank" />
                                    )}
                                    {fieldConfig.type && isValidField(fieldConfig) ? (
                                        <Form.Item
                                            hidden={!!fieldConfig.key && invisibleFields.includes(fieldConfig.key)}
                                            label={
                                                <>
                                                    {fieldConfig.secret && <SecretFieldIcon />}
                                                    {fieldConfig.name || fieldConfig.key}
                                                </>
                                            }
                                            extra={
                                                fieldConfig.hint && (
                                                    <small>
                                                        <div style={{ height: 2 }} />
                                                        <ReactMarkdown source={fieldConfig.hint} linkTarget="_blank" />
                                                    </small>
                                                )
                                            }
                                            name={fieldConfig.key}
                                            required={
                                                fieldConfig.required ||
                                                (!!fieldConfig.key && requiredFields.includes(fieldConfig.key))
                                            }
                                            rules={[
                                                {
                                                    required:
                                                        fieldConfig.required ||
                                                        (!!fieldConfig.key && requiredFields.includes(fieldConfig.key)),
                                                    message: 'Please enter a value!',
                                                },
                                            ]}
                                        >
                                            <PluginField
                                                fieldConfig={fieldConfig}
                                                onChange={updateInvisibleAndRequiredFields}
                                            />
                                        </Form.Item>
                                    ) : (
                                        <>
                                            {fieldConfig.type ? (
                                                <p style={{ color: 'var(--danger)' }}>
                                                    Invalid config field <i>{fieldConfig.name || fieldConfig.key}</i>.
                                                </p>
                                            ) : null}
                                        </>
                                    )}
                                </React.Fragment>
                            ))}
                        </div>
                    ) : null}
                </Form>
            </Drawer>
            {editingPlugin?.plugin_type === 'source' ? <PluginSource /> : null}
        </>
    )
}
Example #7
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 #8
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 #9
Source File: index.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
PageLayout: React.FC<IPageLayoutProps> = ({ icon, title, rightArea, children, customArea, showBack, onChangeCluster, hideCluster = true }) => {
  const { t, i18n } = useTranslation();
  const history = useHistory();
  const dispatch = useDispatch();
  let { profile } = useSelector<AccountRootState, accountStoreState>((state) => state.account);
  const { clusters } = useSelector<CommonRootState, CommonStoreState>((state) => state.common);
  const localCluster = localStorage.getItem('curCluster');
  const [curCluster, setCurCluster] = useState<string>(localCluster || clusters[0]);
  if (!localCluster && clusters.length > 0) {
    setCurCluster(clusters[0]);
    localStorage.setItem('curCluster', clusters[0]);
    dispatch({
      type: 'common/saveData',
      prop: 'curCluster',
      data: clusters[0],
    });
  }

  const menu = (
    <Menu>
      <Menu.Item
        onClick={() => {
          history.push('/account/profile/info');
        }}
      >
        {t('个人信息')}
      </Menu.Item>
      <Menu.Item
        onClick={() => {
          Logout().then((res) => {
            localStorage.removeItem('access_token');
            localStorage.removeItem('refresh_token');
            dispatch({
              type: 'common/saveData',
              prop: 'clusters',
              data: [],
            });
            dispatch({
              type: 'common/saveData',
              prop: 'busiGroups',
              data: [],
            });
            history.push('/login');
          });
        }}
      >
        {t('退出')}
      </Menu.Item>
    </Menu>
  );

  const clusterMenu = (
    <Menu selectedKeys={[curCluster]}>
      {clusters.map((cluster) => (
        <Menu.Item
          key={cluster}
          onClick={(_) => {
            setCurCluster(cluster);
            onChangeCluster && onChangeCluster(cluster);
            localStorage.setItem('curCluster', cluster);
            dispatch({
              type: 'common/saveData',
              prop: 'curCluster',
              data: cluster,
            });
          }}
        >
          {cluster}
        </Menu.Item>
      ))}
    </Menu>
  );

  return (
    <div className={'page-wrapper'}>
      {customArea ? (
        <div className={'page-top-header'}>{customArea}</div>
      ) : (
        <div className={'page-top-header'}>
          <div className={'page-header-content'}>
            <div className={'page-header-title'}>
              {showBack && (
                <RollbackOutlined
                  onClick={() => history.goBack()}
                  style={{
                    marginRight: '5px',
                  }}
                />
              )}
              {icon}
              {title}
            </div>

            {/* <div className={'page-header-right-area'}>{rightArea}</div> */}
            <div className={'page-header-right-area'}>
              {import.meta.env.VITE_DOC_LINK && (
                <a href={import.meta.env.VITE_DOC_LINK as string} target='_blank' style={{ marginRight: 20 }}>
                  文档
                </a>
              )}
              {!hideCluster && (
                <div style={{ marginRight: 20 }}>
                  集群:
                  <Dropdown overlay={clusterMenu}>
                    <Button>
                      {curCluster} <DownOutlined />
                    </Button>
                  </Dropdown>
                </div>
              )}
              {/* 文案完善了再打开 */}
              {/* <span
                className='language'
                onClick={() => {
                  let language = i18n.language == 'en' ? 'zh' : 'en';
                  i18n.changeLanguage(language);
                  localStorage.setItem('language', language);
                }}
              >
                {i18n.language == 'zh' ? 'En' : '中'}
              </span> */}
              <Dropdown overlay={menu} trigger={['click']}>
                <span className='avator'>
                  <img src={profile.portrait || '/image/avatar1.png'} alt='' />
                  <span className='display-name'>{profile.nickname || profile.username}</span>
                  <DownOutlined />
                </span>
              </Dropdown>
            </div>
          </div>
        </div>
      )}
      {children && children}
    </div>
  );
}
Example #10
Source File: Title.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
export default function Title(props: IProps) {
  const { curCluster, clusters, setCurCluster, dashboard, setDashboard, refresh, range, setRange, step, setStep, refreshFlag, setRefreshFlag, refreshRef, onAddPanel } = props;
  const { id, name } = dashboard;
  const history = useHistory();
  const [titleEditing, setTitleEditing] = useState(false);
  const titleRef = useRef<any>(null);
  const handleModifyTitle = async (newName) => {
    updateDashboard(id, { ...dashboard, name: newName }).then(() => {
      setDashboard({ ...dashboard, name: newName });
      setTitleEditing(false);
    });
  };
  const { run } = useThrottleFn(
    () => {
      if ('start' in range && range.start && range.end) {
        const diff = range.end - range.start;
        const now = moment().unix();
        setRange({
          end: now,
          start: now - diff,
        });
      } else if ('unit' in range && range.unit) {
        const newRefreshFlag = _.uniqueId('refreshFlag_');
        setRange({
          ...range,
          refreshFlag: newRefreshFlag,
        });
        setRefreshFlag(newRefreshFlag);
      }
      refresh(false);
    },
    { wait: 1000 },
  );

  return (
    <div className='dashboard-detail-header'>
      <div className='dashboard-detail-header-left'>
        <RollbackOutlined className='back' onClick={() => history.push('/dashboards')} />
        {titleEditing ? (
          <Input
            ref={titleRef}
            defaultValue={name}
            onPressEnter={(e: any) => {
              handleModifyTitle(e.target.value);
            }}
          />
        ) : (
          <div className='title'>{dashboard.name}</div>
        )}
        {!titleEditing ? (
          <EditOutlined
            className='edit'
            onClick={() => {
              setTitleEditing(!titleEditing);
            }}
          />
        ) : (
          <>
            <Button size='small' style={{ marginRight: 5, marginLeft: 5 }} onClick={() => setTitleEditing(false)}>
              取消
            </Button>
            <Button
              size='small'
              type='primary'
              onClick={() => {
                handleModifyTitle(titleRef.current.state.value);
              }}
            >
              保存
            </Button>
          </>
        )}
      </div>
      <div className='dashboard-detail-header-right'>
        <Space>
          <div>
            <Dropdown
              trigger={['click']}
              overlay={
                <Menu>
                  {_.map([{ type: 'row', name: '分组' }, ...visualizations], (item) => {
                    return (
                      <Menu.Item
                        key={item.type}
                        onClick={() => {
                          onAddPanel(item.type);
                        }}
                      >
                        {item.name}
                      </Menu.Item>
                    );
                  })}
                </Menu>
              }
            >
              <Button type='primary' icon={<AddPanelIcon />}>
                添加图表
              </Button>
            </Dropdown>
          </div>
          <div style={{ display: 'flex', alignItems: 'center' }}>
            集群:
            <Dropdown
              overlay={
                <Menu selectedKeys={[curCluster]}>
                  {clusters.map((cluster) => (
                    <Menu.Item
                      key={cluster}
                      onClick={(_) => {
                        setCurCluster(cluster);
                        localStorage.setItem('curCluster', cluster);
                        refresh();
                      }}
                    >
                      {cluster}
                    </Menu.Item>
                  ))}
                </Menu>
              }
            >
              <Button>
                {curCluster} <DownOutlined />
              </Button>
            </Dropdown>
          </div>
          <DateRangePicker value={range} onChange={setRange} />
          <Resolution onChange={(v) => setStep(v)} initialValue={step} />
          <Refresh onRefresh={run} ref={refreshRef} />
        </Space>
      </div>
    </div>
  );
}
Example #11
Source File: detail.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
export default function DashboardDetail() {
  const refreshRef = useRef<{ closeRefresh: Function }>();
  const { t } = useTranslation();
  const { id, busiId } = useParams<URLParam>();
  const [groupForm] = Form.useForm();
  const history = useHistory();
  const Ref = useRef<any>(null);
  const { clusters } = useSelector<CommonRootState, CommonStoreState>((state) => state.common);
  const localCluster = localStorage.getItem('curCluster');
  const [curCluster, setCurCluster] = useState<string>(localCluster || clusters[0]);
  if (!localCluster && clusters.length > 0) {
    setCurCluster(clusters[0]);
    localStorage.setItem('curCluster', clusters[0]);
  }
  const [dashboard, setDashboard] = useState<Dashboard>({
    create_by: '',
    favorite: 0,
    id: 0,
    name: '',
    tags: '',
    update_at: 0,
    update_by: '',
  });
  const [step, setStep] = useState<number | null>(null);
  const [titleEditing, setTitleEditing] = useState(false);
  const [chartGroup, setChartGroup] = useState<Group[]>([]);
  const [variableConfig, setVariableConfig] = useState<VariableType>();
  const [variableConfigWithOptions, setVariableConfigWithOptions] = useState<VariableType>();
  const [dashboardLinks, setDashboardLinks] = useState<ILink[]>();
  const [groupModalVisible, setGroupModalVisible] = useState(false);
  const [chartModalVisible, setChartModalVisible] = useState(false);
  const [chartModalInitValue, setChartModalInitValue] = useState<Chart | null>();
  const [range, setRange] = useState<Range>({
    start: 0,
    end: 0,
  });
  const [refreshFlag, setRefreshFlag] = useState(_.uniqueId('refreshFlag_'));
  const { run } = useThrottleFn(
    () => {
      if ('start' in range && range.start && range.end) {
        const diff = range.end - range.start;
        const now = moment().unix();
        setRange({
          end: now,
          start: now - diff,
        });
      } else if ('unit' in range && range.unit) {
        const newRefreshFlag = _.uniqueId('refreshFlag_');
        setRange({
          ...range,
          refreshFlag: newRefreshFlag,
        });
        setRefreshFlag(newRefreshFlag);
      }
      init(false);
    },
    { wait: 1000 },
  );

  useEffect(() => {
    init();
  }, []);

  const init = (needUpdateVariable = true) => {
    getSingleDashboard(busiId, id).then((res) => {
      setDashboard(res.dat);
      if (res.dat.configs) {
        const configs = JSON.parse(res.dat.configs);
        setVariableConfig(configs);
        setVariableConfigWithOptions(configs);
        setDashboardLinks(configs.links);
      }
    });
    getChartGroup(busiId, id).then((res) => {
      let arr = res.dat || [];
      setChartGroup(
        arr
          .sort((a, b) => a - b)
          .map((item) => {
            item.updateTime = Date.now(); // 前端拓展一个更新时间字段,用来主动刷新ChartGroup
            return item;
          }),
      );
    });
  };

  const handleDateChange = (e) => {
    setRange(e);
  };

  const handleEdit = () => {
    setTitleEditing(!titleEditing);
  };

  const handleModifyTitle = async (e) => {
    await updateSingleDashboard(busiId, id, { ...dashboard, name: e.target.value });
    // await init();
    setDashboard({ ...dashboard, name: e.target.value });
    setTitleEditing(false);
  };

  const handleAddChart = (gid: number) => {
    groupId = gid;
    editor({
      visible: true,
      variableConfig: variableConfigWithOptions,
      cluster: curCluster,
      busiId,
      groupId,
      id,
      initialValues: {
        type: 'timeseries',
        targets: [
          {
            refId: 'A',
            expr: '',
          },
        ],
      },
      onOK: () => {
        handleChartConfigVisibleChange(true);
      },
    });
    // setChartModalVisible(true);
  }; //group是为了让detail组件知道当前需要刷新的是哪个chartGroup,item是为了获取待编辑的信息

  const handleUpdateChart = (group: Group, item: Chart) => {
    groupId = group.id;
    setChartModalInitValue(item);

    if (semver.valid(item.configs.version)) {
      editor({
        visible: true,
        variableConfig,
        cluster: curCluster,
        busiId,
        groupId,
        id,
        initialValues: {
          ...item.configs,
          id: item.id,
        },
        onOK: () => {
          handleChartConfigVisibleChange(true);
        },
      });
    } else {
      setChartModalVisible(true);
    }
  };

  const handleDelChart = async (group: Group, item: Chart) => {
    groupId = group.id;
    await removeChart(busiId, item.id as any);
    refreshUpdateTimeByChartGroupId();
  };

  const handleCloneChart = async (group: Group, item: Chart) => {
    groupId = group.id;
    const configsClone = _.cloneDeep(item.configs);
    configsClone.layout = {
      w: configsClone.layout.w,
      h: configsClone.layout.h,
    };
    await createChart(busiId, {
      configs: JSON.stringify(configsClone),
      weight: 0,
      group_id: groupId,
    });
    refreshUpdateTimeByChartGroupId();
  };

  const handleShareChart = async (group: Group, item: any) => {
    const serielData = {
      dataProps: {
        ...item.configs,
        targets: _.map(item.configs.targets, (target) => {
          const realExpr = variableConfigWithOptions ? replaceExpressionVars(target.expr, variableConfigWithOptions, variableConfigWithOptions.var.length, id) : target.expr;
          return {
            ...target,
            expr: realExpr,
          };
        }),
        step,
        range,
      },
      curCluster: localStorage.getItem('curCluster'),
    };
    SetTmpChartData([
      {
        configs: JSON.stringify(serielData),
      },
    ]).then((res) => {
      const ids = res.dat;
      window.open('/chart/' + ids);
    });
  };

  const handleAddOrUpdateChartGroup = async () => {
    await groupForm.validateFields();
    let obj = groupForm.getFieldsValue();

    if (isAddGroup) {
      let weightArr = chartGroup.map((item) => item.weight);
      let weight = Math.max(...weightArr) + 1;
      await createChartGroup(busiId, { ...obj, weight, dashboard_id: Number(id) });
    } else {
      let group = chartGroup.find((item) => item.id === groupId);
      await updateChartGroup(busiId, [{ dashboard_id: Number(id), ...group, ...obj }]);
    }

    init();
    isAddGroup = true;
    setGroupModalVisible(false);
  };

  const handleUpdateChartGroup = (group: Group) => {
    groupId = group.id;
    isAddGroup = false;
    groupForm.setFieldsValue({ name: group.name });
    setGroupModalVisible(true);
  };

  const handleMoveUpChartGroup = async (group: Group) => {
    const { weight } = group;
    let lessWeightGroup = chartGroup.find((item) => item.weight === weight - 1);
    if (!lessWeightGroup) return;
    lessWeightGroup.weight = weight;
    group.weight = weight - 1;
    await updateChartGroup(busiId, [lessWeightGroup, group]);
    init();
  };

  const handleMoveDownChartGroup = async (group: Group) => {
    const { weight } = group;
    let lessWeightGroup = chartGroup.find((item) => item.weight === weight + 1);
    if (!lessWeightGroup) return;
    lessWeightGroup.weight = weight;
    group.weight = weight + 1;
    await updateChartGroup(busiId, [lessWeightGroup, group]);
    init();
  };

  const handleDelChartGroup = async (id: number) => {
    await delChartGroup(busiId, id);
    message.success(t('删除分组成功'));
    init();
    setGroupModalVisible(false);
  };

  const refreshUpdateTimeByChartGroupId = () => {
    let groupIndex = chartGroup.findIndex((item) => item.id === groupId);
    if (groupIndex < 0) return;
    let newChartGroup = [...chartGroup];
    newChartGroup[groupIndex].updateTime = Date.now();
    setChartGroup(newChartGroup);
  };

  const handleChartConfigVisibleChange = (b) => {
    setChartModalVisible(false);
    setChartModalInitValue(null);
    b && refreshUpdateTimeByChartGroupId();
  };

  const handleVariableChange = (value, b, valueWithOptions) => {
    let dashboardConfigs: any = {};
    try {
      if (dashboard.configs) {
        dashboardConfigs = JSON.parse(dashboard.configs);
      }
    } catch (e) {
      console.error(e);
    }
    dashboardConfigs.var = value.var;
    b && updateSingleDashboard(busiId, id, { ...dashboard, configs: JSON.stringify(dashboardConfigs) });
    setVariableConfig(dashboardConfigs);
    valueWithOptions && setVariableConfigWithOptions(valueWithOptions);
  };

  const stopAutoRefresh = () => {
    refreshRef.current?.closeRefresh();
  };
  const clusterMenu = (
    <Menu selectedKeys={[curCluster]}>
      {clusters.map((cluster) => (
        <Menu.Item
          key={cluster}
          onClick={(_) => {
            setCurCluster(cluster);
            localStorage.setItem('curCluster', cluster);
            init();
          }}
        >
          {cluster}
        </Menu.Item>
      ))}
    </Menu>
  );
  return (
    <PageLayout
      customArea={
        <div className='dashboard-detail-header'>
          <div className='dashboard-detail-header-left'>
            <RollbackOutlined className='back' onClick={() => history.push('/dashboards')} />
            {titleEditing ? <Input ref={Ref} defaultValue={dashboard.name} onPressEnter={handleModifyTitle} /> : <div className='title'>{dashboard.name}</div>}
            {!titleEditing ? (
              <EditOutlined className='edit' onClick={handleEdit} />
            ) : (
              <>
                <Button size='small' style={{ marginRight: 5, marginLeft: 5 }} onClick={() => setTitleEditing(false)}>
                  取消
                </Button>
                <Button
                  size='small'
                  type='primary'
                  onClick={() => {
                    handleModifyTitle({ target: { value: Ref.current.state.value } });
                  }}
                >
                  保存
                </Button>
              </>
            )}
          </div>
          <div className='dashboard-detail-header-right'>
            <Space>
              <div style={{ display: 'flex', alignItems: 'center' }}>
                集群:
                <Dropdown overlay={clusterMenu}>
                  <Button>
                    {curCluster} <DownOutlined />
                  </Button>
                </Dropdown>
              </div>
              <DateRangePicker onChange={handleDateChange} />
              <Resolution onChange={(v) => setStep(v)} initialValue={step} />
              <Refresh onRefresh={run} ref={refreshRef} />
            </Space>
          </div>
        </div>
      }
    >
      <div className='dashboard-detail-content'>
        <div className='dashboard-detail-content-header'>
          <div className='variable-area'>
            <VariableConfig onChange={handleVariableChange} value={variableConfig} cluster={curCluster} range={range} id={id} onOpenFire={stopAutoRefresh} />
          </div>
          <DashboardLinks
            value={dashboardLinks}
            onChange={(v) => {
              let dashboardConfigs: any = {};
              try {
                if (dashboard.configs) {
                  dashboardConfigs = JSON.parse(dashboard.configs);
                }
              } catch (e) {
                console.error(e);
              }
              dashboardConfigs.links = v;
              updateSingleDashboard(busiId, id, {
                ...dashboard,
                configs: JSON.stringify(dashboardConfigs),
              });
              setDashboardLinks(v);
            }}
          />
        </div>

        <div className='charts'>
          {chartGroup.map((item, i) => (
            <ChartGroup
              id={id}
              cluster={curCluster}
              busiId={busiId}
              key={i}
              step={step}
              groupInfo={item}
              onAddChart={handleAddChart}
              onUpdateChart={handleUpdateChart}
              onCloneChart={handleCloneChart}
              onShareChart={handleShareChart}
              onUpdateChartGroup={handleUpdateChartGroup}
              onMoveUpChartGroup={handleMoveUpChartGroup}
              onMoveDownChartGroup={handleMoveDownChartGroup}
              onDelChart={handleDelChart}
              onDelChartGroup={handleDelChartGroup}
              range={range}
              refreshFlag={refreshFlag}
              variableConfig={variableConfigWithOptions!}
              moveUpEnable={i > 0}
              moveDownEnable={i < chartGroup.length - 1}
            />
          ))}
          <Button
            block
            icon={<PlusOutlined />}
            style={{
              paddingRight: 0,
            }}
            onClick={() => {
              groupForm.setFieldsValue({ name: '' });
              setGroupModalVisible(true);
            }}
          >
            {t('新增图表分组')}
          </Button>
        </div>
      </div>
      <Modal
        title={isAddGroup ? t('新建分组') : t('更新分组名称')}
        visible={groupModalVisible}
        onOk={handleAddOrUpdateChartGroup}
        onCancel={() => {
          setGroupModalVisible(false);
        }}
      >
        <Form {...layout} form={groupForm}>
          <Form.Item
            label={t('分组名称')}
            name='name'
            rules={[
              {
                required: true,
                message: t('请输入名称'),
              },
            ]}
          >
            <Input />
          </Form.Item>
        </Form>
      </Modal>

      {chartModalVisible && (
        <ChartConfigModal
          id={id}
          cluster={curCluster}
          busiId={busiId}
          initialValue={chartModalInitValue}
          groupId={groupId}
          show={chartModalVisible}
          onVisibleChange={handleChartConfigVisibleChange}
          variableConfig={variableConfigWithOptions}
        />
      )}
    </PageLayout>
  );
}
Example #12
Source File: add.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
Add = (props: any) => {
  const history = useHistory();
  const query = queryString.parse(_.get(props, 'location.search'));
  const { curBusiItem } = useSelector<RootState, CommonStoreState>((state) => state.common);
  const { t } = useTranslation();
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState();
  const [action, setAction] = useState('');
  const handleSubmit = (values: any) => {
    if (action) {
      request(api.tasks(curBusiItem.id), {
        method: 'POST',
        body: JSON.stringify({
          ...values,
          action,
        }),
      }).then((res) => {
        message.success(t('msg.create.success'));
        props.history.push({
          pathname: `/job-tasks/${res.dat}/result`,
        });
      });
    }
  };

  useEffect(() => {
    if (_.isPlainObject(query)) {
      if (query.tpl !== undefined) {
        setLoading(true);
        request(`${api.tasktpl(curBusiItem.id)}/${query.tpl}`, {
        }).then((data) => {
          setData({
            ...data.dat.tpl,
            hosts: data.dat.hosts,
          });
        }).finally(() => {
          setLoading(false);
        });
      } else if (query.task !== undefined) {
        setLoading(true);
        request(`${api.task(curBusiItem.id)}/${query.task}`, {
        }).then((data) => {
          setData({
            ...data.dat.meta,
            hosts: _.map(data.dat.hosts, (host) => {
              return host.host;
            }),
          });
        }).finally(() => {
          setLoading(false);
        });
      }
    }
  }, []);

  return (
    <PageLayout hideCluster title={
      query.tpl ?
      <>
        <RollbackOutlined className='back' onClick={() => history.push('/job-tpls')} />
        自愈脚本
      </> :
      <>
        <RollbackOutlined className='back' onClick={() => history.push('/job-tasks')} />
        执行历史
      </>
    }>
      <div style={{ padding: 10 }}>
        <div style={{ background: 'none' }}>
        <Row gutter={20}>
          <Col span={18}>
            <Card
              title={
                query.tpl ? '创建任务' : query.task ? '克隆任务' : '创建临时任务'
              }
            >
              <Spin spinning={loading}>
                {
                  data || (!query.tpl && !query.task) ?
                  <TplForm
                    type="task"
                    initialValues={data}
                    onSubmit={handleSubmit}
                    footer={
                      <div>
                        <Button type="primary" htmlType="submit" style={{ marginRight: 10 }}
                          onClick={() => {
                            setAction('pause');
                          }}
                        >
                          保存暂不执行
                        </Button>
                        <Button type="primary" htmlType="submit"
                          onClick={() => {
                            setAction('start');
                          }}
                        >
                          保存立刻执行
                        </Button>
                      </div>
                    }
                  /> : null
                }
              </Spin>
            </Card>
          </Col>
          <Col span={6}>
            <Alert
              showIcon
              message="提示信息"
              description="如果你的角色是管理员,则可以在任意机器执行脚本;否则,只能对有管理权限的业务组下的机器执行脚本"
              type="warning"
            />
          </Col>
        </Row>
        </div>
      </div>
    </PageLayout>
  );
}
Example #13
Source File: detail.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
Detail = (props: any) => {
  const history = useHistory();
  const { curBusiItem } = useSelector<RootState, CommonStoreState>((state) => state.common);
  const { t } = useTranslation();
  const taskId = _.get(props, 'match.params.id');
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState({} as any);

  useEffect(() => {
    if (taskId !== undefined) {
      setLoading(true);
      request(`${api.task(curBusiItem.id)}/${taskId}`).then((data) => {
        setData({
          ...data.dat.meta,
          hosts: _.map(data.dat.hosts, (host) => {
            return host.host;
          }),
        });
      }).finally(() => {
        setLoading(false);
      });
    }
  }, [taskId]);

  return (
    <PageLayout hideCluster title={
      <>
        <RollbackOutlined className='back' onClick={() => history.push('/job-tasks')} />
        执行历史
      </>
    }>
      <div style={{ padding: 10 }}>
        <Card
          title={data.title}
        >
        <Spin spinning={loading}>
          <div className="job-task-table">
            <div className="ant-table ant-table-default ant-table-bordered">
              <div className="ant-table-content">
                <div className="ant-table-body">
                  <table>
                    <colgroup>
                      <col style={{ width: 100, minWidth: 100 }} />
                      <col />
                    </colgroup>
                    <tbody className="ant-table-tbody">
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('task.title')}</td>
                        <td>{data.title}</td>
                      </tr>
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('task.creator')}</td>
                        <td>{data.creator} @ {moment(data.created).format('YYYY-MM-DD HH:mm:ss')}</td>
                      </tr>
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('task.control.params')}</td>
                        <td>
                          {t('task.account')}:{data.account}
                          <Divider type="vertical" />
                          {t('task.batch')}:{data.batch}
                          <Divider type="vertical" />
                          {t('task.tolerance')}:{data.tolerance}
                          <Divider type="vertical" />
                          {t('task.timeout')}:{data.timeout}
                        </td>
                      </tr>
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('task.script')}</td>
                        <td>
                          <Editor value={data.script} readOnly height="200px" />
                        </td>
                      </tr>
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('task.script.args')}</td>
                        <td>{data.args}</td>
                      </tr>
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('task.pause')}</td>
                        <td>{data.pause}</td>
                      </tr>
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('task.host.list')}</td>
                        <td>
                          {
                            _.map(data.hosts, (host) => {
                              return <div key={host}>{host}</div>;
                            })
                          }
                        </td>
                      </tr>
                    </tbody>
                  </table>
                </div>
              </div>
            </div>
          </div>
          <div style={{ marginTop: 10 }}>
            <Link to={{ pathname: '/job-tasks/add', search: `task=${taskId}` }}>
              <Button type="primary">{t('task.clone.new')}</Button>
            </Link>
            <Link style={{ marginLeft: 8 }} to={{ pathname: `/job-tasks` }}>
              <Button>返回</Button>
            </Link>
          </div>
        </Spin>
      </Card>
      </div>
    </PageLayout>
  );
}
Example #14
Source File: result.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
index = (props: any) => {
  const taskResultCls = 'job-task-result';
  const history = useHistory();
  const { curBusiItem } = useSelector<RootState, CommonStoreState>((state) => state.common);
  const { params } = props.match;
  const taskId = params.id;
  const { t, i18n } = useTranslation();
  const [activeStatus, setActiveStatus] = useState<string[]>();
  const [data, setData] = useState({} as any);
  const [hosts, setHosts] = useState<HostItem[]>([]);
  const [loading, setLoading] = useState(false);
  const getTableData = () => {
    setLoading(true)
    return request(`${api.task(curBusiItem.id)}/${params.id}`).then((data) => {
      setData({
        ...data.dat.meta,
        action: data.dat.action,
      });
      setHosts(data.dat.hosts);
    }).finally(() => {
      setLoading(false);
    });
  };
  useEffect(() => {
    getTableData();
  }, []);
  let filteredHosts = _.cloneDeep(hosts);
  if (activeStatus) {
    filteredHosts = _.filter(filteredHosts, (item: any) => {
      return _.includes(activeStatus, item.status);
    });
  }

  const handleHostAction = (host: string, action: string) => {
    request(`${api.task(curBusiItem.id)}/${taskId}/host/${host}/action`, {
      method: 'PUT',
      body: JSON.stringify({
        action,
      }),
    }).then(() => {
      getTableData();
    });
  };

  const handleTaskAction = (action: string) => {
    request(`${api.task(curBusiItem.id)}/${taskId}/action`, {
      method: 'PUT',
      body: JSON.stringify({
        action,
      }),
    }).then(() => {
      getTableData();
    });
  };

  const renderHostStatusFilter = () => {
    const groupedHosts = _.groupBy(hosts, 'status');
    return _.map(groupedHosts, (chosts, status) => {
      return {
        text: `${status} (${chosts.length})`,
        value: status
      }
    });
  }

  const columns: ColumnProps<HostItem>[] = [
    {
      title: (
        <FieldCopy
          dataIndex="host"
          hasSelected={false}
          data={filteredHosts}
        />
      ),
      dataIndex: 'host',
    }, {
      title: t('task.status'),
      dataIndex: 'status',
      filters: renderHostStatusFilter(),
      onFilter: (value: string, record) => {
        return record.status === value;
      },
      render: (text) => {
        if (text === 'success') {
          return <Tag color="#87d068">{text}</Tag>;
        } else if (text === 'cancelled' || text === 'ignored') {
          return <Tag color="#ec971f">{text}</Tag>;
        } else if (text === 'failed' || text === 'killfailed' || text === 'timeout') {
          return <Tag color="#f50">{text}</Tag>;
        }
        return <Tag>{text}</Tag>;
      },
    }, {
      title: t('task.output'),
      render: (_text, record) => {
        return (
          <span>
            <Link
              to={`/job-task/${curBusiItem.id}/output/${params.id}/${record.host}/stdout`}
              target="_blank"
            >
              stdout
            </Link>
            <Divider type="vertical" />
            <a
              href={`/job-task/${curBusiItem.id}/output/${params.id}/${record.host}/stderr`}
              target="_blank"
            >
              stderr
            </a>
          </span>
        );
      },
    },
  ];
  if (!data.done) {
    columns.push({
      title: t('table.operations'),
      render: (_text, record) => {
        return (
          <span>
            <a onClick={() => handleHostAction(record.host, 'ignore')}>ignore</a>
            <Divider type="vertical" />
            <a onClick={() => handleHostAction(record.host, 'redo')}>redo</a>
            <Divider type="vertical" />
            <a onClick={() => handleHostAction(record.host, 'kill')}>kill</a>
          </span>
        );
      },
    });
  }
  
  return (
    <PageLayout hideCluster title={
      <>
        <RollbackOutlined className='back' onClick={() => history.push('/job-tasks')} />
        执行历史
      </>
    }>
      <div style={{ padding: 10 }} className={taskResultCls}>
      <Card
        title={data.title}
        extra={<a onClick={() => { getTableData(); }}>{t('task.refresh')}</a>}
      >
        <Row style={{ marginBottom: 20 }}>
          <Col span={18}>
            <div>
              <a href={`/job-task/${curBusiItem.id}/output/${taskId}/stdout`} target="_blank">stdouts</a>
              <Divider type="vertical" />
              <a href={`/job-task/${curBusiItem.id}/output/${taskId}/stderr`} target="_blank">stderrs</a>
              <Divider type="vertical" />
              <Link to={{ pathname: `/job-tasks/${taskId}/detail` }}>{t('task.meta')}</Link>
              <Divider type="vertical" />
              <Link to={{ pathname: '/job-tasks/add', search: `task=${taskId}` }}>{t('task.clone')}</Link>
            </div>
          </Col>
          <Col span={6} className="textAlignRight">
            {
              !data.done ?
                <span>
                  {
                    data.action === 'start' ?
                      <Button className="success-btn" onClick={() => handleTaskAction('pause')}>Pause</Button> :
                      <Button className="success-btn" onClick={() => handleTaskAction('start')}>Start</Button>
                  }
                  <Button className="ml10 warning-btn" onClick={() => handleTaskAction('cancel')}>Cancel</Button>
                  <Button className="ml10 danger-btn" onClick={() => handleTaskAction('kill')}>Kill</Button>
                </span> : null
            }
          </Col>
        </Row>
        <Table
          rowKey="host"
          columns={columns as any}
          dataSource={hosts}
          loading={loading}
          pagination={{
            showSizeChanger: true,
            pageSizeOptions: ['10', '50', '100', '500', '1000'],
            showTotal: (total) => {
              return i18n.language == 'en' ?
              `Total ${total} items` :
              `共 ${total} 条`
            },
          } as any}
          onChange={(pagination, filters, sorter, extra) => {
            setActiveStatus(filters.status as string[]);
          }}
        />
      </Card>
      </div>
    </PageLayout>
  )
}
Example #15
Source File: detail.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
Detail = (props: any) => {
  const history = useHistory();
  const id = _.get(props, 'match.params.id');
  const { curBusiItem } = useSelector<RootState, CommonStoreState>((state) => state.common);
  const { t } = useTranslation();
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState({} as Tpl);

  useEffect(() => {
    if (id) {
      setLoading(true);
      request(`${api.tasktpl(curBusiItem.id)}/${id}`).then((data) => {
        const { dat } = data;
        setData({
          ...dat.tpl,
          hosts: dat.hosts,
          grp: dat.grp,
        });
      }).finally(() => {
        setLoading(false);
      });
    }
  }, [id, curBusiItem.id]);

  return (
    <PageLayout hideCluster title={
      <>
        <RollbackOutlined className='back' onClick={() => history.push('/job-tpls')} />
        自愈脚本
      </>
    }>
      <div style={{ padding: 10 }}>
        <Card
          title="自愈脚本详情"
        >
        <Spin spinning={loading}>
          <div className="job-task-table">
            <div className="ant-table ant-table-default ant-table-bordered">
              <div className="ant-table-content">
                <div className="ant-table-body">
                  <table>
                    <colgroup>
                      <col style={{ width: 100, minWidth: 100 }} />
                      <col />
                    </colgroup>
                    <tbody className="ant-table-tbody">
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('task.title')}</td>
                        <td>{data.title}</td>
                      </tr>
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('tpl.creator')}</td>
                        <td>{data.create_by}</td>
                      </tr>
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('tpl.last_updated')}</td>
                        <td>{moment.unix(data.update_at).format('YYYY-MM-DD HH:mm:ss')}</td>
                      </tr>
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('task.control.params')}</td>
                        <td>
                          {t('task.account')}:{data.account}
                          <Divider type="vertical" />
                          {t('task.batch')}:{data.batch}
                          <Divider type="vertical" />
                          {t('task.tolerance')}:{data.tolerance}
                          <Divider type="vertical" />
                          {t('task.timeout')}:{data.timeout}
                        </td>
                      </tr>
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('task.script')}</td>
                        <td>
                          <Editor value={data.script} readOnly height="200px" />
                        </td>
                      </tr>
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('task.script.args')}</td>
                        <td>{data.args}</td>
                      </tr>
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('task.pause')}</td>
                        <td>{data.pause}</td>
                      </tr>
                      <tr className="ant-table-row ant-table-row-level-0">
                        <td>{t('task.host.list')}</td>
                        <td>
                          {
                            _.map(data.hosts, (host) => {
                              return <div key={host}>{host}</div>;
                            })
                          }
                        </td>
                      </tr>
                    </tbody>
                  </table>
                </div>
              </div>
            </div>
          </div>
          <div style={{ marginTop: 10 }}>
            <Link to={{ pathname: `/job-tpls/${id}/modify` }}>
              <Button type="primary" style={{ marginRight: 10 }}>{t('tpl.modify')}</Button>
            </Link>
            <Link to={{ pathname: `/job-tpls/add/task`, search: `tpl=${id}` }}>
              <Button type="primary">{t('tpl.create.task')}</Button>
            </Link>
          </div>
        </Spin>
        </Card>
      </div>
    </PageLayout>
  )
}
Example #16
Source File: Columns.tsx    From wildduck-ui with MIT License 4 votes vote down vote up
getArchiveColumns = ({
	dataSource,
	restoreMessage,
}: {
	dataSource: any;
	restoreMessage({ message, params }: any): void;
}): any => {
	const columns = [
		{
			title: 'From',
			dataIndex: 'from',
			key: 'from',
			width: 350,
			customDataIndex: 'from.address',
			filter: true,
			children: [
				{
					title: 'Name',
					dataIndex: 'fromName',
					key: 'fromName',
					width: 100,
					fixed: 'left',
					render: (text: any, record: any) => _.get(record, 'from.name'),
				},
				{
					title: 'Address',
					dataIndex: 'fromAddress',
					key: 'fromAddress',
					fixed: 'left',
					width: 230,
					render: (text: any, record: any) => _.get(record, 'from.address'),
				},
			],
		},
		{
			title: 'To',
			dataIndex: 'to',
			key: 'to',
			width: 350,
			children: [
				{
					title: 'Name',
					dataIndex: 'toName',
					key: 'toName',
					width: 100,
					render: (text: any, record: any) => createRecordDisplayList(record, 'to', 'name'),
				},
				{
					title: 'Address',
					dataIndex: 'toAddress',
					key: 'toAddress',
					width: 230,
					render: (text: any, record: any) => createRecordDisplayList(record, 'to', 'address'),
				},
			],
		},
		{
			title: 'Cc',
			dataIndex: 'cc',
			key: 'cc',
			widht: 350,
			children: [
				{
					title: 'Name',
					dataIndex: 'ccName',
					key: 'ccName',
					width: 100,
					render: (text: any, record: any) => createRecordDisplayList(record, 'cc', 'name'),
				},
				{
					title: 'Address',
					dataIndex: 'ccAddress',
					key: 'ccAddress',
					width: 230,
					render: (text: any, record: any) => createRecordDisplayList(record, 'cc', 'address'),
				},
			],
		},
		{
			title: 'Bcc',
			dataIndex: 'bcc',
			key: 'bcc',
			width: 350,
			children: [
				{
					title: 'Name',
					dataIndex: 'bccName',
					key: 'bccName',
					width: 100,
					render: (text: any, record: any) => createRecordDisplayList(record, 'bcc', 'name'),
				},
				{
					title: 'Address',
					dataIndex: 'bccAddress',
					key: 'bccAddress',
					width: 230,
					render: (text: any, record: any) => createRecordDisplayList(record, 'bcc', 'address'),
				},
			],
		},
		{
			title: 'Subject',
			dataIndex: 'subject',
			key: 'subject',
			width: 100,
		},
		{
			title: 'Date',
			dataIndex: 'date',
			key: 'date',
			sortable: 'date',
			width: 100,
			render: (date: string) => moment(date).format(DATE_TIME_FORMAT_AP),
		},
		{
			title: 'Intro',
			dataIndex: 'intro',
			key: 'intro',
			width: 100,
		},
		{
			title: 'Attachments',
			dataIndex: 'attachments',
			key: 'attachments',
			filter: true,
			width: 110,
			align: 'center',
			render: (text: string) => _.toString(text),
		},
		{
			title: 'Seen',
			dataIndex: 'seen',
			key: 'seen',
			filter: true,
			width: 70,
			align: 'center',
			render: (text: string) => _.toString(text),
		},
		{
			title: 'Deleted',
			dataIndex: 'deleted',
			key: 'deleted',
			filter: true,
			width: 90,
			align: 'center',
			render: (text: string) => _.toString(text),
		},
		{
			title: 'Flagged',
			dataIndex: 'flagged',
			key: 'flagged',
			filter: true,
			width: 90,
			align: 'center',
			render: (text: string) => _.toString(text),
		},
		{
			title: 'Content type',
			dataIndex: 'contentType',
			key: 'contentType',
			customDataIndex: 'contentType.value',
			filter: true,
			width: 350,
			children: [
				{
					title: 'Value',
					dataIndex: 'value',
					key: 'value',
					width: 100,
					render: (text: any, record: any) => _.get(record, 'contentType.value'),
				},
				{
					title: 'Params',
					dataIndex: 'params',
					key: 'params',
					width: 230,
					render: (text: any, record: any) =>
						_.map(_.get(record, 'contentType.params'), (params, key) => (
							<Space key={key + params}>
								{key} : {params}
							</Space>
						)),
				},
			],
		},
		{
			title: 'Action',
			key: 'action',
			fixed: 'right' as const,
			width: 100,
			align: 'center',
			render: (text: string, record: any) => (
				<Space size={'middle'}>
					<Tooltip title={'Restore Message'}>
						<Button
							onClick={() => {
								showConfirm(
									() =>
										restoreMessage({
											message: _.get(record, 'id'),
											params: { mailbox: _.get(record, 'mailbox') },
										}),
									'Are you sure you want to restore this message?',
								);
							}}
							className='ant-btn-icon'
							shape='circle'
						>
							<RollbackOutlined className='green-color' />
						</Button>
					</Tooltip>
				</Space>
			),
		},
	];

	return getColumnsWithFilterAndSort(columns, dataSource);
}