diff --git a/ui/src/components/workflow/WorkflowRunDetail.tsx b/ui/src/components/workflow/WorkflowRunDetail.tsx index 87bbef859..73efbedc2 100644 --- a/ui/src/components/workflow/WorkflowRunDetail.tsx +++ b/ui/src/components/workflow/WorkflowRunDetail.tsx @@ -17,7 +17,7 @@ import { listByWorkflowRunId as listLogsByWorkflowRunId } from "@/repository/wor import { mergeCls } from "@/utils/css"; import { getErrMsg } from "@/utils/error"; -import WorkflowStatusIcon from "./WorkflowStatusIcon"; +import WorkflowStatus from "./WorkflowStatus"; export interface WorkflowRunDetailProps { className?: string; @@ -88,34 +88,6 @@ const WorkflowRunLogs = ({ runId, runStatus }: { runId: string; runStatus: strin const [showTimestamp, setShowTimestamp] = useState(true); const [showWhitespace, setShowWhitespace] = useState(true); - const renderBadge = () => { - let color: string | undefined; - - switch (runStatus) { - case WORKFLOW_RUN_STATUSES.PENDING: - break; - case WORKFLOW_RUN_STATUSES.RUNNING: - color = themeToken.colorInfo; - break; - case WORKFLOW_RUN_STATUSES.SUCCEEDED: - color = themeToken.colorSuccess; - break; - case WORKFLOW_RUN_STATUSES.FAILED: - color = themeToken.colorError; - break; - case WORKFLOW_RUN_STATUSES.CANCELED: - color = themeToken.colorWarning; - break; - } - - return ( - - - {t(`workflow_run.props.status.${runStatus}`)} - - ); - }; - const renderRecord = (record: Log) => { let message = <>{record.message}; if (record.data != null && Object.keys(record.data).length > 0) { @@ -189,7 +161,9 @@ const WorkflowRunLogs = ({ runId, runStatus }: { runId: string; runStatus: strin {t("workflow_run.logs")}
-
{renderBadge()}
+
+ +
{ + const { token: themeToken } = theme.useToken(); + + switch (value) { + case WORKFLOW_RUN_STATUSES.PENDING: + if (defaultColor == null || !defaultColor) { + return themeToken.colorTextSecondary; + } + break; + case WORKFLOW_RUN_STATUSES.RUNNING: + if (defaultColor == null || !defaultColor) { + return themeToken.colorInfo; + } + break; + case WORKFLOW_RUN_STATUSES.SUCCEEDED: + if (defaultColor == null || !defaultColor) { + return themeToken.colorSuccess; + } + break; + case WORKFLOW_RUN_STATUSES.FAILED: + if (defaultColor == null || !defaultColor) { + return themeToken.colorError; + } + break; + case WORKFLOW_RUN_STATUSES.CANCELED: + if (defaultColor == null || !defaultColor) { + return themeToken.colorWarning; + } + break; + default: + if (defaultColor == null || !defaultColor) { + return themeToken.colorTextSecondary; + } + break; + } + + return defaultColor; +}; + +export interface WorkflowStatusIconProps { + className?: string; + style?: React.CSSProperties; + color?: string | false; + size?: number | string; + type?: "filled" | "outlined"; + value: WorkflorRunStatusType | string; +} + +const WorkflowStatusIcon = ({ className, style, size = "1.25em", type = "outlined", value, ...props }: WorkflowStatusIconProps) => { + const color = useColor(value, props.color); + + switch (value) { + case WORKFLOW_RUN_STATUSES.PENDING: + return ( + + {type === "filled" ? : } + + ); + case WORKFLOW_RUN_STATUSES.RUNNING: + return ( + + + + ); + case WORKFLOW_RUN_STATUSES.SUCCEEDED: + return ( + + {type === "filled" ? : } + + ); + case WORKFLOW_RUN_STATUSES.FAILED: + return ( + + {type === "filled" ? : } + + ); + case WORKFLOW_RUN_STATUSES.CANCELED: + return ( + + + + ); + default: + return ( + + + + ); + } +}; + +export interface WorkflowStatusProps { + className?: string; + style?: React.CSSProperties; + children?: React.ReactNode; + color?: string | false; + showIcon?: boolean; + type?: WorkflowStatusIconProps["type"]; + value: WorkflorRunStatusType | string; +} + +const WorkflowStatus = ({ className, style, children, showIcon = true, type, value, ...props }: WorkflowStatusProps) => { + const { t } = useTranslation(); + + const color = useColor(value, props.color); + + const renderIcon = () => (showIcon ? : null); + + switch (value) { + case WORKFLOW_RUN_STATUSES.PENDING: + case WORKFLOW_RUN_STATUSES.RUNNING: + case WORKFLOW_RUN_STATUSES.SUCCEEDED: + case WORKFLOW_RUN_STATUSES.FAILED: + case WORKFLOW_RUN_STATUSES.CANCELED: + return ( + +
+ {renderIcon()} + {children != null ? children : {t(`workflow_run.props.status.${value.toLowerCase()}`)}} +
+
+ ); + default: + return ( + +
{children != null ? children : <>}
+
+ ); + } +}; + +const _default = Object.assign(WorkflowStatus, { + Icon: WorkflowStatusIcon, +}); + +export default _default; diff --git a/ui/src/components/workflow/WorkflowStatusIcon.tsx b/ui/src/components/workflow/WorkflowStatusIcon.tsx deleted file mode 100644 index 04d4d2d38..000000000 --- a/ui/src/components/workflow/WorkflowStatusIcon.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { IconCircleCheck, IconCircleDashed, IconCircleOff, IconCircleX, IconClock, IconLoader3 } from "@tabler/icons-react"; -import { theme } from "antd"; - -import { WORKFLOW_RUN_STATUSES } from "@/domain/workflowRun"; -import { mergeCls } from "@/utils/css"; - -export interface WorkflowStatusIconProps { - className?: string; - style?: React.CSSProperties; - color?: string | true; - size?: number | string; - status: string; -} - -const WorkflowStatusIcon = ({ className, style, color, status, ...props }: WorkflowStatusIconProps) => { - const { size = "1em" } = props; - - const { token: themeToken } = theme.useToken(); - - switch (status) { - case WORKFLOW_RUN_STATUSES.PENDING: - if (color === true) { - color = themeToken.colorTextSecondary; - } - return ( - - - - ); - case WORKFLOW_RUN_STATUSES.RUNNING: - if (color === true) { - color = themeToken.colorInfo; - } - return ( - - - - ); - case WORKFLOW_RUN_STATUSES.SUCCEEDED: - if (color === true) { - color = themeToken.colorSuccess; - } - return ( - - - - ); - case WORKFLOW_RUN_STATUSES.FAILED: - if (color === true) { - color = themeToken.colorError; - } - return ( - - - - ); - case WORKFLOW_RUN_STATUSES.CANCELED: - if (color === true) { - color = themeToken.colorWarning; - } - return ( - - - - ); - default: - if (color === true) { - color = themeToken.colorTextSecondary; - } - return ( - - - - ); - } -}; - -export default WorkflowStatusIcon; diff --git a/ui/src/components/workflow/WorkflowStatusTag.tsx b/ui/src/components/workflow/WorkflowStatusTag.tsx deleted file mode 100644 index 12a645d9b..000000000 --- a/ui/src/components/workflow/WorkflowStatusTag.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { useTranslation } from "react-i18next"; -import { Tag } from "antd"; - -import { WORKFLOW_RUN_STATUSES } from "@/domain/workflowRun"; - -import WorkflowStatusIcon from "./WorkflowStatusIcon"; - -export interface WorkflowStatusTagProps { - className?: string; - style?: React.CSSProperties; - status: string; -} - -const WorkflowStatusTag = ({ className, style, status }: WorkflowStatusTagProps) => { - const { t } = useTranslation(); - - const Icon = ; - - switch (status) { - case WORKFLOW_RUN_STATUSES.PENDING: - return ( - - {t("workflow_run.props.status.pending")} - - ); - case WORKFLOW_RUN_STATUSES.RUNNING: - return ( - - {t("workflow_run.props.status.running")} - - ); - case WORKFLOW_RUN_STATUSES.SUCCEEDED: - return ( - - {t("workflow_run.props.status.succeeded")} - - ); - case WORKFLOW_RUN_STATUSES.FAILED: - return ( - - {t("workflow_run.props.status.failed")} - - ); - case WORKFLOW_RUN_STATUSES.CANCELED: - return ( - - {t("workflow_run.props.status.canceled")} - - ); - default: - return <>; - } -}; - -export default WorkflowStatusTag; diff --git a/ui/src/i18n/locales/en/nls.dashboard.json b/ui/src/i18n/locales/en/nls.dashboard.json index 123ac884d..66345b266 100644 --- a/ui/src/i18n/locales/en/nls.dashboard.json +++ b/ui/src/i18n/locales/en/nls.dashboard.json @@ -7,12 +7,12 @@ "dashboard.statistics.all_workflows": "All workflows", "dashboard.statistics.enabled_workflows": "Active workflows", + "dashboard.shortcut": "Shortcuts", + "dashboard.shortcut.create_workflow": "Create new workflow", + "dashboard.shortcut.change_account": "Change username or password", + "dashboard.shortcut.configure_ca": "Configure certificate authorities", + "dashboard.latest_workflow_runs": "Latest workflow runs", "dashboard.latest_workflow_runs.nodata.description": "It looks like you don't have any runs. Get started by running a workflow.", - "dashboard.latest_workflow_runs.nodata.button": "Go to workflows", - - "dashboard.quick_actions": "Quick actions", - "dashboard.quick_actions.create_workflow": "Create workflow", - "dashboard.quick_actions.change_password": "Change password", - "dashboard.quick_actions.configure_ca": "Configure CA" + "dashboard.latest_workflow_runs.nodata.button": "Go to workflows" } diff --git a/ui/src/i18n/locales/zh/nls.dashboard.json b/ui/src/i18n/locales/zh/nls.dashboard.json index 21a659c77..afe6e30c1 100644 --- a/ui/src/i18n/locales/zh/nls.dashboard.json +++ b/ui/src/i18n/locales/zh/nls.dashboard.json @@ -7,12 +7,12 @@ "dashboard.statistics.all_workflows": "所有工作流", "dashboard.statistics.enabled_workflows": "已启用工作流", + "dashboard.shortcut": "快捷操作", + "dashboard.shortcut.create_workflow": "创建新的工作流", + "dashboard.shortcut.change_account": "修改登录账号密码", + "dashboard.shortcut.configure_ca": "配置证书颁发机构", + "dashboard.latest_workflow_runs": "最近运行的工作流", "dashboard.latest_workflow_runs.nodata.description": "当前未找到任何工作流运行历史。请先运行一个工作流。", - "dashboard.latest_workflow_runs.nodata.button": "前往工作流", - - "dashboard.quick_actions": "快捷操作", - "dashboard.quick_actions.create_workflow": "新建工作流", - "dashboard.quick_actions.change_password": "修改登录密码", - "dashboard.quick_actions.configure_ca": "配置证书颁发机构" + "dashboard.latest_workflow_runs.nodata.button": "前往工作流" } diff --git a/ui/src/pages/dashboard/Dashboard.tsx b/ui/src/pages/dashboard/Dashboard.tsx index adde54a69..426fd48a9 100644 --- a/ui/src/pages/dashboard/Dashboard.tsx +++ b/ui/src/pages/dashboard/Dashboard.tsx @@ -15,14 +15,14 @@ import { IconShieldCheckered, } from "@tabler/icons-react"; import { useRequest } from "ahooks"; -import { App, Button, Card, Col, Divider, Flex, Grid, Row, Skeleton, Table, type TableProps, Typography } from "antd"; +import { App, Button, Card, Col, Row, Skeleton, Table, type TableProps, Typography } from "antd"; import dayjs from "dayjs"; import { ClientResponseError } from "pocketbase"; import { get as getStatistics } from "@/api/statistics"; import Empty from "@/components/Empty"; import WorkflowRunDetailDrawer from "@/components/workflow/WorkflowRunDetailDrawer"; -import WorkflowStatusTag from "@/components/workflow/WorkflowStatusTag"; +import WorkflowStatus from "@/components/workflow/WorkflowStatus"; import { type Statistics } from "@/domain/statistics"; import { type WorkflowRunModel } from "@/domain/workflowRun"; import { useBrowserTheme } from "@/hooks"; @@ -35,8 +35,6 @@ const Dashboard = () => { const { t } = useTranslation(); - const breakpoints = Grid.useBreakpoint(); - return (
@@ -48,26 +46,25 @@ const Dashboard = () => {
- +
+

{t("dashboard.shortcut")}

+
+ + + +
+
- - -
- - - -
-
- - - -
+
+

{t("dashboard.latest_workflow_runs")}

+ +
); @@ -268,7 +265,7 @@ const WorkflowRunHistoryTable = ({ className, style }: { className?: string; sty key: "status", title: t("workflow_run.props.status"), render: (_, record) => { - return ; + return ; }, }, { diff --git a/ui/src/pages/workflows/WorkflowDetailRuns.tsx b/ui/src/pages/workflows/WorkflowDetailRuns.tsx index d8512dc78..b2a2469c6 100644 --- a/ui/src/pages/workflows/WorkflowDetailRuns.tsx +++ b/ui/src/pages/workflows/WorkflowDetailRuns.tsx @@ -11,7 +11,7 @@ import Empty from "@/components/Empty"; import Show from "@/components/Show"; import Tips from "@/components/Tips"; import WorkflowRunDetailDrawer from "@/components/workflow/WorkflowRunDetailDrawer"; -import WorkflowStatusTag from "@/components/workflow/WorkflowStatusTag"; +import WorkflowStatus from "@/components/workflow/WorkflowStatus"; import { WORKFLOW_TRIGGERS } from "@/domain/workflow"; import { WORKFLOW_RUN_STATUSES, type WorkflowRunModel } from "@/domain/workflowRun"; import { useAppSettings, useZustandShallowSelector } from "@/hooks"; @@ -52,7 +52,7 @@ const WorkflowDetailRuns = () => { key: "status", title: t("workflow_run.props.status"), render: (_, record) => { - return ; + return ; }, }, { diff --git a/ui/src/pages/workflows/WorkflowList.tsx b/ui/src/pages/workflows/WorkflowList.tsx index 66f597f97..ec1f0be8d 100644 --- a/ui/src/pages/workflows/WorkflowList.tsx +++ b/ui/src/pages/workflows/WorkflowList.tsx @@ -10,7 +10,7 @@ import { ClientResponseError } from "pocketbase"; import { startRun as startWorkflowRun } from "@/api/workflows"; import Empty from "@/components/Empty"; import Show from "@/components/Show"; -import WorkflowStatusIcon from "@/components/workflow/WorkflowStatusIcon"; +import WorkflowStatus from "@/components/workflow/WorkflowStatus"; import { WORKFLOW_TRIGGERS, type WorkflowModel, cloneNode, initWorkflow, isAllNodesValidated } from "@/domain/workflow"; import { useAppSettings } from "@/hooks"; import { list as listWorkflows, remove as removeWorkflow, save as saveWorkflow } from "@/repository/workflow"; @@ -108,10 +108,9 @@ const WorkflowList = () => { return <>; } else { return ( - - - {lastRunTime ? dayjs(lastRunTime).format("YYYY-MM-DD HH:mm:ss") : ""} - + + {lastRunTime ? dayjs(lastRunTime).format("YYYY-MM-DD HH:mm:ss") : ""} + ); } },