@ant-design/icons#ShareAltOutlined TypeScript Examples

The following examples show how to use @ant-design/icons#ShareAltOutlined. 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 fe-v5 with Apache License 2.0 5 votes vote down vote up
render() {
    const { spinning } = this.state;
    const { extraRender, data, showHeader = true } = this.props;
    const { title, metric } = data;
    const graphConfig = this.getGraphConfig(data);
    return (
      <div className={this.state.legend ? 'graph-container graph-container-hasLegend' : 'graph-container'}>
        {showHeader && (
          <div
            className='graph-header'
            style={{
              height: this.headerHeight,
              lineHeight: `${this.headerHeight}px`,
            }}
          >
            <div>{title || metric}</div>
            <div className='graph-extra'>
              <span className='graph-operationbar-item' key='info'>
                <Popover placement='left' content={this.getContent()} trigger='click' autoAdjustOverflow={false} getPopupContainer={() => document.body}>
                  <Button className='' type='link' size='small' onClick={(e) => e.preventDefault()}>
                    <SettingOutlined />
                  </Button>
                </Popover>
              </span>
              {this.props.isShowRefresh === false ? null : (
                <span className='graph-operationbar-item' key='sync'>
                  <Button type='link' size='small' onClick={(e) => e.preventDefault()}>
                    <SyncOutlined onClick={this.refresh} />
                  </Button>
                </span>
              )}
              {this.props.isShowShare === false ? null : (
                <span className='graph-operationbar-item' key='share'>
                  <Button type='link' size='small' onClick={(e) => e.preventDefault()}>
                    <ShareAltOutlined onClick={this.shareChart} />
                  </Button>
                </span>
              )}
              {extraRender && _.isFunction(extraRender) ? extraRender(this) : null}
            </div>
          </div>
        )}
        {this.props.graphConfigInnerVisible ? (
          <GraphConfigInner
            data={graphConfig}
            onChange={(...args) => {
              this.updateGraphConfig(args[2] || {});
            }}
          />
        ) : null}
        {/* 这个spin有点难搞,因为要第一时间获取chart容器的offsetheight */}
        {/* <Spin spinning={spinning} wrapperClassName='graph-spin'> */}
        {this.renderChart()}
        {/* </Spin> */}
        <Legend
          style={{ display: this.state.legend ? 'block' : 'none', overflowY: 'auto', maxHeight: '35%' }}
          graphConfig={graphConfig}
          series={this.getZoomedSeries()}
          onSelectedChange={this.handleLegendRowSelectedChange}
          comparisonOptions={graphConfig.comparisonOptions}
        />
      </div>
    );
  }
Example #2
Source File: StoryOverLay.tsx    From datart with Apache License 2.0 5 votes vote down vote up
StoryOverLay: React.FC<BoardOverLayProps> = memo(
  ({ onOpenShareLink, allowShare, allowManage, onPublish, isArchived }) => {
    const t = useI18NPrefix(`viz.action`);
    const tg = useI18NPrefix(`global`);
    const { storyId: stroyId, orgId } = useContext(StoryContext);
    const recycleViz = useRecycleViz(orgId, stroyId, 'STORYBOARD');
    const renderList = useMemo(
      () => [
        {
          key: 'shareLink',
          icon: <ShareAltOutlined />,
          onClick: onOpenShareLink,
          disabled: false,
          render: allowShare,
          content: t('share.shareLink'),
          className: 'line',
        },
        {
          key: 'publish',
          icon: <VerticalAlignBottomOutlined />,
          onClick: onPublish,
          disabled: false,
          render: allowManage && !isArchived && onPublish,
          content: t('unpublish'),
        },
        {
          key: 'delete',
          icon: <DeleteOutlined />,
          disabled: false,
          render: allowManage,
          content: (
            <Popconfirm
              title={tg('operation.archiveConfirm')}
              onConfirm={recycleViz}
            >
              {tg('button.archive')}
            </Popconfirm>
          ),
        },
      ],
      [
        onOpenShareLink,
        allowShare,
        t,
        onPublish,
        allowManage,
        isArchived,
        tg,
        recycleViz,
      ],
    );
    const actionItems = useMemo(
      () =>
        renderList
          .filter(item => item.render)
          .map(item => {
            return (
              <>
                <Menu.Item
                  key={item.key}
                  icon={item.icon}
                  onClick={item.onClick}
                >
                  {item.content}
                </Menu.Item>
                {item.className && <Menu.Divider />}
              </>
            );
          }),
      [renderList],
    );
    return <Menu>{actionItems}</Menu>;
  },
)
Example #3
Source File: DashboardHeader.tsx    From posthog-foss with MIT License 4 votes vote down vote up
export function DashboardHeader(): JSX.Element {
    const { dashboard, dashboardMode, lastDashboardModeSource } = useValues(dashboardLogic)
    const { addNewDashboard, triggerDashboardUpdate, setDashboardMode, addGraph, saveNewTag, deleteTag } =
        useActions(dashboardLogic)
    const { dashboardTags } = useValues(dashboardsLogic)
    const { nameSortedDashboards, dashboardsLoading, dashboardLoading } = useValues(dashboardsModel)
    const { pinDashboard, unpinDashboard, deleteDashboard, duplicateDashboard } = useActions(dashboardsModel)
    const { user } = useValues(userLogic)
    const [newName, setNewName] = useState(dashboard?.name || null) // Used to update the input immediately, debouncing API calls

    const nameInputRef = useRef<Input | null>(null)
    const descriptionInputRef = useRef<HTMLInputElement | null>(null)

    if (!dashboard) {
        return <div />
    }

    const actionsDefault = (
        <>
            <Dropdown
                trigger={['click']}
                overlay={
                    <Menu>
                        {dashboard.created_by && (
                            <>
                                <Menu.Item disabled>
                                    Created by {dashboard.created_by.first_name || dashboard.created_by.email || '-'} on{' '}
                                    {dayjs(dashboard.created_at).format(
                                        dayjs(dashboard.created_at).year() === dayjs().year()
                                            ? 'MMMM Do'
                                            : 'MMMM Do YYYY'
                                    )}
                                </Menu.Item>
                                <Menu.Divider />
                            </>
                        )}
                        <Menu.Item
                            icon={<EditOutlined />}
                            onClick={() => setDashboardMode(DashboardMode.Edit, DashboardEventSource.MoreDropdown)}
                        >
                            Edit mode (E)
                        </Menu.Item>
                        <Menu.Item
                            icon={<FullscreenOutlined />}
                            onClick={() =>
                                setDashboardMode(DashboardMode.Fullscreen, DashboardEventSource.MoreDropdown)
                            }
                        >
                            Full screen mode (F)
                        </Menu.Item>
                        {dashboard.pinned ? (
                            <Menu.Item
                                icon={<PushpinFilled />}
                                onClick={() => unpinDashboard(dashboard.id, DashboardEventSource.MoreDropdown)}
                            >
                                Unpin dashboard
                            </Menu.Item>
                        ) : (
                            <Menu.Item
                                icon={<PushpinOutlined />}
                                onClick={() => pinDashboard(dashboard.id, DashboardEventSource.MoreDropdown)}
                            >
                                Pin dashboard
                            </Menu.Item>
                        )}

                        <Menu.Divider />
                        <Menu.Item
                            icon={<CopyOutlined />}
                            onClick={() => duplicateDashboard({ id: dashboard.id, name: dashboard.name, show: true })}
                        >
                            Duplicate dashboard
                        </Menu.Item>
                        <Menu.Item
                            icon={<DeleteOutlined />}
                            onClick={() => deleteDashboard({ id: dashboard.id, redirect: true })}
                            danger
                        >
                            Delete dashboard
                        </Menu.Item>
                    </Menu>
                }
                placement="bottomRight"
            >
                <Button type="link" className="btn-lg-2x" data-attr="dashboard-more" icon={<EllipsisOutlined />} />
            </Dropdown>
            <Button
                type="link"
                data-attr="dashboard-edit-mode"
                icon={<EditOutlined />}
                onClick={() => setDashboardMode(DashboardMode.Edit, DashboardEventSource.DashboardHeader)}
            />
            <HotkeyButton
                onClick={() => addGraph()}
                data-attr="dashboard-add-graph-header"
                icon={<PlusOutlined />}
                hotkey="n"
                className="hide-lte-md"
            >
                New insight
            </HotkeyButton>
            <HotkeyButton
                type="primary"
                onClick={() => setDashboardMode(DashboardMode.Sharing, DashboardEventSource.DashboardHeader)}
                data-attr="dashboard-share-button"
                icon={<ShareAltOutlined />}
                hotkey="k"
            >
                Send or share
            </HotkeyButton>
        </>
    )

    const actionsPresentationMode = (
        <Button
            onClick={() => setDashboardMode(null, DashboardEventSource.DashboardHeader)}
            data-attr="dashboard-exit-presentation-mode"
            icon={<FullscreenExitOutlined />}
        >
            Exit full screen mode
        </Button>
    )

    const actionsEditMode = (
        <Button
            data-attr="dashboard-edit-mode-save"
            type="primary"
            onClick={() => setDashboardMode(null, DashboardEventSource.DashboardHeader)}
            tabIndex={10}
        >
            Finish editing
        </Button>
    )

    useEffect(() => {
        if (dashboardMode === DashboardMode.Edit) {
            if (lastDashboardModeSource === DashboardEventSource.AddDescription) {
                setTimeout(() => descriptionInputRef.current?.focus(), 10)
            } else if (!isMobile()) {
                setTimeout(() => nameInputRef.current?.focus(), 10)
            }
        }
    }, [dashboardMode])

    return (
        <>
            <div className={`dashboard-header${dashboardMode === DashboardMode.Fullscreen ? ' full-screen' : ''}`}>
                {dashboardMode === DashboardMode.Fullscreen && (
                    <FullScreen onExit={() => setDashboardMode(null, DashboardEventSource.Browser)} />
                )}
                <ShareModal
                    onCancel={() => setDashboardMode(null, DashboardEventSource.Browser)}
                    visible={dashboardMode === DashboardMode.Sharing}
                />
                {dashboardsLoading ? (
                    <Loading />
                ) : (
                    <>
                        {dashboardMode === DashboardMode.Edit ? (
                            <Input
                                placeholder="Dashboard name (e.g. Weekly KPIs)"
                                value={newName || ''}
                                size="large"
                                style={{ maxWidth: 400 }}
                                onChange={(e) => {
                                    setNewName(e.target.value) // To update the input immediately
                                    triggerDashboardUpdate({ name: e.target.value }) // This is breakpointed (i.e. debounced) to avoid multiple API calls
                                }}
                                onKeyDown={(e) => {
                                    if (e.key === 'Enter') {
                                        setDashboardMode(null, DashboardEventSource.InputEnter)
                                    }
                                }}
                                ref={nameInputRef}
                                tabIndex={0}
                            />
                        ) : (
                            <div className="dashboard-select">
                                <Select
                                    value={(dashboard?.id || undefined) as number | 'new' | undefined}
                                    onChange={(id) => {
                                        if (id === 'new') {
                                            addNewDashboard()
                                        } else {
                                            router.actions.push(urls.dashboard(id))
                                            eventUsageLogic.actions.reportDashboardDropdownNavigation()
                                        }
                                    }}
                                    bordered={false}
                                    dropdownMatchSelectWidth={false}
                                >
                                    {nameSortedDashboards.map((dash: DashboardType) => (
                                        <Select.Option key={dash.id} value={dash.id}>
                                            {dash.name || <span style={{ color: 'var(--muted)' }}>Untitled</span>}
                                            {dash.is_shared && (
                                                <Tooltip title="This dashboard is publicly shared">
                                                    <ShareAltOutlined style={{ marginLeft: 4, float: 'right' }} />
                                                </Tooltip>
                                            )}
                                        </Select.Option>
                                    ))}
                                    <Select.Option value="new">+ New Dashboard</Select.Option>
                                </Select>
                            </div>
                        )}

                        <div className="dashboard-meta">
                            {dashboardMode === DashboardMode.Edit
                                ? actionsEditMode
                                : dashboardMode === DashboardMode.Fullscreen
                                ? actionsPresentationMode
                                : actionsDefault}
                        </div>
                    </>
                )}
            </div>
            {user?.organization?.available_features?.includes(AvailableFeature.DASHBOARD_COLLABORATION) && (
                <>
                    <div className="mb" data-attr="dashboard-tags">
                        <ObjectTags
                            tags={dashboard.tags}
                            onTagSave={saveNewTag}
                            onTagDelete={deleteTag}
                            saving={dashboardLoading}
                            tagsAvailable={dashboardTags.filter((tag) => !dashboard.tags.includes(tag))}
                        />
                    </div>
                    <Description
                        item={dashboard}
                        setItemMode={setDashboardMode}
                        itemMode={dashboardMode}
                        triggerItemUpdate={triggerDashboardUpdate}
                        descriptionInputRef={descriptionInputRef}
                    />
                </>
            )}
        </>
    )
}
Example #4
Source File: Dashboards.tsx    From posthog-foss with MIT License 4 votes vote down vote up
export function Dashboards(): JSX.Element {
    const { dashboardsLoading } = useValues(dashboardsModel)
    const { deleteDashboard, unpinDashboard, pinDashboard, addDashboard, duplicateDashboard } =
        useActions(dashboardsModel)
    const { setNewDashboardDrawer, setSearchTerm, setCurrentTab } = useActions(dashboardsLogic)
    const { dashboards, newDashboardDrawer, searchTerm, currentTab } = useValues(dashboardsLogic)
    const { hasAvailableFeature } = useValues(userLogic)

    const columns: LemonTableColumns<DashboardType> = [
        {
            width: 0,
            dataIndex: 'pinned',
            render: function Render(pinned, { id }) {
                return pinned ? (
                    <PushpinFilled
                        onClick={() => unpinDashboard(id, DashboardEventSource.DashboardsList)}
                        style={{ cursor: 'pointer' }}
                    />
                ) : (
                    <PushpinOutlined
                        onClick={() => pinDashboard(id, DashboardEventSource.DashboardsList)}
                        style={{ cursor: 'pointer' }}
                    />
                )
            },
        },
        {
            title: 'Name',
            dataIndex: 'name',
            width: '40%',
            render: function Render(name, { id, description, _highlight, is_shared }) {
                return (
                    <div className={_highlight ? 'highlighted' : undefined} style={{ display: 'inline-block' }}>
                        <div className="row-name">
                            <Link data-attr="dashboard-name" to={urls.dashboard(id)}>
                                {name || 'Untitled'}
                            </Link>
                            {is_shared && (
                                <Tooltip title="This dashboard is shared publicly.">
                                    <ShareAltOutlined style={{ marginLeft: 6 }} />
                                </Tooltip>
                            )}
                        </div>
                        {hasAvailableFeature(AvailableFeature.DASHBOARD_COLLABORATION) && description && (
                            <span className="row-description">{description}</span>
                        )}
                    </div>
                )
            },
            sorter: (a, b) => (a.name ?? 'Untitled').localeCompare(b.name ?? 'Untitled'),
        },
        ...(hasAvailableFeature(AvailableFeature.DASHBOARD_COLLABORATION)
            ? [
                  {
                      title: 'Tags',
                      dataIndex: 'tags' as keyof DashboardType,
                      render: function Render(tags: DashboardType['tags']) {
                          return <ObjectTags tags={tags} staticOnly />
                      },
                  } as LemonTableColumn<DashboardType, keyof DashboardType | undefined>,
              ]
            : []),
        createdByColumn<DashboardType>() as LemonTableColumn<DashboardType, keyof DashboardType | undefined>,
        createdAtColumn<DashboardType>() as LemonTableColumn<DashboardType, keyof DashboardType | undefined>,
        {
            width: 0,
            render: function RenderActions(_, { id, name }: DashboardType) {
                return (
                    <More
                        overlay={
                            <>
                                <LemonButton
                                    type="stealth"
                                    to={urls.dashboard(id)}
                                    onClick={() => {
                                        dashboardLogic({ id }).mount()
                                        dashboardLogic({ id }).actions.setDashboardMode(
                                            null,
                                            DashboardEventSource.DashboardsList
                                        )
                                    }}
                                    fullWidth
                                >
                                    View
                                </LemonButton>
                                <LemonButton
                                    type="stealth"
                                    to={urls.dashboard(id)}
                                    onClick={() => {
                                        dashboardLogic({ id }).mount()
                                        dashboardLogic({ id }).actions.setDashboardMode(
                                            DashboardMode.Edit,
                                            DashboardEventSource.DashboardsList
                                        )
                                    }}
                                    fullWidth
                                >
                                    Edit
                                </LemonButton>
                                <LemonButton type="stealth" onClick={() => duplicateDashboard({ id, name })} fullWidth>
                                    Duplicate
                                </LemonButton>
                                <LemonSpacer />
                                <LemonButton
                                    type="stealth"
                                    style={{ color: 'var(--danger)' }}
                                    onClick={() => deleteDashboard({ id, redirect: false })}
                                    fullWidth
                                >
                                    Delete dashboard
                                </LemonButton>
                            </>
                        }
                    />
                )
            },
        },
    ]

    return (
        <div>
            <PageHeader
                title="Dashboards"
                buttons={
                    <Button
                        data-attr={'new-dashboard'}
                        onClick={() => setNewDashboardDrawer(true)}
                        type="primary"
                        icon={<PlusOutlined />}
                    >
                        New Dashboard
                    </Button>
                }
            />
            <Tabs
                activeKey={currentTab}
                style={{ borderColor: '#D9D9D9' }}
                onChange={(tab) => setCurrentTab(tab as DashboardsTab)}
            >
                <Tabs.TabPane tab="All Dashboards" key={DashboardsTab.All} />
                <Tabs.TabPane tab="Pinned" key={DashboardsTab.Pinned} />
                <Tabs.TabPane tab="Shared" key={DashboardsTab.Shared} />
            </Tabs>
            <div>
                <Input.Search
                    allowClear
                    enterButton
                    placeholder="Search for dashboards"
                    style={{ width: 240 }}
                    value={searchTerm}
                    onChange={(e) => {
                        setSearchTerm(e.target.value)
                    }}
                />
            </div>
            <LemonSpacer large />
            <Drawer
                title="New Dashboard"
                width={400}
                onClose={() => setNewDashboardDrawer(false)}
                destroyOnClose={true}
                visible={newDashboardDrawer}
            >
                <NewDashboard />
            </Drawer>

            {dashboardsLoading ? (
                <div className="flex-center" style={{ flexDirection: 'column' }}>
                    <Spinner />
                    <div className="mt">
                        <b>Loading dashboards</b>
                    </div>
                </div>
            ) : dashboards.length > 0 || searchTerm || currentTab !== DashboardsTab.All ? (
                <LemonTable
                    dataSource={dashboards}
                    rowKey="id"
                    columns={columns}
                    defaultSorting={{ columnKey: 'name', order: 1 }}
                    emptyState={
                        searchTerm ? (
                            `No ${
                                currentTab === DashboardsTab.Pinned
                                    ? 'pinned '
                                    : currentTab === DashboardsTab.Shared
                                    ? 'shared '
                                    : ''
                            }dashboards matching "${searchTerm}"!`
                        ) : currentTab === DashboardsTab.Pinned ? (
                            <>
                                No dashboards have been pinned for quick access yet.{' '}
                                <Link onClick={() => setCurrentTab(DashboardsTab.All)}>
                                    Go to All Dashboards to pin one.
                                </Link>
                            </>
                        ) : currentTab === DashboardsTab.Shared ? (
                            <>
                                No dashboards have been shared yet.{' '}
                                <Link onClick={() => setCurrentTab(DashboardsTab.All)}>
                                    Go to All Dashboards to share one.
                                </Link>
                            </>
                        ) : undefined
                    }
                    nouns={['dashboard', 'dashboards']}
                />
            ) : (
                <div className="mt">
                    <p>Create your first dashboard:</p>
                    <Row gutter={[16, 16]}>
                        <Col xs={24} xl={6}>
                            <Card
                                title="Empty"
                                size="small"
                                style={{ cursor: 'pointer' }}
                                onClick={() =>
                                    addDashboard({
                                        name: 'New Dashboard',
                                        show: true,
                                        useTemplate: '',
                                    })
                                }
                            >
                                <div style={{ textAlign: 'center', fontSize: 40 }}>
                                    <AppstoreAddOutlined />
                                </div>
                            </Card>
                        </Col>
                        <Col xs={24} xl={6}>
                            <Card
                                title="App Default"
                                size="small"
                                style={{ cursor: 'pointer' }}
                                onClick={() =>
                                    addDashboard({
                                        name: 'Web App Dashboard',
                                        show: true,
                                        useTemplate: 'DEFAULT_APP',
                                    })
                                }
                            >
                                <div style={{ textAlign: 'center', fontSize: 40 }}>
                                    <AppstoreAddOutlined />
                                </div>
                            </Card>
                        </Col>
                    </Row>
                </div>
            )}
        </div>
    )
}
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 fe-v5 with Apache License 2.0 4 votes vote down vote up
function Chart(props: Props) {
  const { t } = useTranslation();
  const { options, barControl, rightBar, title } = props;
  const [refreshing, setRefreshing] = useState(false);
  const chartRef = useRef(null);
  const location = useLocation();
  const { metric, description = '', tags, range, limit, idents, classpath_id, classpath_prefix, prome_ql, yplotline, xplotline, step } = options;

  const [privateTags, setPrivateTags] = useState<TagType[]>([]);
  const [multi, setMulti] = useState(false);
  const [sort, setSort] = useState<'desc' | 'asc'>('desc');
  const [tooltipFormat, setTooltipFormat] = useState<'origin' | 'short'>('origin');
  const [instance, setInstance] =
    useState<{
      destroy: Function;
      update: Function;
      options: {
        yAxis: object;
        xAxis: object;
      };
    } | null>(null); // transfer Param and RangeItem into timestamp

  const formatDate = (r?: Range) => {
    let newR = r || range;

    if (newR) {
      if (isAbsoluteRange(newR)) {
        const { start, end } = newR;
        return {
          start,
          end,
        };
      } else {
        return generateTimeStampRange(newR);
      }
    }

    return {
      start: 0,
      end: 0,
    };
  };

  const { start, end } = formatDate(range);

  const initChart = (privateTags: TagType[] = []) => {
    let newTags = privateTags;

    if (tags && tags.length > 0) {
      newTags = tags.concat(newTags);
    }

    let params = Array.isArray(metric)
      ? metric.map((item) => {
          return {
            metric: item,
            classpath_id,
            classpath_prefix: classpath_prefix === undefined ? undefined : classpath_prefix ? 1 : 0,
            prome_ql,
            tags: newTags && newTags.length > 0 ? newTags : undefined,
            idents,
          };
        })
      : Array.isArray(prome_ql)
      ? prome_ql.map((item) => {
          return {
            metric,
            classpath_id,
            classpath_prefix: classpath_prefix === undefined ? undefined : classpath_prefix ? 1 : 0,
            prome_ql: item,
            tags: newTags && newTags.length > 0 ? newTags : undefined,
            idents,
          };
        })
      : [
          {
            metric,
            classpath_id,
            classpath_prefix: classpath_prefix ? 1 : 0,
            prome_ql,
            tags: newTags && newTags.length > 0 ? newTags : undefined,
            idents,
          },
        ];
    // GetData({
    //   params,
    //   start,
    //   end,
    //   limit,
    //   step,
    // }).then((data) => {
    //   const dataY: DataSource[] = [];
    //   data.dat.forEach((dataItem) => {
    //     dataY.push({
    //       name: dataItem.metric,
    //       data: dataItem.values.map((item) => item.v),
    //     });
    //   });
    //   const series: Array<any> = [];
    //   data.dat.forEach((dataItem) => {
    //     const { metric, values, tags } = dataItem;
    //     const seriesData = values.map((item) => {
    //       return {
    //         timestamp: item.t * 1000,
    //         value: item.v,
    //       };
    //     });
    //     series.push({
    //       name: (metric ? `【${metric}】` : '') + tags,
    //       data: seriesData,
    //     });
    //   });
    //   // if (chartRef.current) {
    //   //   // @ts-ignore
    //   //   chartRef.current.innerHTML = '';
    //   // }

    //   let graphOption = instance
    //     ? {
    //         series: series,
    //         tooltip: {
    //           precision: tooltipFormat,
    //           shared: multi,
    //           sharedSortDirection: sort,
    //         },
    //         // 必须xAxis和yAxis必须将属性返回
    //         yAxis: {
    //           ...instance.options.yAxis,
    //           plotLines: yplotline
    //             ? [
    //                 {
    //                   value: yplotline,
    //                   color: 'red',
    //                 },
    //               ]
    //             : undefined,
    //         },
    //         xAxis: {
    //           ...instance.options.xAxis,
    //           plotLines: xplotline
    //             ? [
    //                 {
    //                   value: xplotline * 1000,
    //                   color: 'red',
    //                 },
    //               ]
    //             : undefined,
    //         },
    //       }
    //     : {
    //         timestamp: 'x',
    //         xkey: 'timestamp',
    //         ykey: 'value',
    //         chart: {
    //           renderTo: chartRef.current,
    //         },
    //         yAxis: {
    //           plotLines: yplotline
    //             ? [
    //                 {
    //                   value: yplotline,
    //                   color: 'red',
    //                 },
    //               ]
    //             : undefined,
    //         },
    //         xAxis: {
    //           plotLines: xplotline
    //             ? [
    //                 {
    //                   value: xplotline * 1000,
    //                   color: 'red',
    //                 },
    //               ]
    //             : undefined,
    //         },
    //         series: series,
    //         tooltip: {
    //           precision: tooltipFormat,
    //           shared: multi,
    //           sharedSortDirection: sort,
    //         },
    //       };

    //   if (instance) {
    //     instance.update(graphOption);
    //   } else {
    //     setInstance(new TsGraph(graphOption));
    //   }
    // });
  };

  useEffect(() => {
    initChart(privateTags);
  }, [options, multi, sort, tooltipFormat]);

  // each chart is mounted once, when props and state change, the instance will update.
  // so below hook only run once.
  useEffect(() => {
    return () => {
      instance && instance.destroy();
    };
  }, [instance]);

  const handleRefresh = (e) => {
    if (refreshing) return;
    setRefreshing(true);
    initChart(privateTags); //需要将选择的过滤器传进去

    setTimeout(() => {
      setRefreshing(false);
    }, 1000);
  };

  const handleChartTagsChange = (e: TagType[]) => {
    setPrivateTags(e);
    initChart(e);
  };

  const handleMultiChange = (e) => {
    setMulti(e.target.checked);
  };

  const handleOrderSortChange = (bool) => {
    setSort(bool ? 'desc' : 'asc');
  };

  const handleTooltipFormat = (e) => {
    setTooltipFormat(e.target.checked ? 'short' : 'origin');
  };

  const renderMultiOrSort = (
    <>
      <Tooltip title={t('tooltip中展示所有曲线的值')}>
        <Checkbox onChange={handleMultiChange}>Multi</Checkbox>
      </Tooltip>
      <Tooltip
        title={
          <>
            <span>{t('SI格式化:')}</span>
            <a type='link' href='https://en.wikipedia.org/wiki/Metric_prefix#List_of_SI_prefixes' target='_blank'>
              {t('文档')}
            </a>
          </>
        }
      >
        <Checkbox onChange={handleTooltipFormat}>Format</Checkbox>
      </Tooltip>
      <OrderSort onChange={handleOrderSortChange} />
    </>
  );
  return (
    <div className='chart-wrapper'>
      {(title || rightBar || description || metric) && (
        <div className='chart-title'>
          {title ? (
            <div className='chart-title-label'>{title}</div>
          ) : (
            <div className='chart-title-label'>
              {metric} {description}
            </div>
          )}

          <div className='chart-title-right-bar'>
            {rightBar}
            {!location.pathname.startsWith('/chart/') && (
              <Button
                type='link'
                size='small'
                onClick={async (e) => {
                  e.preventDefault();
                  let { dat: ids } = await SetTmpChartData([{ configs: JSON.stringify({ title, options, barControl }) }]);
                  window.open('/chart/' + ids);
                }}
              >
                <ShareAltOutlined />
              </Button>
            )}
          </div>
        </div>
      )}
      {!barControl && (
        <div className='chart-filter'>
          <ReloadOutlined className='refresh' spin={refreshing} onClick={handleRefresh} />
          {renderMultiOrSort}
          {!prome_ql && (
            <TagFilterForChart
              options={{
                ...options,
                start,
                end,
                idents,
              }}
              onChange={handleChartTagsChange}
            />
          )}
        </div>
      )}

      {barControl === 'multiOrSort' && <div className='chart-filter'>{renderMultiOrSort}</div>}

      <div ref={chartRef} className='chart-content'></div>
    </div>
  );
}
Example #7
Source File: index.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
function index(props: IProps) {
  const { dashboardId, id, time, refreshFlag, step, type, variableConfig, isPreview, onCloneClick, onShareClick, onEditClick, onDeleteClick } = props;
  const values = _.cloneDeep(props.values);
  const ref = useRef<HTMLDivElement>(null);
  const [inViewPort] = useInViewport(ref);
  const { series, loading } = usePrometheus({
    id,
    dashboardId,
    time,
    refreshFlag,
    step,
    targets: values.targets,
    variableConfig,
    inViewPort: isPreview || inViewPort,
  });
  const tipsVisible = values.description || !_.isEmpty(values.links);
  if (_.isEmpty(values)) return null;
  // TODO: 如果 hexbin 的 colorRange 为 string 时转成成 array
  if (typeof _.get(values, 'custom.colorRange') === 'string') {
    _.set(values, 'custom.colorRange', _.split(_.get(values, 'custom.colorRange'), ','));
  }
  const subProps = {
    values,
    series,
  };
  const RendererCptMap = {
    timeseries: () => <Timeseries {...subProps} />,
    stat: () => <Stat {...subProps} />,
    table: () => <Table {...subProps} />,
    pie: () => <Pie {...subProps} />,
    hexbin: () => <Hexbin {...subProps} />,
  };

  return (
    <div className='renderer-container' ref={ref}>
      <div className='renderer-header graph-header dashboards-panels-item-drag-handle'>
        {tipsVisible ? (
          <Tooltip
            placement='rightTop'
            overlayInnerStyle={{
              width: 300,
            }}
            title={
              <div>
                <Markdown content={values.description} />
                <div>
                  {_.map(values.links, (link, i) => {
                    return (
                      <div key={i} style={{ marginTop: 8 }}>
                        <a href={link.url} target={link.targetBlank ? '_blank' : '_self'}>
                          {link.title}
                        </a>
                      </div>
                    );
                  })}
                </div>
              </div>
            }
          >
            <div className='renderer-header-desc'>
              <span className='renderer-header-info-corner-inner' />
              {values.description ? <InfoOutlined /> : <LinkOutlined />}
            </div>
          </Tooltip>
        ) : null}
        <div className='renderer-header-content'>
          {!isPreview ? (
            <Dropdown
              trigger={['click']}
              placement='bottomCenter'
              overlayStyle={{
                minWidth: '100px',
              }}
              overlay={
                <Menu>
                  {!isPreview ? (
                    <>
                      <Menu.Item onClick={onEditClick} key='0'>
                        <SettingOutlined style={{ marginRight: 8 }} />
                        编辑
                      </Menu.Item>
                      <Menu.Item onClick={onCloneClick} key='1'>
                        <CopyOutlined style={{ marginRight: 8 }} />
                        克隆
                      </Menu.Item>
                      <Menu.Item onClick={onShareClick} key='2'>
                        <ShareAltOutlined style={{ marginRight: 8 }} />
                        分享
                      </Menu.Item>
                      <Menu.Item onClick={onDeleteClick} key='3'>
                        <DeleteOutlined style={{ marginRight: 8 }} />
                        删除
                      </Menu.Item>
                    </>
                  ) : null}
                </Menu>
              }
            >
              <div className='renderer-header-title'>
                {values.name}
                <DownOutlined className='renderer-header-arrow' />
              </div>
            </Dropdown>
          ) : (
            <div className='renderer-header-title'>{values.name}</div>
          )}
        </div>
        <div className='renderer-header-loading'>{loading && <SyncOutlined spin />}</div>
      </div>
      <div className='renderer-body' style={{ height: `calc(100% - 36px)` }}>
        {RendererCptMap[type] ? RendererCptMap[type]() : `无效的图表类型 ${type}`}
      </div>
    </div>
  );
}
Example #8
Source File: Graph.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
export default function Graph(props: IProps) {
  const { metric, match, range, step, onClose } = props;
  const newGroups = _.map(
    _.filter(match.dimensionLabels, (item) => !_.isEmpty(item.value)),
    'label',
  );
  const [refreshFlag, setRefreshFlag] = useState(_.uniqueId('refreshFlag_'));
  const [calcFunc, setCalcFunc] = useState('');
  const [comparison, setComparison] = useState<string[]>([]);
  const [aggrFunc, setAggrFunc] = useState('avg');
  const [aggrGroups, setAggrGroups] = useState<string[]>(newGroups);
  const [labels, setLabels] = useState<string[]>([]);
  const [series, setSeries] = useState<any[]>([]);
  const [highLevelConfig, setHighLevelConfig] = useState({
    shared: true,
    sharedSortDirection: 'desc',
    legend: true,
    util: 'none',
    colorRange: colors[0].value,
    reverseColorOrder: false,
    colorDomainAuto: true,
    colorDomain: [],
    chartheight: 300,
  });
  const [chartType, setChartType] = useState('line');
  const [reduceFunc, setReduceFunc] = useState('last');
  const lineGraphProps = {
    custom: {
      drawStyle: 'lines',
      fillOpacity: 0,
      stack: 'hidden',
      lineInterpolation: 'smooth',
    },
    options: {
      legend: {
        displayMode: highLevelConfig.legend ? 'list' : 'hidden',
      },
      tooltip: {
        mode: highLevelConfig.shared ? 'all' : 'single',
        sort: highLevelConfig.sharedSortDirection,
      },
      standardOptions: {
        util: highLevelConfig.util,
      },
    },
  };
  const hexbinGraphProps = {
    custom: {
      calc: reduceFunc,
      colorRange: highLevelConfig.colorRange,
      reverseColorOrder: highLevelConfig.reverseColorOrder,
      colorDomainAuto: highLevelConfig.colorDomainAuto,
      colorDomain: highLevelConfig.colorDomain,
    },
    options: {
      standardOptions: {
        util: highLevelConfig.util,
      },
    },
  };
  const graphStandardOptions = {
    line: <LineGraphStandardOptions highLevelConfig={highLevelConfig} setHighLevelConfig={setHighLevelConfig} />,
    hexbin: <HexbinGraphStandardOptions highLevelConfig={highLevelConfig} setHighLevelConfig={setHighLevelConfig} />,
  };

  useEffect(() => {
    setAggrGroups(newGroups);
  }, [JSON.stringify(newGroups)]);

  useEffect(() => {
    const matchStr = getMatchStr(match);
    getLabels(`${metric}${matchStr}`, range).then((res) => {
      setLabels(res);
    });
  }, [refreshFlag, JSON.stringify(match), JSON.stringify(range)]);

  useEffect(() => {
    getQueryRange({
      metric,
      match: getMatchStr(match),
      range,
      step,
      aggrFunc,
      aggrGroups,
      calcFunc,
      comparison,
    }).then((res) => {
      setSeries(res);
    });
  }, [refreshFlag, metric, JSON.stringify(match), JSON.stringify(range), step, calcFunc, comparison, aggrFunc, aggrGroups]);

  return (
    <Card
      size='small'
      style={{ marginBottom: 10 }}
      title={metric}
      className='n9e-metric-views-metrics-graph'
      extra={
        <Space>
          <Space size={0} style={{ marginRight: 10 }}>
            <LineChartOutlined
              className={classNames({
                'button-link-icon': true,
                active: chartType === 'line',
              })}
              onClick={() => {
                setChartType('line');
              }}
            />
            <Divider type='vertical' />
            <HexbinIcon
              className={classNames({
                'button-link-icon': true,
                active: chartType === 'hexbin',
              })}
              onClick={() => {
                setChartType('hexbin');
              }}
            />
          </Space>
          <Popover placement='left' content={graphStandardOptions[chartType]} trigger='click' autoAdjustOverflow={false} getPopupContainer={() => document.body}>
            <a>
              <SettingOutlined />
            </a>
          </Popover>
          <a>
            <SyncOutlined
              onClick={() => {
                setRefreshFlag(_.uniqueId('refreshFlag_'));
              }}
            />
          </a>
          <a>
            <ShareAltOutlined
              onClick={() => {
                const curCluster = localStorage.getItem('curCluster');
                const dataProps = {
                  type: 'timeseries',
                  version: '2.0.0',
                  name: metric,
                  step,
                  range,
                  ...lineGraphProps,
                  targets: _.map(
                    getExprs({
                      metric,
                      match: getMatchStr(match),
                      aggrFunc,
                      aggrGroups,
                      calcFunc,
                      comparison,
                    }),
                    (expr) => {
                      return {
                        expr,
                      };
                    },
                  ),
                };
                setTmpChartData([
                  {
                    configs: JSON.stringify({
                      curCluster,
                      dataProps,
                    }),
                  },
                ]).then((res) => {
                  const ids = res.dat;
                  window.open('/chart/' + ids);
                });
              }}
            />
          </a>
          <a>
            <CloseCircleOutlined onClick={onClose} />
          </a>
        </Space>
      }
    >
      <div>
        <Space>
          <div>
            计算函数:
            <Dropdown
              overlay={
                <Menu onClick={(e) => setCalcFunc(e.key === 'clear' ? '' : e.key)} selectedKeys={[calcFunc]}>
                  <Menu.Item key='rate_1m'>rate_1m</Menu.Item>
                  <Menu.Item key='rate_5m'>rate_5m</Menu.Item>
                  <Menu.Item key='increase_1m'>increase_1m</Menu.Item>
                  <Menu.Item key='increase_5m'>increase_5m</Menu.Item>
                  <Menu.Divider></Menu.Divider>
                  <Menu.Item key='clear'>clear</Menu.Item>
                </Menu>
              }
            >
              <a className='ant-dropdown-link' onClick={(e) => e.preventDefault()}>
                {calcFunc || '无'} <DownOutlined />
              </a>
            </Dropdown>
          </div>
          <div>
            环比:
            {comparison.map((ag) => (
              <Tag
                key={ag}
                closable
                onClose={() => {
                  setComparison(_.without(comparison, ag));
                }}
              >
                {ag}
              </Tag>
            ))}
            <Dropdown
              overlay={
                <Menu
                  onClick={(e) => {
                    if (comparison.indexOf(e.key) === -1) {
                      setComparison([...comparison, e.key]);
                    } else {
                      setComparison(_.without(comparison, e.key));
                    }
                  }}
                  selectedKeys={comparison}
                >
                  <Menu.Item key='1d'>1d</Menu.Item>
                  <Menu.Item key='7d'>7d</Menu.Item>
                </Menu>
              }
              overlayStyle={{ maxHeight: 400, overflow: 'auto' }}
            >
              <a className='ant-dropdown-link' onClick={(e) => e.preventDefault()}>
                <PlusCircleOutlined />
              </a>
            </Dropdown>
          </div>
          <div>
            聚合函数:
            <Dropdown
              overlay={
                <Menu onClick={(e) => setAggrFunc(e.key)} selectedKeys={[aggrFunc]}>
                  <Menu.Item key='sum'>sum</Menu.Item>
                  <Menu.Item key='avg'>avg</Menu.Item>
                  <Menu.Item key='max'>max</Menu.Item>
                  <Menu.Item key='min'>min</Menu.Item>
                </Menu>
              }
            >
              <a className='ant-dropdown-link' onClick={(e) => e.preventDefault()}>
                {aggrFunc} <DownOutlined />
              </a>
            </Dropdown>
          </div>
          {aggrFunc ? (
            <div className='graph-config-inner-item'>
              聚合维度:
              {aggrGroups.map((ag) => (
                <Tag
                  key={ag}
                  closable
                  onClose={() => {
                    setAggrGroups(_.without(aggrGroups, ag));
                  }}
                >
                  {ag}
                </Tag>
              ))}
              <Dropdown
                overlay={
                  <Menu
                    onClick={(e) => {
                      if (aggrGroups.indexOf(e.key) === -1) {
                        setAggrGroups([...aggrGroups, e.key]);
                      } else {
                        setAggrGroups(_.without(aggrGroups, e.key));
                      }
                    }}
                    selectedKeys={aggrGroups}
                  >
                    {_.map(
                      _.filter(labels, (n) => n !== '__name__'),
                      (ag) => (
                        <Menu.Item key={ag}>{ag}</Menu.Item>
                      ),
                    )}
                  </Menu>
                }
                overlayStyle={{ maxHeight: 400, overflow: 'auto' }}
              >
                <a className='ant-dropdown-link' onClick={(e) => e.preventDefault()}>
                  <PlusCircleOutlined />
                </a>
              </Dropdown>
            </div>
          ) : null}
          {chartType === 'hexbin' && (
            <div>
              取值计算:
              <Dropdown
                overlay={
                  <Menu onClick={(e) => setReduceFunc(e.key)} selectedKeys={[reduceFunc]}>
                    {_.map(calcsOptions, (val, key) => {
                      return <Menu.Item key={key}>{val.name}</Menu.Item>;
                    })}
                  </Menu>
                }
              >
                <a className='ant-dropdown-link' onClick={(e) => e.preventDefault()}>
                  {calcsOptions[reduceFunc]?.name} <DownOutlined />
                </a>
              </Dropdown>
            </div>
          )}
        </Space>
      </div>
      <div>
        {chartType === 'line' && <Timeseries inDashboard={false} values={lineGraphProps as any} series={series} />}
        {chartType === 'hexbin' && (
          <div style={{ padding: '20px 0 0 0', height: highLevelConfig.chartheight }}>
            <Hexbin values={hexbinGraphProps as any} series={series} />
          </div>
        )}
      </div>
    </Card>
  );
}
Example #9
Source File: index.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
function index(props: IProps) {
  const { dashboardId, id, time, refreshFlag, step, type, variableConfig, values, isPreview, onCloneClick, onShareClick, onEditClick, onDeleteClick } = props;
  const ref = useRef<HTMLDivElement>(null);
  const [inViewPort] = useInViewport(ref);
  const { series, loading } = usePrometheus({
    id,
    dashboardId,
    time,
    refreshFlag,
    step,
    targets: values.targets,
    variableConfig,
    inViewPort: isPreview || inViewPort,
  });
  const subProps = {
    values,
    series,
  };
  const tipsVisible = values.description || !_.isEmpty(values.links);
  if (_.isEmpty(values)) return null;
  const RendererCptMap = {
    timeseries: () => <Timeseries {...subProps} />,
    stat: () => <Stat {...subProps} />,
    table: () => <Table {...subProps} />,
    pie: () => <Pie {...subProps} />,
  };

  return (
    <div className='renderer-container' ref={ref}>
      <div className='renderer-header graph-header dashboards-panels-item-drag-handle'>
        {tipsVisible ? (
          <Tooltip
            placement='rightTop'
            overlayInnerStyle={{
              width: 300,
            }}
            title={
              <div>
                <Markdown content={values.description} />
                <div>
                  {_.map(values.links, (link) => {
                    return (
                      <div style={{ marginTop: 8 }}>
                        <a href={link.url} target={link.targetBlank ? '_blank' : '_self'}>
                          {link.title}
                        </a>
                      </div>
                    );
                  })}
                </div>
              </div>
            }
          >
            <div className='renderer-header-desc'>
              <span className='renderer-header-info-corner-inner' />
              {values.description ? <InfoOutlined /> : <LinkOutlined />}
            </div>
          </Tooltip>
        ) : null}
        <div className='renderer-header-content'>
          {!isPreview ? (
            <Dropdown
              trigger={['click']}
              placement='bottomCenter'
              overlayStyle={{
                minWidth: '100px',
              }}
              overlay={
                <Menu>
                  {!isPreview ? (
                    <>
                      <Menu.Item onClick={onEditClick} key='0'>
                        <SettingOutlined style={{ marginRight: 8 }} />
                        编辑
                      </Menu.Item>
                      <Menu.Item onClick={onCloneClick} key='1'>
                        <CopyOutlined style={{ marginRight: 8 }} />
                        克隆
                      </Menu.Item>
                      <Menu.Item onClick={onShareClick} key='2'>
                        <ShareAltOutlined style={{ marginRight: 8 }} />
                        分享
                      </Menu.Item>
                      <Menu.Item onClick={onDeleteClick} key='3'>
                        <DeleteOutlined style={{ marginRight: 8 }} />
                        删除
                      </Menu.Item>
                    </>
                  ) : null}
                </Menu>
              }
            >
              <div className='renderer-header-title'>
                {values.name}
                <DownOutlined className='renderer-header-arrow' />
              </div>
            </Dropdown>
          ) : (
            <div className='renderer-header-title'>{values.name}</div>
          )}
        </div>
        <div className='renderer-header-loading'>{loading && <SyncOutlined spin />}</div>
      </div>
      <div className='renderer-body' style={{ height: `calc(100% - 36px)` }}>
        {RendererCptMap[type] ? RendererCptMap[type]() : `无效的图表类型 ${type}`}
      </div>
    </div>
  );
}
Example #10
Source File: ShareTicketModal.tsx    From condo with MIT License 4 votes vote down vote up
ShareTicketModal: React.FC<IShareTicketModalProps> = (props) => {
    const intl = useIntl()
    const SendTicketToEmailMessage = intl.formatMessage({ id: 'SendTicketToEmail' })
    const ToEmployeesEmailMessage = intl.formatMessage({ id: 'ToEmployeesEmail' })
    const EmployeesNameMessage = intl.formatMessage({ id: 'EmployeesName' })
    const ServerErrorMessage = intl.formatMessage({ id: 'ServerError' })
    const WhatsappMessage = intl.formatMessage({ id: 'WhatsApp' })
    const TelegramMessage = intl.formatMessage({ id: 'Telegram' })
    const ShareHeaderMessage = intl.formatMessage({ id: 'ticket.shareHeader' })
    const ShareButtonMessage = intl.formatMessage({ id: 'ticket.shareButton' })
    const OKMessage = intl.formatMessage({ id: 'OK' })
    const ShareSentMessage = intl.formatMessage({ id: 'ticket.shareSent' })
    const ShareSentToEmailMessage = intl.formatMessage({ id: 'ticket.shareSentToEmail' })
    const { isSmall } = useLayoutContext()

    const { date, number, details, id, locale, organization } = props
    const cipher = crypto.createCipher(ALGORITHM, SALT)

    let cutDetails = details || ''
    if (cutDetails.length >= 110) {
        cutDetails = `${cutDetails.substr(0, 100)}…`
    }
    const stringifiedParams = JSON.stringify({ date, number, details: cutDetails, id })
    const encryptedText = cipher.update(stringifiedParams, 'utf8', CRYPTOENCODING) + cipher.final(CRYPTOENCODING)

    const { query } = useRouter()
    const [shareTicket] = useMutation(SHARE_TICKET_MUTATION)

    const {
        publicRuntimeConfig: { serverUrl: origin },
    } = getConfig()

    const [chosenEmployees, setChosenEmployees] = useState([])
    const [loading, setLoading] = useState(false)
    const [shareVisible, setShareVisible] = useState(false)
    const [okVisible, setOkVisible] = useState(false)
    const [usersWithoutEmail, setUsersWithoutEmail] = useState([])

    const parseSelectValue = (selectedEmployees) => {
        try {
            return selectedEmployees.map(JSON.parse)
        } catch (error) {
            console.error('Invalid format for employees in multiple select', selectedEmployees)
        }
    }

    function handleSelect (value) {
        const withoutEmails = parseSelectValue(value).filter(item => !get(item, 'value.hasEmail')).map(item => item.text)
        setUsersWithoutEmail(withoutEmails)
        setChosenEmployees(value)
    }

    async function handleClick () {
        setLoading(true)
        const sender = getClientSideSenderInfo()
        const { data, error } = await shareTicket({
            variables: {
                data: {
                    sender,
                    employees: parseSelectValue(chosenEmployees).filter(employee => get(employee, 'value.hasEmail')).map(employee => employee.id),
                    ticketId: query.id,
                },
            },
        })
        if (data && data.obj) {
            setChosenEmployees([])
            setShareVisible(false)
            setOkVisible(true)
            setUsersWithoutEmail([])
        }
        if (error) {
            console.error(error)
            notification.error({
                message: ServerErrorMessage,
                description: error.message,
            })
        }
        setLoading(false)
    }

    function handleCancel () {
        setShareVisible(false)
    }

    function handleShow () {
        setShareVisible(true)
    }

    function handleClickSecond () {
        setOkVisible(false)
    }

    return (
        <>
            <Button
                type={'sberDefaultGradient'}
                icon={<ShareAltOutlined />}
                secondary
                onClick={handleShow}
                css={sendButton}
            >
                {ShareButtonMessage}
            </Button>
            <Modal
                style={{ top: 30 }}
                visible={okVisible}
                footer={<Button
                    type='sberPrimary'
                    size='large'
                    onClick={handleClickSecond}
                >
                    {OKMessage}
                </Button>}
                onCancel={handleCancel}
                title={ShareSentMessage}
            >
                {ShareSentToEmailMessage}
            </Modal>
            <Modal
                style={{ top: 30 }}
                visible={shareVisible}
                footer={null}
                onCancel={handleCancel}
                title={<Typography.Title level={isSmall ? 5 : 3}>{ShareHeaderMessage}</Typography.Title>}
            >
                <Row gutter={[0, 16]}>
                    <Col span={24}>
                        <a
                            target='_blank'
                            rel='noreferrer'
                            href={`https://wa.me/?text=${encodeURIComponent(`${origin}/share?q=${encryptedText}&locale=${locale || EN_LOCALE}`)}`}
                        >
                            <ShareButton>
                                {WhatsappMessage}
                                <RightOutlined />
                            </ShareButton>
                        </a>
                    </Col>
                    <Col span={24}>
                        <a
                            target='_blank'
                            rel='noreferrer'
                            href={`https://t.me/share/url?url=${encodeURIComponent(`${origin}/share?q=${encryptedText}&locale=${locale || EN_LOCALE}`)}`}
                        >
                            <ShareButton>
                                {TelegramMessage}
                                <RightOutlined />
                            </ShareButton>
                        </a>
                    </Col>
                    <Col span={24}>
                        <Collapse expandIconPosition='right' css={collapse}>
                            <Collapse.Panel key='1' header={ToEmployeesEmailMessage}>
                                <GraphQlSearchInput
                                    search={getEmployeeWithEmail(get(organization, 'id'))}
                                    showArrow={false}
                                    mode='multiple'
                                    css={search}
                                    onChange={handleSelect}
                                    value={chosenEmployees}
                                    placeholder={EmployeesNameMessage}
                                    autoClearSearchValue={true}
                                />
                                {
                                    !isEmpty(usersWithoutEmail) &&
                                    <Warning>
                                        {usersWithoutEmail}
                                    </Warning>
                                }
                                {
                                    !isEmpty(chosenEmployees) &&
                                    <Button
                                        type='sberPrimary'
                                        size='large'
                                        onClick={handleClick}
                                        style={{ marginTop: '20px' }}
                                        disabled={loading}
                                    >
                                        {SendTicketToEmailMessage}
                                    </Button>
                                }
                            </Collapse.Panel>
                        </Collapse>
                    </Col>
                </Row>
            </Modal>
        </>
    )
}
Example #11
Source File: VizOperationMenu.tsx    From datart with Apache License 2.0 4 votes vote down vote up
VizOperationMenu: FC<{
  onShareLinkClick?;
  onDownloadDataLinkClick?;
  onSaveAsVizs?;
  onReloadData?;
  onAddToDashBoard?;
  onPublish?;
  onRecycleViz?;
  allowDownload?: boolean;
  allowShare?: boolean;
  allowManage?: boolean;
  isArchived?: boolean;
}> = memo(
  ({
    onShareLinkClick,
    onDownloadDataLinkClick,
    onSaveAsVizs,
    onReloadData,
    onAddToDashBoard,
    onPublish,
    allowDownload,
    allowShare,
    allowManage,
    isArchived,
    onRecycleViz,
  }) => {
    const t = useI18NPrefix(`viz.action`);
    const tg = useI18NPrefix(`global`);

    const moreActionMenu = () => {
      const menus: any[] = [];

      if (onReloadData) {
        menus.push(
          <Menu.Item
            key="reloadData"
            icon={<ReloadOutlined />}
            onClick={onReloadData}
          >
            {t('syncData')}
          </Menu.Item>,
          <Menu.Divider key={'reloadDataLine'} />,
        );
      }

      if (allowManage && onSaveAsVizs) {
        menus.push(
          <Menu.Item key="saveAs" icon={<CopyFilled />} onClick={onSaveAsVizs}>
            {tg('button.saveAs')}
          </Menu.Item>,
        );
      }

      if (allowManage && onSaveAsVizs) {
        menus.push(
          <Menu.Item
            key="addToDash"
            icon={<FileAddOutlined />}
            onClick={() => onAddToDashBoard(true)}
          >
            {t('addToDash')}
          </Menu.Item>,
          <Menu.Divider key="addToDashLine" />,
        );
      }

      if (allowShare && onShareLinkClick) {
        menus.push(
          <Menu.Item
            key="shareLink"
            icon={<ShareAltOutlined />}
            onClick={onShareLinkClick}
          >
            {t('share.shareLink')}
          </Menu.Item>,
        );
      }

      if (allowDownload && onDownloadDataLinkClick) {
        menus.push(
          <Menu.Item key="downloadData" icon={<CloudDownloadOutlined />}>
            <Popconfirm
              placement="left"
              title={t('common.confirm')}
              onConfirm={() => {
                onDownloadDataLinkClick(DownloadFileType.Excel);
              }}
              okText={t('common.ok')}
              cancelText={t('common.cancel')}
            >
              {t('share.downloadData')}
            </Popconfirm>
          </Menu.Item>,
          <Menu.Item key="downloadPDF" icon={<CloudDownloadOutlined />}>
            <Popconfirm
              placement="left"
              title={t('common.confirm')}
              onConfirm={() => {
                onDownloadDataLinkClick(DownloadFileType.Pdf);
              }}
              okText={t('common.ok')}
              cancelText={t('common.cancel')}
            >
              {t('share.downloadPDF')}
            </Popconfirm>
          </Menu.Item>,
          <Menu.Item key="downloadPicture" icon={<CloudDownloadOutlined />}>
            <Popconfirm
              placement="left"
              title={t('common.confirm')}
              onConfirm={() => {
                onDownloadDataLinkClick(DownloadFileType.Image);
              }}
              okText={t('common.ok')}
              cancelText={t('common.cancel')}
            >
              {t('share.downloadPicture')}
            </Popconfirm>
          </Menu.Item>,
          <Menu.Divider />,
          <Menu.Divider key="downloadDataLine" />,
        );
      }

      if (allowManage && !isArchived && onPublish) {
        menus.push(
          <Menu.Item
            key="publish"
            icon={<VerticalAlignBottomOutlined />}
            onClick={onPublish}
          >
            {t('unpublish')}
          </Menu.Item>,
        );
      }

      if (allowManage && onRecycleViz) {
        menus.push(
          <Menu.Item key="delete" icon={<DeleteOutlined />}>
            <Popconfirm
              title={tg('operation.archiveConfirm')}
              onConfirm={onRecycleViz}
            >
              {tg('button.archive')}
            </Popconfirm>
          </Menu.Item>,
        );
      }

      return <Menu>{menus}</Menu>;
    };

    return <StyleVizOperationMenu>{moreActionMenu()}</StyleVizOperationMenu>;
  },
)
Example #12
Source File: BoardDropdownList.tsx    From datart with Apache License 2.0 4 votes vote down vote up
BoardDropdownList: FC<Props> = memo(
  ({ onOpenShareLink, openStoryList }) => {
    const t = useI18NPrefix(`viz.action`);
    const tg = useI18NPrefix(`global`);
    const dispatch = useDispatch();
    const {
      allowDownload,
      allowShare,
      allowManage,
      renderMode,
      status,
      orgId,
      boardId,
    } = useContext(BoardContext);
    const recycleViz = useRecycleViz(orgId, boardId, 'DASHBOARD');
    const saveAsViz = useSaveAsViz();
    const reloadData = () => {
      dispatch(widgetsQueryAction({ boardId, renderMode }));
    };
    const { onBoardToDownLoad } = useContext(BoardActionContext);
    const { publishBoard } = usePublishBoard(boardId, 'DASHBOARD', status);
    return (
      <Menu>
        <Menu.Item
          key="reloadData"
          onClick={reloadData}
          icon={<ReloadOutlined />}
        >
          {t('syncData')}
        </Menu.Item>
        {allowShare && (
          <>
            <Menu.Divider key={'shareLinkLine'} />
            <Menu.Item
              key={'shareLink'}
              onClick={onOpenShareLink}
              icon={<ShareAltOutlined />}
            >
              {t('share.shareLink')}
            </Menu.Item>
          </>
        )}
        {allowDownload && (
          <>
            <Menu.Divider key={'downloadDataLine'} />
            <Menu.Item key={'downloadData'} icon={<CloudDownloadOutlined />}>
              <Popconfirm
                placement="left"
                title={t('common.confirm')}
                okText={t('common.ok')}
                cancelText={t('common.cancel')}
                onConfirm={() => {
                  onBoardToDownLoad?.(DownloadFileType.Excel);
                }}
              >
                {t('share.downloadData')}
              </Popconfirm>
            </Menu.Item>
            <Menu.Item key={'downloadPDF'} icon={<CloudDownloadOutlined />}>
              <Popconfirm
                placement="left"
                title={t('common.confirm')}
                okText={t('common.ok')}
                cancelText={t('common.cancel')}
                onConfirm={() => {
                  onBoardToDownLoad?.(DownloadFileType.Pdf);
                }}
              >
                {t('share.downloadPDF')}
              </Popconfirm>
            </Menu.Item>
            <Menu.Item key={'downloadPicture'} icon={<CloudDownloadOutlined />}>
              <Popconfirm
                placement="left"
                title={t('common.confirm')}
                okText={t('common.ok')}
                cancelText={t('common.cancel')}
                onConfirm={() => {
                  onBoardToDownLoad?.(DownloadFileType.Image);
                }}
              >
                {t('share.downloadPicture')}
              </Popconfirm>
            </Menu.Item>
          </>
        )}
        {allowManage && (
          <>
            <Menu.Divider key="unpublishLine" />
            {status === 2 && (
              <Menu.Item
                key={'unpublish'}
                onClick={publishBoard}
                icon={<FileAddOutlined />}
              >
                {t('unpublish')}
              </Menu.Item>
            )}

            <Menu.Item
              key={'saveAs'}
              onClick={() => saveAsViz(boardId, 'DASHBOARD')}
              icon={<CopyFilled />}
            >
              {tg('button.saveAs')}
            </Menu.Item>
            <Menu.Item
              key={'addToStory'}
              onClick={openStoryList}
              icon={<FileAddOutlined />}
            >
              {t('addToStory')}
            </Menu.Item>
            <Menu.Item
              key={'archive'}
              onClick={recycleViz}
              icon={<DeleteOutlined />}
            >
              {tg('button.archive')}
            </Menu.Item>
          </>
        )}
      </Menu>
    );
  },
)