@ant-design/icons#ExportOutlined TypeScript Examples

The following examples show how to use @ant-design/icons#ExportOutlined. 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: ActionsTab.tsx    From posthog-foss with MIT License 6 votes vote down vote up
export function ActionsTab(): JSX.Element {
    const { selectedAction } = useValues(actionsTabLogic)
    const { apiURL } = useValues(toolbarLogic)

    return (
        <div className="toolbar-content">
            <div className="toolbar-block action-block-body">
                {selectedAction ? (
                    <EditAction />
                ) : (
                    <>
                        <ActionsList />
                        <div style={{ textAlign: 'right' }}>
                            <a href={`${apiURL}${urls.actions()}`} target="_blank" rel="noopener noreferrer">
                                View &amp; edit all actions <ExportOutlined />
                            </a>
                        </div>
                    </>
                )}
            </div>
        </div>
    )
}
Example #2
Source File: Persons.tsx    From posthog-foss with MIT License 5 votes vote down vote up
export function Persons({ cohort }: PersonsProps = {}): JSX.Element {
    const personsLogicProps: PersonLogicProps = { cohort: cohort?.id, syncWithUrl: !cohort }
    const { loadPersons, setListFilters } = useActions(personsLogic(personsLogicProps))
    const { persons, listFilters, personsLoading } = useValues(personsLogic(personsLogicProps))

    return (
        <BindLogic logic={personsLogic} props={personsLogicProps}>
            <div className="persons-list">
                <PersonPageHeader hideGroupTabs={!!cohort} />
                <Row align="middle" justify="space-between" className="mb" style={{ gap: '0.75rem' }}>
                    <PersonsSearch autoFocus={!cohort} />
                    <div>
                        <Button
                            type="default"
                            icon={<ExportOutlined />}
                            href={'/api/person.csv' + (listFilters.cohort ? '?cohort=' + listFilters.cohort : '')}
                            style={{ marginLeft: 8 }}
                        >
                            Export
                        </Button>
                    </div>
                </Row>
                <PropertyFilters
                    pageKey="persons-list-page"
                    propertyFilters={listFilters.properties}
                    onChange={(properties) => {
                        setListFilters({ properties })
                        loadPersons()
                    }}
                    endpoint="person"
                    taxonomicGroupTypes={[TaxonomicFilterGroupType.PersonProperties, TaxonomicFilterGroupType.Cohorts]}
                    showConditionBadge
                />
                <PersonsTable
                    people={persons.results}
                    loading={personsLoading}
                    hasPrevious={!!persons.previous}
                    hasNext={!!persons.next}
                    loadPrevious={() => loadPersons(persons.previous)}
                    loadNext={() => loadPersons(persons.next)}
                />
            </div>
        </BindLogic>
    )
}
Example #3
Source File: index.tsx    From LogicFlow with Apache License 2.0 5 votes vote down vote up
export default function AdapterExample() {
  useEffect(() => {
    // 注册插件
    LogicFlow.use(BpmnAdapter);
    LogicFlow.use(Control);
    LogicFlow.use(DndPanel);

    lf = new LogicFlow({
      container: document.querySelector('#graph') as HTMLElement,
      stopScrollGraph: true,
      stopZoomGraph: true,
    });
    lf.extension.dndPanel.setPatternItems(dndItem);
    lf.render();
  }, []);

  function download(filename: string, text: string) {
    var element = document.createElement('a');
    element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    element.setAttribute('download', filename);
    element.style.display = 'none';
    document.body.appendChild(element);
    element.click();
    document.body.removeChild(element);
  }

  function exportAdapterData() {
    const adapterData = lf.getGraphData();
    download('logic-flow.json', JSON.stringify(adapterData));
  }

  return (
    <>
      <ExampleHeader githubPath="/extension/adapter/index.tsx">
        导出 bpmnAdapter 转换后的数据格式:
        <Button
          shape="round"
          icon={<ExportOutlined />}
          onClick={exportAdapterData}
        />
      </ExampleHeader>
      <div id="graph" className="viewport"></div>
    </>
  );
}
Example #4
Source File: ActionStep.tsx    From posthog-foss with MIT License 4 votes vote down vote up
function AutocaptureFields({
    step,
    actionId,
    sendStep,
}: {
    step: ActionStepType
    sendStep: (stepToSend: ActionStepType) => void
    actionId: number
}): JSX.Element {
    const AndC = (): JSX.Element => {
        return (
            <div className="text-center">
                <span className="stateful-badge and">AND</span>
            </div>
        )
    }
    return (
        <div>
            <span>
                <AppEditorLink actionId={actionId} style={{ margin: '1rem 0' }}>
                    Select element on site <ExportOutlined />
                </AppEditorLink>
                <a
                    href={`${learnMoreLink}#autocapture-based-actions`}
                    target="_blank"
                    rel="noopener"
                    style={{ marginLeft: 8 }}
                >
                    See documentation.
                </a>{' '}
            </span>
            <Option
                step={step}
                sendStep={sendStep}
                item="href"
                label="Link target equals"
                caption={
                    <>
                        If your element is a link, the location that the link opens (<code>href</code> tag)
                    </>
                }
            />
            <AndC />
            <Option
                step={step}
                sendStep={sendStep}
                item="text"
                label="Text equals"
                caption="Text content inside your element"
            />
            <AndC />
            <Option
                step={step}
                sendStep={sendStep}
                item="selector"
                label={
                    <>
                        HTML selector matches
                        <Tooltip title="Click here to learn more about supported selectors">
                            <a href={`${learnMoreLink}#matching-selectors`} target="_blank" rel="noopener">
                                <InfoCircleOutlined style={{ marginLeft: 4 }} />
                            </a>
                        </Tooltip>
                    </>
                }
                placeholder='button[data-attr="my-id"]'
                caption={
                    <Space direction="vertical">
                        <Text style={{ color: 'var(--muted)' }}>
                            CSS selector or an HTML attribute that ideally uniquely identifies your element. Example:{' '}
                            <Text code>[data-attr="signup"]</Text>
                        </Text>
                    </Space>
                }
            />
            <div style={{ marginBottom: 18 }}>
                <AndC />
            </div>
            <Option
                step={step}
                sendStep={sendStep}
                item="url"
                extra_options={<URLMatching step={step} sendStep={sendStep} />}
                label="Page URL"
                caption="Elements will match only when triggered from the URL (particularly useful if you have non-unique elements in different pages)."
            />
            {step?.url_matching && step.url_matching in URL_MATCHING_HINTS && (
                <small style={{ display: 'block', marginTop: -12 }}>{URL_MATCHING_HINTS[step.url_matching]}</small>
            )}
        </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: List.tsx    From fe-v5 with Apache License 2.0 4 votes vote down vote up
export default function List(props: IProps) {
  const [list, setList] = useState([]);
  const [active, setActive] = useState<number>();
  const [search, setSearch] = useState('');
  const [refreshFlag, setRefreshFlag] = useState(_.uniqueId('refreshFlag_'));
  const { profile } = useSelector<AccountRootState, accountStoreState>((state) => state.account);
  useEffect(() => {
    const defaultMetricViewId = localStorage.getItem('metric-view-id') !== null ? Number(localStorage.getItem('metric-view-id')) : null;
    getList().then((res) => {
      setList(res);
      let curId;
      if (!defaultMetricViewId || !_.find(res, { id: defaultMetricViewId })) {
        curId = _.get(_.head(res), 'id');
      } else {
        curId = defaultMetricViewId;
      }
      if (curId) {
        setActive(curId);
        const curItem = _.find(res, { id: curId });
        let configs = {} as IMatch;
        try {
          configs = JSON.parse(curItem.configs);
          configs.id = curId;
          configs.refreshFlag = refreshFlag;
        } catch (e) {
          console.error(e);
        }
        props.onSelect({
          ...configs,
        });
      }
    });
  }, [refreshFlag]);

  return (
    <div className='n9e-metric-views-list'>
      <div className='n9e-metric-views-list-header'>
        <div className='metric-page-title'>快捷视图列表</div>
        <a>
          <PlusSquareOutlined
            onClick={() => {
              Form({
                admin: profile.admin,
                action: 'add',
                visible: true,
                range: props.range,
                onOk: (record) => {
                  localStorage.setItem('metric-view-id', record.id);
                  setRefreshFlag(_.uniqueId('refreshFlag_'));
                },
              });
            }}
          />
        </a>
      </div>
      <Input
        prefix={<SearchOutlined />}
        value={search}
        onChange={(e) => {
          setSearch(e.target.value);
        }}
      />
      <div className='n9e-metric-views-list-content'>
        {_.isEmpty(list)
          ? '暂无数据'
          : _.map(
              _.filter(list, (item) => {
                if (search) {
                  let result = true;
                  try {
                    const reg = new RegExp(search, 'gi');
                    result = reg.test(item.name);
                  } catch (e) {
                    console.log(e);
                  }
                  return result;
                }
                return true;
              }),
              (item) => {
                return (
                  <div
                    className={classNames({
                      'n9e-metric-views-list-content-item': true,
                      active: item.id === active,
                    })}
                    key={item.id}
                    onClick={() => {
                      setActive(item.id);
                      localStorage.setItem('metric-view-id', item.id);
                      const curItem = _.find(list, { id: item.id });
                      let configs = {} as IMatch;
                      try {
                        configs = JSON.parse(curItem.configs);
                        configs.id = item.id;
                      } catch (e) {
                        console.error(e);
                      }
                      props.onSelect({
                        ...configs,
                      });
                    }}
                  >
                    <span className='name'>{item.name}</span>
                    {item.cate === 1 || profile.admin ? (
                      <span>
                        {item.cate === 0 && (
                          <span className='n9e-metric-views-list-content-item-cate' style={{ color: '#ccc' }}>
                            公开
                          </span>
                        )}
                        <div className='n9e-metric-views-list-content-item-opes'>
                          <EditOutlined
                            onClick={(e) => {
                              e.stopPropagation();
                              let configs = {} as any;
                              try {
                                configs = JSON.parse(item.configs);
                                configs.dynamicLabels = _.map(configs.dynamicLabels, 'label');
                                configs.dimensionLabels = _.map(configs.dimensionLabels, 'label');
                              } catch (e) {
                                console.error(e);
                              }
                              const initialValues = {
                                id: item.id,
                                name: item.name,
                                cate: item.cate === 0,
                                ...configs,
                              };
                              Form({
                                admin: profile.admin,
                                action: 'edit',
                                visible: true,
                                range: props.range,
                                initialValues,
                                onOk: () => {
                                  localStorage.setItem('metric-view-id', item.id);
                                  setRefreshFlag(_.uniqueId('refreshFlag_'));
                                },
                              });
                            }}
                          />
                          <DeleteOutlined
                            onClick={(e) => {
                              e.stopPropagation();
                              Modal.confirm({
                                title: '是否要删除?',
                                onOk: () => {
                                  deleteMetricView({
                                    ids: [item.id],
                                  }).then(() => {
                                    message.success('删除成功');
                                    setRefreshFlag(_.uniqueId('refreshFlag_'));
                                  });
                                },
                              });
                            }}
                          />
                          <Tooltip title='导出配置' placement='right'>
                            <ExportOutlined
                              onClick={() => {
                                Export({
                                  visible: true,
                                  data: item.configs,
                                });
                              }}
                            />
                          </Tooltip>
                        </div>
                      </span>
                    ) : (
                      <span style={{ color: '#ccc' }}>公开</span>
                    )}
                  </div>
                );
              },
            )}
      </div>
    </div>
  );
}
Example #7
Source File: index.tsx    From Aragorn with MIT License 4 votes vote down vote up
FileManage = () => {
  const {
    state: {
      uploaderProfiles,
      configuration: { defaultUploaderProfileId }
    }
  } = useAppContext();

  const [windowHeight, setWindowHeight] = useState(window.innerHeight);

  useEffect(() => {
    function handleResize() {
      setWindowHeight(window.innerHeight);
    }
    window.addEventListener('resize', handleResize);

    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []);

  const { id } = useParams<{ id: string }>();

  const [hasFileManageFeature, setHasFileManageFeature] = useState(false);

  const [uploaderProfile, setUploaderProfile] = useState({} as UploaderProfile);

  useEffect(() => {
    const currentId = id || defaultUploaderProfileId;
    setCurrentProfile(currentId as string);
  }, []);

  useEffect(() => {
    if (uploaderProfile?.id) {
      getList();
    }
  }, [uploaderProfile]);

  const [list, setList] = useState([] as ListFile[]);
  const [listLoading, setListLoading] = useState(false);

  const getList = (directoryPath?: string) => {
    setListLoading(true);
    ipcRenderer.send('file-list-get', uploaderProfile.id, directoryPath);
  };

  const [dirPath, setDirPath] = useState([] as string[]);

  useEffect(() => {
    function handleListGetReply(_, res?: FileListResponse) {
      setListLoading(false);
      if (res === undefined) {
        setHasFileManageFeature(false);
        setList([]);
        message.info(`${uploaderProfile.uploaderName}暂不支持文件管理功能`);
        return;
      }
      setHasFileManageFeature(true);
      if (res.success) {
        setList(res.data);
      } else {
        message.error(`文件列表获取失败 ${res.desc || ''}`);
      }
    }

    function handleFileDeleteReply(_, res?: DeleteFileResponse) {
      if (res === undefined) {
        return;
      }
      if (res.success) {
        message.success({ content: '文件删除成功', key: 'file-manage-delete' });
        getList(dirPath.join('/'));
      } else {
        message.error({ content: `文件删除失败 ${res.desc || ''}`, key: 'file-manage-delete' });
      }
    }

    function handleFileUploadReply() {
      getList(dirPath.join('/'));
    }

    function handleDirectoryCreateReply(_, res?: CreateDirectoryResponse) {
      if (res === undefined) {
        return;
      }
      if (res.success) {
        message.success('目录创建成功');
        setModalVisible(false);
        getList(dirPath.join('/'));
      } else {
        message.error(`目录创建失败 ${res.desc || ''}`);
      }
    }

    function handleExportReplay(_, res) {
      setExportLoading(false);
      if (res) {
        shell.showItemInFolder(res);
        setRowKeys([]);
        setSelectRows([]);
      }
    }

    ipcRenderer.on('file-list-get-reply', handleListGetReply);
    ipcRenderer.on('file-delete-reply', handleFileDeleteReply);
    ipcRenderer.on('file-upload-reply', handleFileUploadReply);
    ipcRenderer.on('directory-create-reply', handleDirectoryCreateReply);
    ipcRenderer.on('export-reply', handleExportReplay);

    return () => {
      ipcRenderer.removeListener('file-list-get-reply', handleListGetReply);
      ipcRenderer.removeListener('file-delete-reply', handleFileDeleteReply);
      ipcRenderer.removeListener('file-upload-reply', handleFileUploadReply);
      ipcRenderer.removeListener('directory-create-reply', handleDirectoryCreateReply);
      ipcRenderer.removeListener('export-reply', handleExportReplay);
    };
  }, [uploaderProfile, dirPath]);

  const handleNameClick = (record: ListFile) => {
    if (record.type === 'directory') {
      const newPath = [...dirPath, formatFileName(record.name)];
      setDirPath(newPath);
      getList(newPath.join('/'));
    } else {
      clipboard.writeText(record.url as string);
      message.success('链接已复制到粘贴板');
    }
  };

  const handlePathClick = (index: number) => {
    if (index === -1) {
      setDirPath([]);
      getList();
    } else {
      const newPath = dirPath.slice(0, index + 1);
      setDirPath(newPath);
      getList(newPath.join('/'));
    }
  };

  const setCurrentProfile = (uploaderProfileId: string) => {
    setDirPath([]);
    const uploaderProfile = uploaderProfiles.find(item => item.id === uploaderProfileId);
    setUploaderProfile(uploaderProfile as UploaderProfile);
  };

  const formatFileName = (name: string) => {
    if (dirPath.length > 0) {
      const pathPrefix = dirPath.join('/') + '/';
      return name.split(pathPrefix).pop() || '';
    } else {
      return name;
    }
  };

  const [selectRowKeys, setRowKeys] = useState([] as string[]);
  const [selectRows, setSelectRows] = useState([] as ListFile[]);

  const handleTableRowChange = (selectedRowKeys, selectedRows: ListFile[]) => {
    setRowKeys(selectedRowKeys);
    setSelectRows(selectedRows);
  };

  const handleRefresh = () => {
    getList(dirPath.join('/'));
  };

  const handleBatchDelete = () => {
    Modal.confirm({
      title: '确认删除',
      onOk: () => {
        const names = selectRows.map(item => [...dirPath, formatFileName(item.name)].join('/'));
        message.info({ content: '正在删除,请稍后...', key: 'file-manage-delete' });
        ipcRenderer.send('file-delete', uploaderProfile.id, names);
      }
    });
  };

  const handleDelete = (record: ListFile) => {
    let name = record.name;
    Modal.confirm({
      title: '确认删除',
      content: name,
      onOk: () => {
        let name = record.name;
        if (record.type === 'directory') {
          name = `${[...dirPath, record.name].join('/')}/`;
        } else {
          name = [...dirPath, formatFileName(record.name)].join('/');
        }
        message.info({ content: '正在删除,请稍后...', key: 'file-manage-delete' });
        ipcRenderer.send('file-delete', uploaderProfile.id, [name]);
      }
    });
  };

  const uploadRef = useRef<HTMLInputElement>(null);

  const handleFileUpload = (event: React.FormEvent<HTMLInputElement>) => {
    const fileList = event.currentTarget.files || [];
    const filesPath = Array.from(fileList).map(file => file.path);
    const pathPrefix = dirPath.join('/');
    ipcRenderer.send('file-upload', uploaderProfile.id, filesPath, pathPrefix);
    event.currentTarget.value = '';
  };

  const [modalVisible, setModalVisible] = useState(false);

  const [form] = Form.useForm();

  const handleCreateDirectory = () => {
    form.validateFields().then(values => {
      ipcRenderer.send('directory-create', uploaderProfile.id, values?.directoryPath || '');
    });
  };

  const handleDownload = (record: ListFile) => {
    ipcRenderer.send('file-download', record.name, record.url);
  };

  const [exportLoading, setExportLoading] = useState(false);

  const handleExport = () => {
    const data = selectRows.map(item => {
      const fileNameArr = item.name.split('.');
      fileNameArr.pop();
      return {
        name: fileNameArr.join('.'),
        url: item.url
      };
    });
    setExportLoading(true);
    ipcRenderer.send('export', data);
  };

  const columns: ColumnsType<ListFile> = [
    {
      title: '文件名',
      dataIndex: 'name',
      ellipsis: true,
      render: (val: string, record: ListFile) => (
        <div style={{ display: 'flex', alignItems: 'center' }}>
          {record.type === 'directory' ? (
            <FolderFilled style={{ fontSize: 16 }} />
          ) : (
            <FileOutlined style={{ fontSize: 16 }} />
          )}
          {record.type === 'directory' ? (
            <a
              title={val}
              onClick={() => handleNameClick(record)}
              className="table-filename"
              style={{ marginLeft: 10, overflow: 'hidden', textOverflow: 'ellipsis' }}
            >
              {formatFileName(val)}
            </a>
          ) : (
            <Popover
              placement="topLeft"
              content={() =>
                /(jpg|png|gif|jpeg)$/.test(val) ? (
                  <Image
                    style={{ maxWidth: 500 }}
                    src={record.url}
                    fallback="data:image/png;base64,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"
                  />
                ) : (
                  val
                )
              }
              trigger="hover"
            >
              <a
                title={val}
                onClick={() => handleNameClick(record)}
                className="table-filename"
                style={{ marginLeft: 10, overflow: 'hidden', textOverflow: 'ellipsis' }}
              >
                {formatFileName(val)}
              </a>
            </Popover>
          )}
        </div>
      )
    },
    {
      title: '文件大小',
      dataIndex: 'size',
      ellipsis: true,
      width: 120,
      render: val => (val ? filesize(val) : '-')
    },
    {
      title: '更新时间',
      dataIndex: 'lastModified',
      ellipsis: true,
      width: 200,
      render: val => (val ? dayjs(val).format('YYYY-MM-DD HH:mm:ss') : '-')
    },
    {
      title: '操作',
      width: 120,
      render: (_, record) => (
        <Space>
          {record.type !== 'directory' && (
            <>
              <DownloadOutlined onClick={() => handleDownload(record)} />
              <CopyOutlined onClick={() => handleNameClick(record)} />
            </>
          )}
          <DeleteOutlined onClick={() => handleDelete(record)} />
        </Space>
      )
    }
  ];

  return (
    <div className="storage-page">
      <header>
        <span>文件管理</span>
        <Divider />
      </header>
      <Space style={{ marginBottom: 10 }}>
        <Select style={{ minWidth: 120 }} value={uploaderProfile?.id} onChange={setCurrentProfile}>
          {uploaderProfiles.map(item => (
            <Select.Option key={item.name} value={item.id}>
              {item.name}
            </Select.Option>
          ))}
        </Select>
        <Button
          title="上传"
          icon={<UploadOutlined />}
          disabled={!hasFileManageFeature}
          type="primary"
          onClick={() => {
            uploadRef.current?.click();
          }}
        />
        <Button title="刷新" icon={<ReloadOutlined />} disabled={!hasFileManageFeature} onClick={handleRefresh} />
        <Button
          title="创建文件夹"
          icon={<FolderAddOutlined />}
          disabled={!hasFileManageFeature}
          onClick={() => {
            setModalVisible(true);
          }}
        />
        <Button
          title="导出"
          icon={<ExportOutlined />}
          disabled={selectRows.length === 0}
          onClick={handleExport}
          loading={exportLoading}
        />
        <Button title="删除" icon={<DeleteOutlined />} disabled={selectRows.length === 0} onClick={handleBatchDelete} />
      </Space>
      <Breadcrumb style={{ marginBottom: 10 }}>
        <Breadcrumb.Item>
          <a onClick={() => handlePathClick(-1)}>全部文件</a>
        </Breadcrumb.Item>
        {dirPath.map((item, index) => (
          <Breadcrumb.Item key={item}>
            <a onClick={() => handlePathClick(index)}>{item}</a>
          </Breadcrumb.Item>
        ))}
      </Breadcrumb>
      <div className="table-wrapper">
        <Table
          size="small"
          rowKey="name"
          scroll={{ y: windowHeight - 270 }}
          dataSource={list}
          columns={columns}
          pagination={{
            size: 'small',
            defaultPageSize: 100,
            pageSizeOptions: ['50', '100', '200'],
            hideOnSinglePage: true
          }}
          loading={listLoading}
          rowSelection={{
            onChange: handleTableRowChange,
            selectedRowKeys: selectRowKeys,
            getCheckboxProps: record => ({ disabled: record?.type === 'directory' })
          }}
        />
      </div>
      <input ref={uploadRef} type="file" multiple hidden onChange={handleFileUpload} />
      <Modal
        title="创建目录"
        visible={modalVisible}
        onCancel={() => setModalVisible(false)}
        onOk={handleCreateDirectory}
        destroyOnClose={true}
      >
        <Form form={form} preserve={false}>
          <Form.Item
            label="目录名称"
            name="directoryPath"
            rules={[{ required: true }, { pattern: domainPathRegExp, message: '目录名不能以 / 开头或结尾' }]}
          >
            <Input autoFocus />
          </Form.Item>
        </Form>
      </Modal>
    </div>
  );
}
Example #8
Source File: index.tsx    From surveyo with Apache License 2.0 4 votes vote down vote up
function DashboardHelper() {
  const {user} = useAuth0();

  const [state, setState] = useState([]);

  const [deleteForm] = useMutation<DeleteForm, DeleteFormVariables>(
    DELETE_FORM
  );

  const {loading, error, data} = useQuery<GetSurveys, GetSurveysVariables>(
    GET_FORMS,
    {
      variables: {
        email: user.email,
      },
      onCompleted: () => {
        setState((data?.getUser?.forms || []) as any);
      },
    }
  );

  if (loading) {
    return <Card loading />;
  }

  if (error) {
    console.error(error);
    return <Alert message={error.message} type="warning" />;
  }

  async function handleDelete(id: string) {
    setState(state => state.filter((form: any) => form?.id !== id));

    try {
      await deleteForm({
        variables: {
          id,
        },
      });
    } catch (e) {
      console.error(e);
      message.error('Internal error: could not delete form');
    }
  }

  const tableCols = [
    {
      title: 'Title',
      dataIndex: 'title',
      key: 'title',
      render: (text: any) => text,
    },
    {
      title: 'Responses',
      dataIndex: 'responses',
      key: 'responses',
      render: (_text: any, record: any) => record.responses?.length || 0,
    },
    {
      title: 'Actions',
      key: 'action',
      render: (_text: any, record: any) => (
        <Space size="middle">
          <Tooltip title="Open form">
            <Link to={`/form/${record.id}`} target="_blank">
              <Button type="link" icon={<ExportOutlined />} />
            </Link>
          </Tooltip>
          <Tooltip title="Download CSV">
            <DownloadCsv id={record.id} title={record.title} />
          </Tooltip>
          <Tooltip title="Charts">
            <Link to={`/charts/${record.id}`} target="_blank">
              <Button type="link" icon={<LineChartOutlined />} />
            </Link>
          </Tooltip>
          <Tooltip title="GraphiQL">
            <Link to={`/graphiql/${record.id}`} target="_blank">
              <Button type="link" icon={<CodeOutlined />} />
            </Link>
          </Tooltip>
          <Tooltip title="Delete">
            <Popconfirm
              title="Are you sure you want to delete this form?"
              onConfirm={() => handleDelete(record.id)}
              okText="Yes"
              cancelText="No"
            >
              <Button type="link" icon={<DeleteOutlined />} />
            </Popconfirm>
          </Tooltip>
        </Space>
      ),
    },
  ];

  return <Table columns={tableCols as any} dataSource={state as any} />;
}
Example #9
Source File: index.tsx    From datart with Apache License 2.0 4 votes vote down vote up
export function Navbar() {
  const { actions } = useMainSlice();
  const [profileVisible, setProfileVisible] = useState(false);
  const [modifyPasswordVisible, setModifyPasswordVisible] = useState(false);
  const dispatch = useDispatch();
  const history = useHistory();
  const { i18n } = useTranslation();
  const systemInfo = useSelector(selectSystemInfo);
  const orgId = useSelector(selectOrgId);
  const currentOrganization = useSelector(selectCurrentOrganization);
  const loggedInUser = useSelector(selectLoggedInUser);
  const organizationListLoading = useSelector(selectOrganizationListLoading);
  const downloadPolling = useSelector(selectDownloadPolling);
  const themeKey = useSelector(selectThemeKey);
  const matchModules = useRouteMatch<{ moduleName: string }>(
    '/organizations/:orgId/:moduleName',
  );

  const t = useI18NPrefix('main');
  const brandClick = useCallback(() => {
    history.push('/');
  }, [history]);

  const hideProfile = useCallback(() => {
    setProfileVisible(false);
  }, []);
  const hideModifyPassword = useCallback(() => {
    setModifyPasswordVisible(false);
  }, []);

  const organizationListVisibleChange = useCallback(
    visible => {
      if (visible && !organizationListLoading) {
        dispatch(getOrganizations());
      }
    },
    [dispatch, organizationListLoading],
  );

  const subNavs = useMemo(
    () => [
      {
        name: 'variables',
        title: t('subNavs.variables.title'),
        icon: <FunctionOutlined />,
        module: ResourceTypes.Manager,
      },
      {
        name: 'orgSettings',
        title: t('subNavs.orgSettings.title'),
        icon: <SettingOutlined />,
        module: ResourceTypes.Manager,
      },
    ],
    [t],
  );

  const navs = useMemo(
    () => [
      {
        name: 'vizs',
        title: t('nav.vizs'),
        icon: <i className="iconfont icon-xietongzhihuidaping" />,
        module: ResourceTypes.Viz,
      },
      {
        name: 'views',
        title: t('nav.views'),
        icon: <i className="iconfont icon-24gf-table" />,
        module: ResourceTypes.View,
      },
      {
        name: 'sources',
        title: t('nav.sources'),
        icon: <i className="iconfont icon-shujukupeizhi" />,
        module: ResourceTypes.Source,
      },
      {
        name: 'schedules',
        title: t('nav.schedules'),
        icon: <i className="iconfont icon-fasongyoujian" />,
        module: ResourceTypes.Schedule,
      },
      {
        name: 'members',
        title: t('nav.members'),
        icon: <i className="iconfont icon-users1" />,
        isActive: (_, location) =>
          !!location.pathname.match(
            /\/organizations\/[\w]{32}\/(members|roles)/,
          ),
        module: ResourceTypes.User,
      },
      {
        name: 'permissions',
        title: t('nav.permissions'),
        icon: <SafetyCertificateFilled />,
        module: ResourceTypes.Manager,
      },
      {
        name: 'toSub',
        title: t('nav.settings'),
        icon: <SettingFilled />,
        isActive: (_, location) => {
          const reg = new RegExp(
            `\\/organizations\\/[\\w]{32}\\/(${subNavs
              .map(({ name }) => name)
              .join('|')})`,
          );
          return !!location.pathname.match(reg);
        },
        module: ResourceTypes.Manager,
      },
    ],
    [subNavs, t],
  );

  const showSubNav = useMemo(
    () => subNavs.some(({ name }) => name === matchModules?.params.moduleName),
    [matchModules?.params.moduleName, subNavs],
  );

  const handleChangeThemeFn = useCallback(
    (theme: ThemeKeyType) => {
      if (themeKey !== theme) {
        dispatch(themeSlice.actions.changeTheme(theme));
        changeAntdTheme(theme);
        saveTheme(theme);
      }
    },
    [dispatch, themeKey],
  );

  const userMenuSelect = useCallback(
    ({ key }) => {
      switch (key) {
        case 'profile':
          setProfileVisible(true);
          break;
        case 'logout':
          dispatch(
            logout(() => {
              history.replace('/');
            }),
          );
          break;
        case 'password':
          setModifyPasswordVisible(true);
          break;
        case 'zh':
        case 'en':
          if (i18n.language !== key) {
            changeLang(key);
          }
          break;
        case 'dark':
        case 'light':
          handleChangeThemeFn(key);
          break;
        default:
          break;
      }
    },
    [dispatch, history, i18n, handleChangeThemeFn],
  );

  const onSetPolling = useCallback(
    (polling: boolean) => {
      dispatch(actions.setDownloadPolling(polling));
    },
    [dispatch, actions],
  );

  return (
    <>
      <MainNav>
        <Brand onClick={brandClick}>
          <img src={logo} alt="logo" />
        </Brand>
        <Nav>
          {navs.map(({ name, title, icon, isActive, module }) => {
            return name !== 'toSub' || subNavs.length > 0 ? (
              <Access
                key={name}
                type="module"
                module={module}
                level={PermissionLevels.Enable}
              >
                <Tooltip title={title} placement="right">
                  <NavItem
                    to={`/organizations/${orgId}/${
                      name === 'toSub' ? subNavs[0].name : name
                    }`}
                    activeClassName="active"
                    {...(isActive && { isActive })}
                  >
                    {icon}
                  </NavItem>
                </Tooltip>
              </Access>
            ) : null;
          })}
        </Nav>
        <Toolbar>
          <DownloadListPopup
            polling={downloadPolling}
            setPolling={onSetPolling}
            onLoadTasks={loadTasks}
            onDownloadFile={item => {
              if (item.id) {
                downloadFile(item.id).then(() => {
                  dispatch(actions.setDownloadPolling(true));
                });
              }
            }}
          />
          {systemInfo?.tenantManagementMode ===
            TenantManagementMode.Platform && (
            <Popup
              content={<OrganizationList />}
              trigger={['click']}
              placement="rightBottom"
              onVisibleChange={organizationListVisibleChange}
            >
              <li>
                <Tooltip title={t('nav.organization.title')} placement="right">
                  <Avatar
                    src={`${BASE_RESOURCE_URL}${currentOrganization?.avatar}`}
                  >
                    <BankFilled />
                  </Avatar>
                </Tooltip>
              </li>
            </Popup>
          )}
          <Popup
            content={
              <Menu
                prefixCls="ant-dropdown-menu"
                selectable={false}
                onClick={userMenuSelect}
              >
                <MenuListItem
                  key="language"
                  prefix={<GlobalOutlined className="icon" />}
                  title={<p>{t('nav.account.switchLanguage.title')}</p>}
                  sub
                >
                  <MenuListItem key="zh">中文</MenuListItem>
                  <MenuListItem key="en">English</MenuListItem>
                </MenuListItem>
                <MenuListItem
                  key="theme"
                  prefix={<SkinOutlined className="icon" />}
                  title={<p>{t('nav.account.switchTheme.title')}</p>}
                  sub
                >
                  <MenuListItem key="light" prefix={<ThemeBadge />}>
                    {t('nav.account.switchTheme.light')}
                  </MenuListItem>
                  <MenuListItem
                    key="dark"
                    prefix={<ThemeBadge background={BLACK} />}
                  >
                    {t('nav.account.switchTheme.dark')}
                  </MenuListItem>
                </MenuListItem>
                <Menu.Divider />
                <MenuListItem
                  key="profile"
                  prefix={<ProfileOutlined className="icon" />}
                >
                  <p>{t('nav.account.profile.title')}</p>
                </MenuListItem>
                <MenuListItem
                  key="password"
                  prefix={<FormOutlined className="icon" />}
                >
                  <p>{t('nav.account.changePassword.title')}</p>
                </MenuListItem>
                <MenuListItem
                  key="logout"
                  prefix={<ExportOutlined className="icon" />}
                >
                  <p>{t('nav.account.logout.title')}</p>
                </MenuListItem>
              </Menu>
            }
            trigger={['click']}
            placement="rightBottom"
          >
            <li>
              <Avatar src={`${BASE_RESOURCE_URL}${loggedInUser?.avatar}`}>
                <UserOutlined />
              </Avatar>
            </li>
          </Popup>
        </Toolbar>
        <Profile visible={profileVisible} onCancel={hideProfile} />
        <ModifyPassword
          visible={modifyPasswordVisible}
          onCancel={hideModifyPassword}
        />
      </MainNav>
      {showSubNav && (
        <SubNav>
          <List
            dataSource={subNavs}
            renderItem={({ name, title, icon }) => (
              <SubNavTitle
                key={name}
                to={`/organizations/${orgId}/${name}`}
                activeClassName="active"
              >
                {cloneElement(icon, { className: 'prefix' })}
                <h4>{title}</h4>
              </SubNavTitle>
            )}
          />
        </SubNav>
      )}
    </>
  );
}
Example #10
Source File: CollectionCell.tsx    From Protoman with MIT License 4 votes vote down vote up
CollectionCell: React.FunctionComponent<Props> = ({ collectionName }) => {
  const dispatch = useDispatch();

  const collection = useSelector((s: AppState) => getByKey(s.collections, collectionName));
  const collectionNames = useSelector(selectColNames);

  const [menuVisible, setMenuVisible] = React.useState(false);
  const [isEditingName, setIsEditingName] = React.useState(false);
  const [isInvalidName, setIsInvalidName] = React.useState(false);
  const [draftName, setDraftName] = React.useState(collectionName);

  React.useEffect(() => {
    setDraftName(collectionName);
  }, [collectionName]);

  function showMenu(): void {
    setMenuVisible(true);
  }

  function hideMenu(): void {
    setMenuVisible(false);
  }

  function startEditing(): void {
    setIsEditingName(true);
    hideMenu();
  }

  function stopEditing(): void {
    setIsEditingName(false);
  }

  const collectionSize = Object.keys(collection?.flows || {}).length;

  function handleDelete(): void {
    if (collectionNames.length > 1) {
      dispatch(deleteCollection(collectionName));
    } else {
      message.error("Can't delete the last collection");
    }
    hideMenu();
  }

  function checkName(newName: string): boolean {
    return validateCollectionName(newName, collectionName, collectionNames);
  }

  function handleNameChange(newName: string): void {
    if (checkName(newName)) {
      dispatch(changeCollectionName(collectionName, newName));
    }
  }

  function handleOpenFM(): void {
    dispatch(openFM(collectionName));
    hideMenu();
  }

  function validateFlowName(flowName: string): boolean {
    return !collection?.flows?.map(([n]) => n)?.includes(flowName);
  }

  function handleCreate(): void {
    const tmpName = 'Request';
    let tmpNameIdx = 1;
    while (!validateFlowName(`${tmpName}${tmpNameIdx}`)) tmpNameIdx++;
    dispatch(createFlow(collectionName, `${tmpName}${tmpNameIdx}`));
    hideMenu();
  }

  function handleExport(): void {
    if (collection) {
      // error display is done in index.ts
      exportCollection(collectionName, collection);
    }
  }

  const menu = (
    <>
      <Button type="link" onClick={prevent(handleOpenFM)}>
        <FilePptOutlined />
        Manage .proto files
      </Button>
      <Separator />
      <Button type="link" onClick={prevent(handleCreate)}>
        <PlusOutlined />
        New Request
      </Button>
      <Separator />
      <Button type="link" onClick={prevent(startEditing)}>
        <EditOutlined />
        Edit Name
      </Button>
      <Separator />
      <Button type="link" onClick={prevent(handleExport)}>
        <ExportOutlined />
        Export Collection
      </Button>
      <Separator />
      <Button type="link" danger onClick={prevent(handleDelete)}>
        <DeleteOutlined />
        Delete Collection
      </Button>
    </>
  );

  return (
    <Popover
      placement="rightTop"
      content={menu}
      visible={menuVisible}
      trigger="contextMenu"
      onVisibleChange={setMenuVisible}
    >
      <TableData onContextMenu={prevent(showMenu)}>
        {isEditingName ? (
          <Form.Item
            validateStatus={isInvalidName ? 'error' : ''}
            style={{ margin: 0 }}
            help={isInvalidName ? 'Invalid Name' : ''}
          >
            <TitleInput
              value={draftName}
              onChange={(e): void => {
                setIsInvalidName(!checkName(e.target.value));
                setDraftName(e.target.value);
              }}
              onKeyDown={(e): void => {
                switch (e.keyCode) {
                  case 27: // esc
                    setDraftName(collectionName);
                    stopEditing();
                    break;
                  case 13: // enter
                    if (!isInvalidName) {
                      handleNameChange(draftName);
                      stopEditing();
                    }
                }
              }}
              onClick={prevent(e => e)}
            />
          </Form.Item>
        ) : (
          <Title>{draftName}</Title>
        )}
        <Description>
          {collectionSize} {collectionSize === 1 ? 'entry' : 'entries'}
        </Description>
      </TableData>
    </Popover>
  );
}
Example #11
Source File: App.tsx    From pcap2socks-gui with MIT License 4 votes vote down vote up
render() {
    return (
      <Layout className="layout">
        <Content className="content-wrapper">
          <div className="content">
            {(() => {
              switch (this.state.stage) {
                case STAGE_WELCOME:
                  return this.renderWelcome();
                case STAGE_INTERFACE:
                  return this.renderInterface();
                case STAGE_DEVICE:
                  return this.renderDevice();
                case STAGE_PROXY:
                  return this.renderProxy();
                case STAGE_RUNNING:
                  return this.renderRunning();
                default:
                  return;
              }
            })()}
          </div>
          <div className="footer">
            {(() => {
              if (this.state.stage > STAGE_WELCOME && this.state.stage <= STAGE_PROXY) {
                return (
                  <Button
                    className="button"
                    disabled={this.state.loading > 0}
                    icon={<LeftOutlined />}
                    onClick={() => this.setState({ stage: this.state.stage - 1 })}
                  >
                    上一步
                  </Button>
                );
              }
            })()}
            {(() => {
              if (this.state.stage === STAGE_INTERFACE) {
                return (
                  <Button
                    className="button"
                    disabled={this.state.loading > 0 && this.state.loading !== 1}
                    icon={<ReloadOutlined />}
                    onClick={this.updateInterfaces}
                  >
                    刷新网卡列表
                  </Button>
                );
              }
            })()}
            {(() => {
              if (this.state.stage === STAGE_PROXY) {
                return (
                  <Button
                    className="button"
                    disabled={this.state.loading > 0}
                    icon={<FolderOpenOutlined />}
                    onClick={() => {
                      const node = document.getElementById("open");
                      if (node) {
                        node.click();
                      }
                    }}
                  >
                    导入代理配置
                    <input id="open" type="file" onChange={this.import} style={{ display: "none" }} />
                  </Button>
                );
              }
            })()}
            {(() => {
              if (this.state.stage === STAGE_PROXY) {
                return (
                  <Button className="button" icon={<ExportOutlined />} onClick={this.export}>
                    导出代理配置
                  </Button>
                );
              }
            })()}
            {(() => {
              if (this.state.stage === STAGE_PROXY) {
                return (
                  <Button
                    className="button"
                    disabled={this.state.loading > 0 && this.state.loading !== 2}
                    loading={this.state.loading === 2}
                    icon={<ExperimentOutlined />}
                    onClick={this.test}
                  >
                    测试代理服务器
                  </Button>
                );
              }
            })()}
            {(() => {
              if (this.state.stage === STAGE_WELCOME && this.state.ready) {
                return (
                  <Tooltip title={this.state.destination}>
                    <Button
                      className="button"
                      type="primary"
                      disabled={this.state.loading > 0 && this.state.loading !== 3}
                      loading={this.state.loading === 3}
                      icon={<PlayCircleOutlined />}
                      onClick={this.run}
                    >
                      以上次的配置运行
                    </Button>
                  </Tooltip>
                );
              }
            })()}
            {(() => {
              if (this.state.stage >= STAGE_WELCOME && this.state.stage < STAGE_PROXY) {
                return (
                  <Button
                    className="button"
                    disabled={this.state.loading > 0}
                    icon={<RightOutlined />}
                    type="primary"
                    onClick={() => this.setState({ stage: this.state.stage + 1 })}
                  >
                    下一步
                  </Button>
                );
              }
            })()}
            {(() => {
              if (this.state.stage === STAGE_PROXY) {
                return (
                  <Button
                    className="button"
                    type="primary"
                    disabled={this.state.loading > 0 && this.state.loading !== 3}
                    loading={this.state.loading === 3}
                    icon={<PoweroffOutlined />}
                    onClick={this.run}
                  >
                    运行
                  </Button>
                );
              }
            })()}
            {(() => {
              if (this.state.stage === STAGE_RUNNING) {
                return (
                  <Button className="button" icon={<GlobalOutlined />} onClick={this.notifyNetwork}>
                    显示网络设置
                  </Button>
                );
              }
            })()}
            {(() => {
              if (this.state.stage === STAGE_RUNNING) {
                return (
                  <Button
                    className="button"
                    type="primary"
                    danger
                    disabled={this.state.loading > 0 && this.state.loading !== 4}
                    loading={this.state.loading === 4}
                    icon={<PoweroffOutlined />}
                    onClick={this.stopConfirm}
                  >
                    停止
                  </Button>
                );
              }
            })()}
          </div>
        </Content>
      </Layout>
    );
  }