@ant-design/icons#ToolOutlined TypeScript Examples
The following examples show how to use
@ant-design/icons#ToolOutlined.
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: CurrentPlan.tsx From posthog-foss with MIT License | 5 votes |
export function CurrentPlan({ plan }: { plan: PlanInterface }): JSX.Element {
const { billing } = useValues(billingLogic)
return (
<>
<div className="space-top" />
{billing?.should_setup_billing ? (
<Alert
type="warning"
message={
<>
Your plan is <b>currently inactive</b> as you haven't finished setting up your billing
information.
</>
}
action={
billing.subscription_url && (
<Button href={billing.subscription_url} icon={<ToolOutlined />}>
Finish setup
</Button>
)
}
showIcon
icon={<WarningOutlined />}
/>
) : (
<Card title="Organization billing plan">
<div style={{ display: 'flex', alignItems: 'center' }}>
<div>
<img src={plan.image_url || defaultImg} alt="" height={100} width={100} />
</div>
<div style={{ flexGrow: 1, paddingLeft: 16 }}>
<h3 className="l3" style={{ marginBottom: 8 }}>
{plan.name}
</h3>
<Link target="_blank" to={`https://posthog.com/pricing#plan-${plan.key}?${UTM_TAGS}`}>
More plan details <IconOpenInNew />
</Link>
<div style={{ marginTop: 4 }}>{plan.price_string}</div>
<div className="text-muted mt">
Click on <b>manage subscription</b> to cancel your billing agreement,{' '}
<b>update your card</b> or other billing information,
</div>
</div>
<div>
<Button type="primary" href="/billing/manage" icon={<ToolOutlined />}>
Manage subscription
</Button>
<div className="text-muted text-center">Get past invoices too</div>
</div>
</div>
</Card>
)}
</>
)
}
Example #2
Source File: personalizationOptions.tsx From posthog-foss with MIT License | 5 votes |
ROLES: RadioSelectType[] = [
{
key: 'engineer',
label: 'Engineer',
icon: <CodeOutlined />,
},
{
key: 'product',
label: 'Product Manager',
icon: <RocketOutlined />,
},
{
key: 'management',
label: 'Management',
icon: <ClusterOutlined />,
},
{
key: 'marketing',
label: 'Marketing',
icon: <NotificationOutlined />,
},
{
key: 'sales',
label: 'Sales',
icon: <DollarOutlined />,
},
{
key: 'cx',
label: 'Customer success',
icon: <SmileOutlined />,
},
{
key: 'ops',
label: 'Operations',
icon: <ToolOutlined />,
},
{
key: 'other',
label: 'Other',
icon: <BlockOutlined />,
},
]
Example #3
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 #4
Source File: Dashboard.tsx From yugong with MIT License | 4 votes |
Dashboard: React.FC<Props> = () => {
// 复制模块
const [showCopyedModal, setShowCopyedModal] = useState(false);
// 复制模块名称
const [newModalName, setNewModalName] = useState<string>();
const [showRunningTimes, setShowRunningTimes] = useState(false);
const runningTimes = useSelector((state: RootState) => state.runningTimes);
// appdata
const appData = useSelector((state: RootState) => state.appData);
const pageData = useSelector((state: RootState) => state.pageData);
// 模板ID
const moduleId = useSelector(
(state: RootState) => state.activationItem.moduleId,
);
const activationItem = useSelector(
(state: RootState) => state.activationItem,
);
const updateActivationItem =
useDispatch<Dispatch>().activationItem.updateActivationItem;
const updateAppData = useDispatch<Dispatch>().appData.updateAppData;
const removeActivationItem =
useDispatch<Dispatch>().activationItem.removeActivationItem;
// 样式与设置菜单面板
const [mainTag, setMainTag] = useState('config');
const onSelectMainTag = useCallback((e) => {
setMainTag(e.key);
}, []);
const sendMessage = usePostMessage(() => {});
// 收发处理,子窗口onload时向子窗口发送信息, 通知当前正处于编辑模式下,
// 重置当前被选择项
const onChangeSelect = useCallback(
(e) => {
if (activationItem.moduleId === e) return;
for (let index = 0; index < appData.length; index++) {
const element = appData[index];
if (element.moduleId === e) {
const value = { ...element };
updateActivationItem(value);
const win = (
document.getElementById('wrapiframe') as HTMLIFrameElement
).contentWindow;
if (win) {
sendMessage({ tag: 'id', value: element.moduleId }, win);
}
break;
}
}
},
[activationItem.moduleId, appData, sendMessage, updateActivationItem],
);
// =====================================模块删除=======================================//
const [isDeleteComp, setIsDeleteComp] = useState(false);
const delModule = useCallback(() => {
const optAppData = produce(reject([...appData], { moduleId }), undefined, createDesc('删除',`组件${activationItem.moduleName}`) );
const win = (document.getElementById('wrapiframe') as HTMLIFrameElement)
.contentWindow;
updateAppData(optAppData);
removeActivationItem();
sendMessage(
{
tag: 'updateAppData',
value: optAppData,
},
win,
);
sendMessage(
{
tag: 'removeActivationItem',
value: undefined,
},
win,
);
setIsDeleteComp(false);
}, [activationItem.moduleName, appData, moduleId, removeActivationItem, sendMessage, updateAppData]);
const confirmModal = useCallback(() => {
if (isDeleteComp) return;
setIsDeleteComp(true);
confirm({
content: (
<div>
<h3>确定删除</h3>
<br />
模块名称:{activationItem.moduleName}
<br />
Id: {activationItem.moduleId}
<br />
<span className={s.warn}>
当前模块将被移除,请手动清除其他模块事件中引用的当前模块方法。
</span>
</div>
),
okText: '确定',
cancelText: '取消',
onCancel: () => setIsDeleteComp(false),
onOk: delModule,
});
}, [
isDeleteComp,
activationItem.moduleName,
activationItem.moduleId,
delModule,
]);
// 模块删除快捷键
// key deletd
useKeyDown((event) => {
event.preventDefault();
confirmModal();
}, 'Delete');
// =====================================模块复制=======================================//
// copyData
const beforCopyModule = useCallback(() => {
setNewModalName(`${activationItem.moduleName} 拷贝`);
setShowCopyedModal(true);
}, [activationItem.moduleName]);
// 初始化或,取消复制弹窗
const initCopyModule = useCallback(() => {
setShowCopyedModal(false);
setNewModalName(undefined);
}, []);
// 方法,复制当前选中的组件
const copyModule = useCallback(() => {
// 准备创建
const oprateActivationItem = cloneDeep(activationItem);
const moduleId = nanoid();
oprateActivationItem.moduleId = moduleId;
oprateActivationItem.layout!.i = moduleId;
oprateActivationItem.moduleName =
newModalName || `${activationItem.moduleName} 拷贝`;
// 模块垂直位置
let y = 0;
// 行高
let rowHeight = pageData.rowHeight || GRID_DEFAULT_ROWHEIGHT;
if (typeof rowHeight === 'string') rowHeight = getResult(rowHeight);
// 滚动条高度
const iframeNode = document.getElementById(
'wrapiframe',
) as HTMLIFrameElement | null;
const scrollTop =
iframeNode?.contentDocument?.documentElement.scrollTop || 0;
// 通过滚动条定位计算新增元素应该在当前视窗内
y = (scrollTop + 100) / (rowHeight as number);
oprateActivationItem.layout!.y = y;
// 复制模块,更新当前模块到全局并设为当前被选择模块
updateAppData(produce([...appData, oprateActivationItem], undefined, createDesc('复制',`新组件${oprateActivationItem.moduleName}`)));
updateActivationItem(oprateActivationItem);
// 初始化复制窗口
initCopyModule();
}, [activationItem, appData, newModalName, pageData.rowHeight, updateAppData, updateActivationItem, initCopyModule]);
// 处理键盘事件
// 模拟模块复制
// useKeyDown(
// () => {
// beforCopyModule();
// },
// 'c',
// 'ctrlKey',
// );
// // 确认复制模块
useKeyDown((event) => {
if (showCopyedModal) {
event.preventDefault();
copyModule();
}
}, 'Enter');
const CodeEditor = useMemo(
() => lazy(() => import(`../CodeEditor/index`)),
[],
);
return (
<>
<div className={s.headtab}>
<div className={s.moduleselect}>
<Select
onChange={onChangeSelect}
className={s.select}
value={moduleId}
showSearch
placeholder="请选择编辑模块"
optionFilterProp="children"
filterOption={
(input, option) => {
const str = option?.children?.join('').toLowerCase();
if (str?.indexOf(input) !== -1) {
return true;
}
return false;
}
// option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}
>
{appData.map((item) => (
<Select.Option value={item.moduleId} key={item.moduleId}>
{item.moduleName || '(未标题)'}-{item.type}
</Select.Option>
))}
</Select>
</div>
<Menu
onClick={() => setMainTag('config')}
onSelect={onSelectMainTag}
selectedKeys={[mainTag]}
mode="horizontal"
className={s.contentmenu}
>
<Menu.Item key="config" icon={<ToolOutlined />}>
设置
</Menu.Item>
<Menu.Item key="style" icon={<FormatPainterOutlined />}>
样式
</Menu.Item>
<Menu.Item key="code" icon={<CodeOutlined />}>
code
</Menu.Item>
</Menu>
<div className={s.info}>
<Tooltip placement="bottomRight" title="查看全局发布变量">
<ClusterOutlined
className={s.delete}
onClick={() => setShowRunningTimes(true)}
/>
</Tooltip>
</div>
<div className={s.info}>
<Tooltip
placement="bottomRight"
title={
<div className={s.tips}>
<h3>复制为新模块</h3>
当前模块信息
<br />
模块:{activationItem.moduleName}
<br />
类型:{activationItem.type}
<br />
Id:{activationItem.moduleId}
</div>
}
>
<CopyOutlined alt="复制模块" onClick={beforCopyModule} />
</Tooltip>
</div>
<div>
<Tooltip
placement="bottomRight"
title={`删除 ${
activationItem.moduleName || activationItem.moduleId
}`}
>
<DeleteOutlined className={s.delete} onClick={confirmModal} />
</Tooltip>
</div>
</div>
<div
className={s.root}
style={{ height: `${window.innerHeight - 80}px` }}
>
<div
className={s.controllerwrap}
style={{ display: mainTag === 'style' ? 'block' : 'none' }}
>
<StyleController />
</div>
<div
className={s.controllerwrap}
style={{ display: mainTag === 'config' ? 'block' : 'none' }}
>
<ConfigurationController />
</div>
<div
className={s.controllerwrap}
style={{ display: mainTag === 'code' ? 'block' : 'none' }}
>
<CodeEditor />
</div>
</div>
<Modal
title={`复制${activationItem?.moduleName || ''}(${
activationItem?.type || ''
})模块`}
visible={!!showCopyedModal}
footer={null}
onCancel={initCopyModule}
>
<Row gutter={[16, 16]}>
<Col span={3}></Col>
<Col span={15}>
<Input
type="text"
value={newModalName as any}
onChange={(e) => setNewModalName(e.target.value || undefined)}
placeholder={`请输入${activationItem?.type || ''}模块的别名`}
/>
</Col>
<Col span={6}>
<Button type="primary" onClick={copyModule}>
确定
</Button>
</Col>
</Row>
<br />
</Modal>
<RunningTimesModal
visible={showRunningTimes}
data={runningTimes}
onCancel={() => setShowRunningTimes(false)}
/>
</>
);
}
Example #5
Source File: YakLocalProcess.tsx From yakit with GNU Affero General Public License v3.0 | 4 votes |
YakLocalProcess: React.FC<YakLocalProcessProp> = (props) => {
const [process, setProcess] = useState<yakProcess[]>([]);
const [shouldAutoStart, setShouldAutoStart] = useState(false);
const [installed, setInstalled] = useState(false);
const [psIng, setPsIng] = useState(false);
const [notified, setNotified] = useState(false);
// 检查是不是 windows
const [isWindows, setIsWindows] = useState(false);
const notWindows = !isWindows;
// 检查默认数据库是不是又问题?
const [databaseError, setDatabaseError] = useState("");
let databaseErrorVerbose: React.ReactNode = databaseError;
switch (databaseError) {
case "not allow to write":
databaseErrorVerbose = "数据库无权限写入"
break
case "no such file or directory":
databaseErrorVerbose = <div>
<Tooltip title={"直接启动引擎即可"}>
无本地数据库
</Tooltip>
</div>
}
const update = useMemoizedFn(() => {
let noProcess = true;
ipcRenderer.invoke("is-yak-engine-installed").then(ok => {
setInstalled(ok)
});
if (psIng) {
return
}
setPsIng(true)
ipcRenderer.invoke("ps-yak-grpc").then((i: yakProcess[]) => {
setNotified(false)
setProcess(i.map((element: yakProcess) => {
noProcess = false;
return {
port: element.port,
pid: element.pid,
cmd: element.cmd,
origin: element.origin,
}
}).filter(i => true))
}).catch(e => {
if (!notified) {
failed(`PS | GREP yak failed ${e}`)
setNotified(true)
}
}).finally(() => {
if (noProcess) {
setShouldAutoStart(true)
}
setPsIng(false)
})
ipcRenderer.invoke("is-windows").then((i: boolean) => {
setIsWindows(i)
})
ipcRenderer.invoke("check-local-database").then(e => {
setDatabaseError(e)
})
})
useEffect(() => {
update()
let id = setInterval(update, 1000);
return () => {
clearInterval(id);
}
}, [])
useEffect(() => {
props.onProcess && props.onProcess([...process])
}, [process])
const promptInstallYakEngine = () => {
let m = showModal({
keyboard: false,
title: "引擎安装与升级",
width: "50%",
content: <>
<YakUpgrade onFinished={() => {
m.destroy()
}}/>
</>
})
}
const startYakGRPCServer = (sudo: boolean) => {
ipcRenderer.invoke("start-local-yak-grpc-server", {
sudo,
}).then(() => {
info("启动 yak grpc 进程成功")
}).catch((e: Error) => {
const flag = `${e.message}`;
if (flag.includes(`uninstall yak engine`)) {
failed("未安装 Yak 引擎")
promptInstallYakEngine()
return
}
failed(`${e.message}`)
}).finally(() => {
update()
})
}
const databaseMeetError = notWindows && installed && databaseError !== "";
return <>
<Form.Item label={" "} colon={false}>
<div style={{width: "100%"}}>
<Row>
<Col span={5}/>
<Col span={14}>
<Card
title={<Space>
<div>本地 Yak 进程管理</div>
{!installed && <Tag color={"red"}>引擎未安装</Tag>}
{notWindows && installed && databaseError !== "" &&
<Space size={0}>
<Tag color={"red"}>{databaseErrorVerbose}</Tag>
<Popconfirm
title={"尝试修复数据库写权限(可能要求 ROOT 权限)"}
onConfirm={e => {
ipcRenderer.invoke("fix-local-database").then(e => {
info("修复成功")
}).catch(e => {
failed(`修复数据库权限错误:${e}`)
})
}}
>
<Button type={"link"} size={"small"}
icon={<>
<ToolOutlined/>
</>}/>
</Popconfirm>
</Space>}
</Space>}
size={"small"}
extra={
process.length > 0 && <Space>
<Button size={"small"} onClick={() => {
startYakGRPCServer(false)
}} disabled={databaseMeetError}>普通权限启动</Button>
<Popconfirm title={"以管理员权限启动"} onConfirm={() => {
startYakGRPCServer(true)
}} disabled={databaseMeetError}>
<Button
size={"small"} type={"primary"}
disabled={databaseMeetError}
>管理员(sudo)启动</Button>
</Popconfirm>
</Space>
}
>
{process.length > 0 ? <List
dataSource={process}
renderItem={(i: yakProcess) => {
return <List.Item
key={i.pid}
>
<Card
size={"small"} style={{width: "100%"}} bordered={false} hoverable={true}
>
<Row>
<Col span={12} style={{textAlign: "left"}}>
<Space>
<Tag color={"green"}>PID: {i.pid}</Tag>
<CopyableField
text={`yak grpc --port ${i.port === 0 ? "获取中" : i.port}`}
width={300}
/>
</Space>
</Col>
<Col span={12}>
<div style={{width: "100%", textAlign: "right"}}>
<Space>
<Button
size={"small"} type={"primary"}
disabled={!props.onConnected}
loading={i.port <= 0}
onClick={() => {
props.onConnected && props.onConnected(
i.port, "localhost")
}}
>连接引擎</Button>
<Popconfirm
title={"将会强制关闭该进程"}
onConfirm={() => {
ipcRenderer.invoke("kill-yak-grpc", i.pid).catch((e: any) => {
}).finally(update)
}}
>
<Button
size={"small"} danger={true}
>关闭引擎</Button>
</Popconfirm>
<Button
type={"link"} size={"small"}
onClick={() => {
showModal({
title: "YakProcess 详情",
content: <>
<ReactJson src={i}/>
</>
})
}}
>
details
</Button>
</Space>
</div>
</Col>
</Row>
</Card>
</List.Item>
}}
>
</List> : <Space>
<Button onClick={() => {
startYakGRPCServer(false)
}} disabled={databaseMeetError}>普通权限启动</Button>
<Popconfirm title={"以管理员权限启动,解锁全部 yak 引擎功能"} onConfirm={() => {
startYakGRPCServer(true)
}} disabled={databaseMeetError}>
<Button disabled={databaseMeetError} type={"primary"}>管理员(sudo)启动</Button>
</Popconfirm>
</Space>}
</Card>
</Col>
<Col span={5}/>
</Row>
</div>
</Form.Item>
</>
}