feat(ui): add @ant-design/icons

This commit is contained in:
Fu Diwei 2024-12-26 13:02:22 +08:00
parent 8a816ba44f
commit dae6ad2951
20 changed files with 111 additions and 82 deletions

1
ui/package-lock.json generated
View File

@ -8,6 +8,7 @@
"name": "ui",
"version": "0.0.0",
"dependencies": {
"@ant-design/icons": "^5.5.2",
"@ant-design/pro-components": "^2.8.2",
"@hookform/resolvers": "^3.9.0",
"@radix-ui/react-dialog": "^1.1.2",

View File

@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@ant-design/icons": "^5.5.2",
"@ant-design/pro-components": "^2.8.2",
"@hookform/resolvers": "^3.9.0",
"@radix-ui/react-dialog": "^1.1.2",

View File

@ -3,9 +3,9 @@ import { flushSync } from "react-dom";
import { useTranslation } from "react-i18next";
import { useDeepCompareEffect } from "ahooks";
import { Button, Form, Input, Upload, type FormInstance, type UploadFile, type UploadProps } from "antd";
import { UploadOutlined as UploadOutlinedIcon } from "@ant-design/icons";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { Upload as UploadIcon } from "lucide-react";
import { useAntdForm } from "@/hooks";
import { type KubernetesAccessConfig } from "@/domain/access";
@ -78,7 +78,7 @@ const AccessEditFormKubernetesConfig = ({ form, formName, disabled, initialValue
tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.k8s_kubeconfig.tooltip") }}></span>}
>
<Upload beforeUpload={() => false} fileList={kubeFileList} maxCount={1} onChange={handleKubeFileChange}>
<Button icon={<UploadIcon size={16} />}>{t("access.form.k8s_kubeconfig.upload")}</Button>
<Button icon={<UploadOutlinedIcon />}>{t("access.form.k8s_kubeconfig.upload")}</Button>
</Upload>
</Form.Item>
</Form>

View File

@ -3,9 +3,9 @@ import { flushSync } from "react-dom";
import { useTranslation } from "react-i18next";
import { useDeepCompareEffect } from "ahooks";
import { Button, Form, Input, InputNumber, Upload, type FormInstance, type UploadFile, type UploadProps } from "antd";
import { UploadOutlined as UploadOutlinedIcon } from "@ant-design/icons";
import { createSchemaFieldRule } from "antd-zod";
import { z } from "zod";
import { Upload as UploadIcon } from "lucide-react";
import { useAntdForm } from "@/hooks";
import { type SSHAccessConfig } from "@/domain/access";
@ -136,7 +136,7 @@ const AccessEditFormSSHConfig = ({ form, formName, disabled, initialValues, onVa
</Form.Item>
<Form.Item label={t("access.form.ssh_key.label")} tooltip={<span dangerouslySetInnerHTML={{ __html: t("access.form.ssh_key.tooltip") }}></span>}>
<Upload beforeUpload={() => false} fileList={keyFileList} maxCount={1} onChange={handleKeyFileChange}>
<Button icon={<UploadIcon size={16} />}>{t("access.form.ssh_key.upload")}</Button>
<Button icon={<UploadOutlinedIcon />}>{t("access.form.ssh_key.upload")}</Button>
</Upload>
</Form.Item>
</div>

View File

@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import { Button, Dropdown, Form, Input, message, Space, Tooltip } from "antd";
import { CopyOutlined as CopyOutlinedIcon, DownOutlined as DownOutlinedIcon, LikeOutlined as LikeOutlinedIcon } from "@ant-design/icons";
import { CopyToClipboard } from "react-copy-to-clipboard";
import { ChevronDown as ChevronDownIcon, Clipboard as ClipboardIcon, ThumbsUp as ThumbsUpIcon } from "lucide-react";
import dayjs from "dayjs";
import { type CertificateModel } from "@/domain/certificate";
@ -53,7 +53,7 @@ const CertificateDetail = ({ data, ...props }: CertificateDetailProps) => {
messageApi.success(t("common.text.copied"));
}}
>
<Button type="text" icon={<ClipboardIcon size={14} />}></Button>
<Button size="small" type="text" icon={<CopyOutlinedIcon />}></Button>
</CopyToClipboard>
</Tooltip>
</div>
@ -70,7 +70,7 @@ const CertificateDetail = ({ data, ...props }: CertificateDetailProps) => {
messageApi.success(t("common.text.copied"));
}}
>
<Button type="text" icon={<ClipboardIcon size={14} />}></Button>
<Button size="small" type="text" icon={<CopyOutlinedIcon />}></Button>
</CopyToClipboard>
</Tooltip>
</div>
@ -85,7 +85,7 @@ const CertificateDetail = ({ data, ...props }: CertificateDetailProps) => {
{
key: "PEM",
label: "PEM",
extra: <ThumbsUpIcon size="14" />,
extra: <LikeOutlinedIcon />,
onClick: () => handleDownloadPEMClick(),
},
{
@ -110,7 +110,7 @@ const CertificateDetail = ({ data, ...props }: CertificateDetailProps) => {
<Button type="primary">
<Space>
<span>{t("certificate.action.download")}</span>
<ChevronDownIcon size={14} />
<DownOutlinedIcon />
</Space>
</Button>
</Dropdown>

View File

@ -2,8 +2,13 @@
import { useTranslation } from "react-i18next";
import { useControllableValue } from "ahooks";
import { Button, Input, Space, type InputRef, type InputProps } from "antd";
import {
DownOutlined as DownOutlinedIcon,
MinusOutlined as MinusOutlinedIcon,
PlusOutlined as PlusOutlinedIcon,
UpOutlined as UpOutlinedIcon,
} from "@ant-design/icons";
import { produce } from "immer";
import { ArrowDown as ArrowDownIcon, ArrowUp as ArrowUpIcon, Minus as MinusIcon, Plus as PlusIcon } from "lucide-react";
export type MultipleInputProps = Omit<InputProps, "count" | "defaultValue" | "showCount" | "value" | "onChange" | "onPressEnter" | "onClear"> & {
allowClear?: boolean;
@ -125,7 +130,7 @@ const MultipleInput = ({
</Button>
) : (
<Space className="w-full" direction="vertical" size="small">
{value.map((element, index) => {
{Array.from(value).map((element, index) => {
const allowUp = index > 0;
const allowDown = index < value.length - 1;
const allowRemove = minCount == null || value.length > minCount;
@ -192,6 +197,7 @@ const MultipleInputItem = forwardRef<MultipleInputItemInstance, MultipleInputIte
allowUp,
disabled,
showSortButton,
size,
onChange,
onClickAdd,
onClickDown,
@ -212,21 +218,17 @@ const MultipleInputItem = forwardRef<MultipleInputItemInstance, MultipleInputIte
const upBtn = useMemo(() => {
if (!showSortButton) return null;
return <Button icon={<ArrowUpIcon size={14} />} color="default" disabled={disabled || !allowUp} shape="circle" variant="text" onClick={onClickUp} />;
return <Button icon={<UpOutlinedIcon />} color="default" disabled={disabled || !allowUp} type="text" onClick={onClickUp} />;
}, [allowUp, disabled, showSortButton, onClickUp]);
const downBtn = useMemo(() => {
if (!showSortButton) return null;
return (
<Button icon={<ArrowDownIcon size={14} />} color="default" disabled={disabled || !allowDown} shape="circle" variant="text" onClick={onClickDown} />
);
return <Button icon={<DownOutlinedIcon />} color="default" disabled={disabled || !allowDown} type="text" onClick={onClickDown} />;
}, [allowDown, disabled, showSortButton, onClickDown]);
const removeBtn = useMemo(() => {
return (
<Button icon={<MinusIcon size={14} />} color="default" disabled={disabled || !allowRemove} shape="circle" variant="text" onClick={onClickRemove} />
);
return <Button icon={<MinusOutlinedIcon />} color="default" disabled={disabled || !allowRemove} type="text" onClick={onClickRemove} />;
}, [allowRemove, disabled, onClickRemove]);
const addBtn = useMemo(() => {
return <Button icon={<PlusIcon size={14} />} color="default" disabled={disabled || !allowAdd} shape="circle" variant="text" onClick={onClickAdd} />;
return <Button icon={<PlusOutlinedIcon />} color="default" disabled={disabled || !allowAdd} type="text" onClick={onClickAdd} />;
}, [allowAdd, disabled, onClickAdd]);
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
@ -261,12 +263,12 @@ const MultipleInputItem = forwardRef<MultipleInputItemInstance, MultipleInputIte
onChange={handleChange}
/>
</div>
<div>
<Button.Group size={size}>
{removeBtn}
{upBtn}
{downBtn}
{addBtn}
</div>
</Button.Group>
</div>
);
}

View File

@ -1,6 +1,6 @@
import { useTranslation } from "react-i18next";
import { Divider, Space, Typography } from "antd";
import { BookOpen as BookOpenIcon } from "lucide-react";
import { BookOutlined as BookOutlinedIcon } from "@ant-design/icons";
import { version } from "@/domain/version";
@ -16,7 +16,7 @@ const Version = ({ className, style }: VersionProps) => {
<Space className={className} style={style} size={4}>
<Typography.Link type="secondary" href="https://docs.certimate.me" target="_blank">
<div className="flex items-center justify-center space-x-1">
<BookOpenIcon size={16} />
<BookOutlinedIcon />
<span>{t("common.menu.document")}</span>
</div>
</Typography.Link>

View File

@ -1,4 +1,4 @@
import { WorkflowNodeDropdwonItemIcon, WorkflowNodeDropdwonItemIconType } from "@/domain/workflow";
import { type WorkflowNodeDropdwonItemIcon, WorkflowNodeDropdwonItemIconType } from "@/domain/workflow";
import { CloudUpload, GitFork, Megaphone, NotebookPen } from "lucide-react";
const icons = new Map([

View File

@ -3,8 +3,8 @@ import { useTranslation } from "react-i18next";
import { useControllableValue } from "ahooks";
import { AutoComplete, Button, Divider, Form, Input, InputNumber, Select, Switch, Typography, type AutoCompleteProps } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { PlusOutlined as PlusOutlinedIcon } from "@ant-design/icons";
import z from "zod";
import { Plus as PlusIcon } from "lucide-react";
import AccessEditModal from "@/components/access/AccessEditModal";
import AccessSelect from "@/components/access/AccessSelect";
@ -77,11 +77,21 @@ const ApplyNodeForm = ({ data }: ApplyNodeFormProps) => {
return (
<Form {...formProps} form={formInst} disabled={formPending} layout="vertical">
<Form.Item name="domain" label={t("workflow.nodes.apply.form.domain.label")} rules={[formRule]}>
<Form.Item
name="domain"
label={t("workflow.nodes.apply.form.domain.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow.nodes.apply.form.domain.tooltip") }}></span>}
>
<Input placeholder={t("workflow.nodes.apply.form.domain.placeholder")} />
</Form.Item>
<Form.Item name="email" label={t("workflow.nodes.apply.form.email.label")} rules={[formRule]}>
<Form.Item
name="email"
label={t("workflow.nodes.apply.form.email.label")}
rules={[formRule]}
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow.nodes.apply.form.email.tooltip") }}></span>}
>
<ContactEmailSelect placeholder={t("workflow.nodes.apply.form.email.placeholder")} />
</Form.Item>
@ -94,7 +104,7 @@ const ApplyNodeForm = ({ data }: ApplyNodeFormProps) => {
preset="add"
trigger={
<Button className="p-0" type="link">
<PlusIcon size={14} />
<PlusOutlinedIcon />
{t("workflow.nodes.apply.form.access.button")}
</Button>
}

View File

@ -3,8 +3,8 @@ import { Link } from "react-router";
import { useTranslation } from "react-i18next";
import { Button, Form, Input, Select } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { RightOutlined as RightOutlinedIcon } from "@ant-design/icons";
import { z } from "zod";
import { ChevronRight as ChevronRightIcon } from "lucide-react";
import { usePanel } from "../PanelProvider";
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
@ -75,9 +75,9 @@ const NotifyNodeForm = ({ data }: NotifyNodeFormProps) => {
<div className="flex-grow max-w-full truncate">{t("workflow.nodes.notify.form.channel.label")}</div>
<div className="text-right">
<Link className="ant-typography" to="/settings/notification" target="_blank">
<Button className="p-0" type="link">
<Button size="small" type="link">
{t("workflow.nodes.notify.form.channel.button")}
<ChevronRightIcon size={14} />
<RightOutlinedIcon className="text-xs" />
</Button>
</Link>
</div>

View File

@ -2,7 +2,6 @@ import { cloneElement, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { useControllableValue } from "ahooks";
import { Alert, Drawer } from "antd";
import { CircleCheck as CircleCheckIcon, CircleX as CircleXIcon } from "lucide-react";
import Show from "@/components/Show";
import { type WorkflowRunModel } from "@/domain/workflowRun";
@ -45,11 +44,11 @@ const WorkflowRunDetailDrawer = ({ data, loading, trigger, ...props }: WorkflowR
<Drawer closable destroyOnClose open={open} loading={loading} placement="right" title={data?.id} width={640} onClose={() => setOpen(false)}>
<Show when={!!data}>
<Show when={data!.succeed}>
<Alert showIcon type="success" message={t("workflow_run.props.status.succeeded")} icon={<CircleCheckIcon size={16} />} />
<Alert showIcon type="success" message={t("workflow_run.props.status.succeeded")} />
</Show>
<Show when={!!data!.error}>
<Alert showIcon type="error" message={t("workflow_run.props.status.failed")} description={data!.error} icon={<CircleXIcon size={16} />} />
<Alert showIcon type="error" message={t("workflow_run.props.status.failed")} description={data!.error} />
</Show>
<div className="mt-4 p-4 bg-black text-stone-200 rounded-md">

View File

@ -3,7 +3,11 @@ import { useParams } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { useRequest } from "ahooks";
import { Button, Empty, notification, Space, Table, theme, Tooltip, Typography, type TableProps } from "antd";
import { CircleCheck as CircleCheckIcon, CircleX as CircleXIcon, Eye as EyeIcon } from "lucide-react";
import {
CheckCircleTwoTone as CheckCircleTwoToneIcon,
CloseCircleTwoTone as CloseCircleTwoToneIcon,
SelectOutlined as SelectOutlinedIcon,
} from "@ant-design/icons";
import { ClientResponseError } from "pocketbase";
import WorkflowRunDetailDrawer from "./WorkflowRunDetailDrawer";
@ -45,14 +49,14 @@ const WorkflowRuns = ({ className, style }: WorkflowRunsProps) => {
if (record.succeed) {
return (
<Space>
<CircleCheckIcon color={themeToken.colorSuccess} size={16} />
<CheckCircleTwoToneIcon twoToneColor={themeToken.colorSuccess} />
<Typography.Text type="success">{t("workflow_run.props.status.succeeded")}</Typography.Text>
</Space>
);
} else {
<Tooltip title={record.error}>
<Space>
<CircleXIcon color={themeToken.colorError} size={16} />
<CloseCircleTwoToneIcon twoToneColor={themeToken.colorError} />
<Typography.Text type="danger">{t("workflow_run.props.status.failed")}</Typography.Text>
</Space>
</Tooltip>;
@ -82,7 +86,7 @@ const WorkflowRuns = ({ className, style }: WorkflowRunsProps) => {
width: 120,
render: (_, record) => (
<Button.Group>
<WorkflowRunDetailDrawer data={record} trigger={<Button color="primary" icon={<EyeIcon size={16} />} variant="text" />} />
<WorkflowRunDetailDrawer data={record} trigger={<Button color="primary" icon={<SelectOutlinedIcon />} variant="text" />} />
</Button.Group>
),
},

View File

@ -40,10 +40,12 @@
"workflow.nodes.start.form.trigger_cron.tooltip": "Time zone is based on the server.",
"workflow.nodes.start.form.trigger_cron.extra": "Expected execution time for the last 5 times:",
"workflow.nodes.start.form.trigger_cron_alert.content": "Tips: If you have multiple workflows, it is recommended to set them to run at multiple times of the day instead of always running at specific times.<br><br>Reference links:<br>1. <a href=\"https://letsencrypt.org/docs/rate-limits/\" target=\"_blank\">Lets Encrypt rate limits</a><br>2. <a href=\"https://letsencrypt.org/docs/faq/#why-should-my-let-s-encrypt-acme-client-run-at-a-random-time\" target=\"_blank\">Why should my Lets Encrypt (ACME) client run at a random time?</a>",
"workflow.nodes.apply.form.domain.label": "Domain (wildcard domain is supported)",
"workflow.nodes.apply.form.domain.label": "Domain",
"workflow.nodes.apply.form.domain.placeholder": "Please enter domain",
"workflow.nodes.apply.form.domain.tooltip": "Wildcard domain: *.example.com",
"workflow.nodes.apply.form.email.label": "Contact Email",
"workflow.nodes.apply.form.email.placeholder": "Please enter contact email",
"workflow.nodes.apply.form.email.tooltip": "Contact information required for SSL certificate application. Please pay attention to the <a href=\"https://letsencrypt.org/docs/rate-limits/\" target=\"_blank\">rate limits</a>.",
"workflow.nodes.apply.form.access.label": "DNS Provider Authorization",
"workflow.nodes.apply.form.access.placeholder": "Please select an authorization of DNS provider",
"workflow.nodes.apply.form.access.button": "Create",

View File

@ -40,10 +40,12 @@
"workflow.nodes.start.form.trigger_cron.tooltip": "时区以服务器设置为准。",
"workflow.nodes.start.form.trigger_cron.extra": "预计最近 5 次执行时间:",
"workflow.nodes.start.form.trigger_cron_alert.content": "小贴士:如果你有多个工作流,建议将它们设置为在一天中的多个时间段运行,而非总是在相同的特定时间。<br><br>参考链接:<br>1. <a href=\"https://letsencrypt.org/zh-cn/docs/rate-limits/\" target=\"_blank\">Lets Encrypt 速率限制</a><br>2. <a href=\"https://letsencrypt.org/zh-cn/docs/faq/#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E7%9A%84-let-s-encrypt-acme-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%AF%E5%8A%A8%E6%97%B6%E9%97%B4%E5%BA%94%E5%BD%93%E9%9A%8F%E6%9C%BA\" target=\"_blank\">为什么我的 Lets Encrypt (ACME) 客户端启动时间应当随机?</a>",
"workflow.nodes.apply.form.domain.label": "域名(支持泛域名)",
"workflow.nodes.apply.form.domain.label": "域名",
"workflow.nodes.apply.form.domain.placeholder": "请输入域名",
"workflow.nodes.apply.form.domain.tooltip": "泛域名表示形式为:*.example.com",
"workflow.nodes.apply.form.email.label": "联系邮箱",
"workflow.nodes.apply.form.email.placeholder": "请输入联系邮箱",
"workflow.nodes.apply.form.email.tooltip": "申请签发 SSL 证书时所需的联系方式。请注意<a href=\"https://letsencrypt.org/zh-cn/docs/rate-limits/\" target=\"_blank\">速率限制</a>。",
"workflow.nodes.apply.form.access.label": "DNS 提供商授权",
"workflow.nodes.apply.form.access.placeholder": "请选择 DNS 提供商授权",
"workflow.nodes.apply.form.access.button": "新建",

View File

@ -3,17 +3,17 @@ import { Link, Navigate, Outlet, useLocation, useNavigate } from "react-router-d
import { useTranslation } from "react-i18next";
import { Button, Drawer, Dropdown, Layout, Menu, Tooltip, theme, type ButtonProps, type MenuProps } from "antd";
import {
Languages as LanguagesIcon,
LogOut as LogOutIcon,
Home as HomeIcon,
Menu as MenuIcon,
Moon as MoonIcon,
Server as ServerIcon,
Settings as SettingsIcon,
ShieldCheck as ShieldCheckIcon,
Sun as SunIcon,
Workflow as WorkflowIcon,
} from "lucide-react";
CloudServerOutlined as CloudServerOutlinedIcon,
GlobalOutlined as GlobalOutlinedIcon,
HomeOutlined as HomeOutlinedIcon,
LogoutOutlined as LogoutOutlinedIcon,
MenuOutlined as MenuOutlinedIcon,
MoonOutlined as MoonOutlinedIcon,
NodeIndexOutlined as NodeIndexOutlinedIcon,
SafetyOutlined as SafetyOutlinedIcon,
SettingOutlined as SettingOutlinedIcon,
SunOutlined as SunOutlinedIcon,
} from "@ant-design/icons";
import Version from "@/components/core/Version";
import { useBrowserTheme } from "@/hooks";
@ -67,7 +67,7 @@ const ConsoleLayout = () => {
<Layout.Header className="sticky top-0 left-0 right-0 p-0 z-[19] shadow-sm" style={{ background: themeToken.colorBgContainer }}>
<div className="flex items-center justify-between size-full px-4 overflow-hidden">
<div className="flex items-center gap-4 size-full">
<Button className="md:hidden" icon={<MenuIcon />} size="large" onClick={handleSiderOpen} />
<Button className="md:hidden" icon={<MenuOutlinedIcon />} size="large" onClick={handleSiderOpen} />
<Drawer
closable={false}
destroyOnClose
@ -90,10 +90,10 @@ const ConsoleLayout = () => {
<LocaleToggleButton size="large" />
</Tooltip>
<Tooltip title={t("common.menu.settings")} mouseEnterDelay={2}>
<Button icon={<SettingsIcon size={18} />} size="large" onClick={handleSettingsClick} />
<Button icon={<SettingOutlinedIcon />} size="large" onClick={handleSettingsClick} />
</Tooltip>
<Tooltip title={t("common.menu.logout")} mouseEnterDelay={2}>
<Button danger icon={<LogOutIcon size={18} />} size="large" onClick={handleLogoutClick} />
<Button danger icon={<LogoutOutlinedIcon />} size="large" onClick={handleLogoutClick} />
</Tooltip>
</div>
</div>
@ -118,10 +118,10 @@ const SiderMenu = memo(({ onSelect }: { onSelect?: (key: string) => void }) => {
const MENU_KEY_CERTIFICATES = "/certificates";
const MENU_KEY_ACCESSES = "/accesses";
const menuItems: Required<MenuProps>["items"] = [
[MENU_KEY_HOME, <HomeIcon size={16} />, t("dashboard.page.title")],
[MENU_KEY_WORKFLOWS, <WorkflowIcon size={16} />, t("workflow.page.title")],
[MENU_KEY_CERTIFICATES, <ShieldCheckIcon size={16} />, t("certificate.page.title")],
[MENU_KEY_ACCESSES, <ServerIcon size={16} />, t("access.page.title")],
[MENU_KEY_HOME, <HomeOutlinedIcon />, t("dashboard.page.title")],
[MENU_KEY_WORKFLOWS, <NodeIndexOutlinedIcon />, t("workflow.page.title")],
[MENU_KEY_CERTIFICATES, <SafetyOutlinedIcon />, t("certificate.page.title")],
[MENU_KEY_ACCESSES, <CloudServerOutlinedIcon />, t("access.page.title")],
].map(([key, icon, label]) => {
return {
key: key as string,
@ -201,7 +201,7 @@ const ThemeToggleButton = memo(({ size }: { size?: ButtonProps["size"] }) => {
return (
<Dropdown menu={{ items }} trigger={["click"]}>
<Button icon={theme === "dark" ? <MoonIcon size={18} /> : <SunIcon size={18} />} size={size} />
<Button icon={theme === "dark" ? <MoonOutlinedIcon /> : <SunOutlinedIcon />} size={size} />
</Dropdown>
);
});
@ -219,7 +219,7 @@ const LocaleToggleButton = memo(({ size }: { size?: ButtonProps["size"] }) => {
return (
<Dropdown menu={{ items }} trigger={["click"]}>
<Button icon={<LanguagesIcon size={18} />} size={size} />
<Button icon={<GlobalOutlinedIcon />} size={size} />
</Dropdown>
);
});

View File

@ -3,7 +3,12 @@ import { useTranslation } from "react-i18next";
import { useRequest } from "ahooks";
import { Avatar, Button, Empty, Modal, notification, Space, Table, Tooltip, Typography, type TableProps } from "antd";
import { PageHeader } from "@ant-design/pro-components";
import { Copy as CopyIcon, Pencil as PencilIcon, Plus as PlusIcon, Trash2 as Trash2Icon } from "lucide-react";
import {
DeleteOutlined as DeleteOutlinedIcon,
EditOutlined as EditOutlinedIcon,
PlusOutlined as PlusOutlinedIcon,
SnippetsOutlined as SnippetsOutlinedIcon,
} from "@ant-design/icons";
import dayjs from "dayjs";
import { ClientResponseError } from "pocketbase";
@ -75,7 +80,7 @@ const AccessList = () => {
preset="edit"
trigger={
<Tooltip title={t("access.action.edit")}>
<Button color="primary" icon={<PencilIcon size={16} />} variant="text" />
<Button color="primary" icon={<EditOutlinedIcon />} variant="text" />
</Tooltip>
}
/>
@ -85,7 +90,7 @@ const AccessList = () => {
preset="add"
trigger={
<Tooltip title={t("access.action.copy")}>
<Button color="primary" icon={<CopyIcon size={16} />} variant="text" />
<Button color="primary" icon={<SnippetsOutlinedIcon />} variant="text" />
</Tooltip>
}
/>
@ -93,7 +98,7 @@ const AccessList = () => {
<Tooltip title={t("access.action.delete")}>
<Button
color="danger"
icon={<Trash2Icon size={16} />}
icon={<DeleteOutlinedIcon />}
variant="text"
onClick={() => {
handleDeleteClick(record);
@ -168,7 +173,7 @@ const AccessList = () => {
key="create"
preset="add"
trigger={
<Button type="primary" icon={<PlusIcon size={16} />}>
<Button type="primary" icon={<PlusOutlinedIcon />}>
{t("access.action.add")}
</Button>
}

View File

@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next";
import { useRequest } from "ahooks";
import { Button, Divider, Empty, Menu, notification, Radio, Space, Table, theme, Tooltip, Typography, type MenuProps, type TableProps } from "antd";
import { PageHeader } from "@ant-design/pro-components";
import { Eye as EyeIcon, Filter as FilterIcon, Trash2 as Trash2Icon } from "lucide-react";
import { DeleteOutlined as DeleteOutlinedIcon, SelectOutlined as SelectOutlinedIcon } from "@ant-design/icons";
import dayjs from "dayjs";
import { ClientResponseError } from "pocketbase";
@ -88,7 +88,6 @@ const CertificateList = () => {
</div>
);
},
filterIcon: () => <FilterIcon size={14} />,
render: (_, record) => {
const total = dayjs(record.expireAt).diff(dayjs(record.created), "d") + 1;
const left = dayjs(record.expireAt).diff(dayjs(), "d");
@ -158,7 +157,7 @@ const CertificateList = () => {
data={record}
trigger={
<Tooltip title={t("certificate.action.view")}>
<Button color="primary" icon={<EyeIcon size={16} />} variant="text" />
<Button color="primary" icon={<SelectOutlinedIcon />} variant="text" />
</Tooltip>
}
/>
@ -166,7 +165,7 @@ const CertificateList = () => {
<Tooltip title={t("certificate.action.delete")}>
<Button
color="danger"
icon={<Trash2Icon size={16} />}
icon={<DeleteOutlinedIcon />}
variant="text"
onClick={() => {
alert("TODO");

View File

@ -3,7 +3,12 @@ import { Outlet, useLocation, useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { Card, Space } from "antd";
import { PageHeader } from "@ant-design/pro-components";
import { KeyRound as KeyRoundIcon, Megaphone as MegaphoneIcon, ShieldCheck as ShieldCheckIcon, UserRound as UserRoundIcon } from "lucide-react";
import {
ApiOutlined as ApiOutlinedIcon,
LockOutlined as LockOutlinedIcon,
SendOutlined as SendOutlinedIcon,
UserOutlined as UserOutlinedIcon,
} from "@ant-design/icons";
const Settings = () => {
const location = useLocation();
@ -32,7 +37,7 @@ const Settings = () => {
key: "account",
label: (
<Space>
<UserRoundIcon size={14} />
<UserOutlinedIcon />
<label>{t("settings.account.tab")}</label>
</Space>
),
@ -41,7 +46,7 @@ const Settings = () => {
key: "password",
label: (
<Space>
<KeyRoundIcon size={14} />
<LockOutlinedIcon />
<label>{t("settings.password.tab")}</label>
</Space>
),
@ -50,7 +55,7 @@ const Settings = () => {
key: "notification",
label: (
<Space>
<MegaphoneIcon size={14} />
<SendOutlinedIcon />
<label>{t("settings.notification.tab")}</label>
</Space>
),
@ -59,7 +64,7 @@ const Settings = () => {
key: "ssl-provider",
label: (
<Space>
<ShieldCheckIcon size={14} />
<ApiOutlinedIcon />
<label>{t("settings.sslprovider.tab")}</label>
</Space>
),

View File

@ -4,8 +4,8 @@ import { useTranslation } from "react-i18next";
import { Button, Card, Dropdown, Form, Input, message, Modal, notification, Tabs, Typography } from "antd";
import { createSchemaFieldRule } from "antd-zod";
import { PageHeader } from "@ant-design/pro-components";
import { DeleteOutlined as DeleteOutlinedIcon, EllipsisOutlined as EllipsisOutlinedIcon } from "@ant-design/icons";
import { z } from "zod";
import { Ellipsis as EllipsisIcon, Trash2 as Trash2Icon } from "lucide-react";
import Show from "@/components/Show";
import End from "@/components/workflow/End";
@ -136,7 +136,7 @@ const WorkflowDetail = () => {
key: "delete",
label: t("common.button.delete"),
danger: true,
icon: <Trash2Icon size={14} />,
icon: <DeleteOutlinedIcon />,
onClick: () => {
handleDeleteClick();
},
@ -145,7 +145,7 @@ const WorkflowDetail = () => {
}}
trigger={["click"]}
>
<Button icon={<EllipsisIcon size={14} />} />
<Button icon={<EllipsisOutlinedIcon />} />
</Dropdown>
</Button.Group>,
]}

View File

@ -21,7 +21,7 @@ import {
type TableProps,
} from "antd";
import { PageHeader } from "@ant-design/pro-components";
import { Filter as FilterIcon, Pencil as PencilIcon, Plus as PlusIcon, Trash2 as Trash2Icon } from "lucide-react";
import { DeleteOutlined as DeleteOutlinedIcon, EditOutlined as EditOutlinedIcon, PlusOutlined as PlusOutlinedIcon } from "@ant-design/icons";
import dayjs from "dayjs";
import { ClientResponseError } from "pocketbase";
@ -133,7 +133,6 @@ const WorkflowList = () => {
</div>
);
},
filterIcon: () => <FilterIcon size={14} />,
render: (_, record) => {
const enabled = record.enabled;
return (
@ -180,7 +179,7 @@ const WorkflowList = () => {
<Tooltip title={t("workflow.action.edit")}>
<Button
color="primary"
icon={<PencilIcon size={16} />}
icon={<EditOutlinedIcon />}
variant="text"
onClick={() => {
navigate(`/workflows/${record.id}`);
@ -192,7 +191,7 @@ const WorkflowList = () => {
<Button
color="danger"
danger={true}
icon={<Trash2Icon size={16} />}
icon={<DeleteOutlinedIcon />}
variant="text"
onClick={() => {
handleDeleteClick(record);
@ -301,7 +300,7 @@ const WorkflowList = () => {
<Button
key="create"
type="primary"
icon={<PlusIcon size={16} />}
icon={<PlusOutlinedIcon />}
onClick={() => {
handleCreateClick();
}}