@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 |
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 & edit all actions <ExportOutlined />
</a>
</div>
</>
)}
</div>
</div>
)
}
Example #2
Source File: Persons.tsx From posthog-foss with MIT License | 5 votes |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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>
);
}