From ddb6a8839266f9758fd190acff0234e8037ec533 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Sun, 5 Jan 2025 00:47:27 +0800 Subject: [PATCH] fix(ui): wrong form initial values --- ui/src/components/access/AccessEditForm.tsx | 5 ++--- .../notification/NotifyChannelEditForm.tsx | 16 +++------------- .../components/workflow/node/ApplyNodeForm.tsx | 7 +++++-- .../components/workflow/node/DeployNodeForm.tsx | 1 + .../components/workflow/node/NotifyNodeForm.tsx | 1 + .../components/workflow/node/StartNodeForm.tsx | 1 + ui/src/domain/workflow.ts | 1 - ui/src/hooks/index.ts | 3 ++- ui/src/hooks/useAntdForm.ts | 7 ++++++- ui/src/hooks/useAntdFormName.ts | 14 ++++++++++++++ ui/src/pages/workflows/WorkflowDetail.tsx | 9 ++------- ui/src/stores/contact/index.ts | 2 +- 12 files changed, 38 insertions(+), 29 deletions(-) create mode 100644 ui/src/hooks/useAntdFormName.ts diff --git a/ui/src/components/access/AccessEditForm.tsx b/ui/src/components/access/AccessEditForm.tsx index 6809da4d..139b6d36 100644 --- a/ui/src/components/access/AccessEditForm.tsx +++ b/ui/src/components/access/AccessEditForm.tsx @@ -1,6 +1,5 @@ import { forwardRef, useEffect, useImperativeHandle, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; -import { useCreation } from "ahooks"; import { Form, type FormInstance, Input } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; @@ -8,7 +7,7 @@ import { z } from "zod"; import AccessProviderSelect from "@/components/provider/AccessProviderSelect"; import { type AccessModel } from "@/domain/access"; import { ACCESS_PROVIDERS } from "@/domain/provider"; -import { useAntdForm } from "@/hooks"; +import { useAntdForm, useAntdFormName } from "@/hooks"; import AccessEditFormACMEHttpReqConfig from "./AccessEditFormACMEHttpReqConfig"; import AccessEditFormAWSConfig from "./AccessEditFormAWSConfig"; @@ -71,7 +70,7 @@ const AccessEditForm = forwardRef(( }, [initialValues?.provider]); const [configFormInst] = Form.useForm(); - const configFormName = useCreation(() => `accessEditForm_config${Math.random().toString(36).substring(2, 10)}${new Date().getTime()}`, []); + const configFormName = useAntdFormName({ form: configFormInst, name: "accessEditConfigForm" }); const configFormComponent = useMemo(() => { /* 注意:如果追加新的子组件,请保持以 ASCII 排序。 diff --git a/ui/src/components/notification/NotifyChannelEditForm.tsx b/ui/src/components/notification/NotifyChannelEditForm.tsx index f4c85d9e..ccb94e65 100644 --- a/ui/src/components/notification/NotifyChannelEditForm.tsx +++ b/ui/src/components/notification/NotifyChannelEditForm.tsx @@ -1,9 +1,8 @@ import { forwardRef, useImperativeHandle, useMemo } from "react"; -import { useCreation } from "ahooks"; import { Form, type FormInstance } from "antd"; import { NOTIFY_CHANNELS, type NotifyChannelsSettingsContent } from "@/domain/settings"; -import { useAntdForm } from "@/hooks"; +import { useAntdForm, useAntdFormName } from "@/hooks"; import NotifyChannelEditFormBarkFields from "./NotifyChannelEditFormBarkFields"; import NotifyChannelEditFormDingTalkFields from "./NotifyChannelEditFormDingTalkFields"; @@ -35,8 +34,8 @@ const NotifyChannelEditForm = forwardRef { const { form: formInst, formProps } = useAntdForm({ initialValues: initialValues, + name: "notifyChannelEditForm", }); - const formName = useCreation(() => `notifyChannelEditForm_${Math.random().toString(36).substring(2, 10)}${new Date().getTime()}`, []); const formFieldsComponent = useMemo(() => { /* 注意:如果追加新的子组件,请保持以 ASCII 排序。 @@ -81,16 +80,7 @@ const NotifyChannelEditForm = forwardRef +
{formFieldsComponent}
); diff --git a/ui/src/components/workflow/node/ApplyNodeForm.tsx b/ui/src/components/workflow/node/ApplyNodeForm.tsx index 11a469bd..6b4523ae 100644 --- a/ui/src/components/workflow/node/ApplyNodeForm.tsx +++ b/ui/src/components/workflow/node/ApplyNodeForm.tsx @@ -52,7 +52,9 @@ const ApplyNodeForm = ({ node }: ApplyNodeFormProps) => { providerAccessId: z .string({ message: t("workflow_node.apply.form.provider_access.placeholder") }) .min(1, t("workflow_node.apply.form.provider_access.placeholder")), - keyAlgorithm: z.string().nullish(), + keyAlgorithm: z + .string({ message: t("workflow_node.apply.form.key_algorithm.placeholder") }) + .nonempty(t("workflow_node.apply.form.key_algorithm.placeholder")), nameservers: z .string() .nullish() @@ -76,6 +78,7 @@ const ApplyNodeForm = ({ node }: ApplyNodeFormProps) => { formPending, formProps, } = useAntdForm>({ + name: "workflowApplyNodeForm", initialValues: (node?.config as WorkflowNodeConfigForApply) ?? initFormModel(), onSubmit: async (values) => { await formInst.validateFields(); @@ -305,7 +308,7 @@ const FormFieldEmailSelect = ({ const handleSearch = (text: string) => { const temp = emailsToOptions(); - if (text) { + if (text?.trim()) { if (temp.every((option) => option.label !== text)) { temp.unshift({ label: text, value: text }); } diff --git a/ui/src/components/workflow/node/DeployNodeForm.tsx b/ui/src/components/workflow/node/DeployNodeForm.tsx index aab6628d..f3a749a8 100644 --- a/ui/src/components/workflow/node/DeployNodeForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeForm.tsx @@ -67,6 +67,7 @@ const DeployNodeForm = ({ node }: DeployFormProps) => { formPending, formProps, } = useAntdForm>({ + name: "workflowDeployNodeForm", initialValues: (node?.config as WorkflowNodeConfigForDeploy) ?? initFormModel(), onSubmit: async (values) => { await formInst.validateFields(); diff --git a/ui/src/components/workflow/node/NotifyNodeForm.tsx b/ui/src/components/workflow/node/NotifyNodeForm.tsx index 1b645a57..d1256079 100644 --- a/ui/src/components/workflow/node/NotifyNodeForm.tsx +++ b/ui/src/components/workflow/node/NotifyNodeForm.tsx @@ -57,6 +57,7 @@ const NotifyNodeForm = ({ node }: NotifyNodeFormProps) => { formPending, formProps, } = useAntdForm>({ + name: "workflowNotifyNodeForm", initialValues: (node?.config as WorkflowNodeConfigForNotify) ?? initFormModel(), onSubmit: async (values) => { await formInst.validateFields(); diff --git a/ui/src/components/workflow/node/StartNodeForm.tsx b/ui/src/components/workflow/node/StartNodeForm.tsx index 92292266..a1dcdd71 100644 --- a/ui/src/components/workflow/node/StartNodeForm.tsx +++ b/ui/src/components/workflow/node/StartNodeForm.tsx @@ -54,6 +54,7 @@ const StartNodeForm = ({ node }: StartNodeFormProps) => { formPending, formProps, } = useAntdForm>({ + name: "workflowStartNodeForm", initialValues: (node?.config as WorkflowNodeConfigForStart) ?? initFormModel(), onSubmit: async (values) => { await formInst.validateFields(); diff --git a/ui/src/domain/workflow.ts b/ui/src/domain/workflow.ts index 379d6c1b..05fc622d 100644 --- a/ui/src/domain/workflow.ts +++ b/ui/src/domain/workflow.ts @@ -193,7 +193,6 @@ export const newNode = (nodeType: WorkflowNodeType, options: NewNodeOptions = {} case WorkflowNodeType.Apply: case WorkflowNodeType.Deploy: { - node.config = {} as Record; node.inputs = workflowNodeTypeDefaultInputs.get(nodeType); node.outputs = workflowNodeTypeDefaultOutputs.get(nodeType); } diff --git a/ui/src/hooks/index.ts b/ui/src/hooks/index.ts index b4024a3c..045c0aad 100644 --- a/ui/src/hooks/index.ts +++ b/ui/src/hooks/index.ts @@ -1,6 +1,7 @@ import useAntdForm from "./useAntdForm"; +import useAntdFormName from "./useAntdFormName"; import useBrowserTheme from "./useBrowserTheme"; import useTriggerElement from "./useTriggerElement"; import useZustandShallowSelector from "./useZustandShallowSelector"; -export { useAntdForm, useBrowserTheme, useTriggerElement, useZustandShallowSelector }; +export { useAntdForm, useAntdFormName, useBrowserTheme, useTriggerElement, useZustandShallowSelector }; diff --git a/ui/src/hooks/useAntdForm.ts b/ui/src/hooks/useAntdForm.ts index 525d1b71..96aa6e45 100644 --- a/ui/src/hooks/useAntdForm.ts +++ b/ui/src/hooks/useAntdForm.ts @@ -2,9 +2,12 @@ import { useDeepCompareEffect } from "ahooks"; import { Form, type FormInstance, type FormProps } from "antd"; +import useAntdFormName from "./useAntdFormName"; + export interface UseAntdFormOptions = any> { form?: FormInstance; initialValues?: Partial | (() => Partial | Promise>); + name?: string; onSubmit?: (values: T) => unknown; } @@ -20,8 +23,9 @@ export interface UseAntdFormReturns = any> { * @param {UseAntdFormOptions} options * @returns {UseAntdFormReturns} */ -const useAntdForm = = any>({ initialValues, form, onSubmit }: UseAntdFormOptions): UseAntdFormReturns => { +const useAntdForm = = any>({ form, initialValues, onSubmit, ...options }: UseAntdFormOptions): UseAntdFormReturns => { const formInst = form ?? Form["useForm"]()[0]; + const formName = useAntdFormName({ form: formInst, name: options.name }); const [formInitialValues, setFormInitialValues] = useState>(); const [formPending, setFormPending] = useState(false); @@ -90,6 +94,7 @@ const useAntdForm = = any>({ initialValues, form const formProps: FormProps = { form: formInst, initialValues: formInitialValues, + name: options.name ? formName : undefined, onFinish, }; diff --git a/ui/src/hooks/useAntdFormName.ts b/ui/src/hooks/useAntdFormName.ts new file mode 100644 index 00000000..9426db2f --- /dev/null +++ b/ui/src/hooks/useAntdFormName.ts @@ -0,0 +1,14 @@ +import { useCreation } from "ahooks"; +import { type FormInstance } from "antd"; + +export interface UseAntdFormNameOptions = any> { + form: FormInstance; + name?: string; +} + +const useAntdFormName = = any>(options: UseAntdFormNameOptions) => { + const formName = useCreation(() => `${options.name}_${Math.random().toString(36).substring(2, 10)}${new Date().getTime()}`, [options.name, options.form]); + return formName; +}; + +export default useAntdFormName; diff --git a/ui/src/pages/workflows/WorkflowDetail.tsx b/ui/src/pages/workflows/WorkflowDetail.tsx index 29a866a3..f0369a50 100644 --- a/ui/src/pages/workflows/WorkflowDetail.tsx +++ b/ui/src/pages/workflows/WorkflowDetail.tsx @@ -43,7 +43,7 @@ const WorkflowDetail = () => { useZustandShallowSelector(["workflow", "initialized", "init", "destroy", "save", "setBaseInfo", "switchEnable"]) ); useEffect(() => { - // TODO: loading + // TODO: loading & error init(workflowId!); return () => { @@ -64,7 +64,7 @@ const WorkflowDetail = () => { setAllowDiscard(!isRunning && hasReleased && hasChanges); setAllowRelease(!isRunning && hasChanges); setAllowRun(hasReleased); - }, [workflow, isRunning]); + }, [workflow.content, workflow.draft, workflow.hasDraft, isRunning]); const handleBaseInfoFormFinish = async (values: Pick) => { try { @@ -141,11 +141,6 @@ const WorkflowDetail = () => { }; const handleRunClick = () => { - if (!workflow.enabled) { - alert("TODO: 暂时只支持执行已启用的工作流"); - return; - } - const { promise, resolve, reject } = Promise.withResolvers(); if (workflow.hasDraft) { modalApi.confirm({ diff --git a/ui/src/stores/contact/index.ts b/ui/src/stores/contact/index.ts index 1ea000b3..a17e18bd 100644 --- a/ui/src/stores/contact/index.ts +++ b/ui/src/stores/contact/index.ts @@ -30,7 +30,7 @@ export const useContactEmailsStore = create((set, get) => { try { set({ loading: true }); settings = await fetcher; - set({ emails: settings.content.emails?.sort() ?? [], loadedAtOnce: true }); + set({ emails: settings.content.emails?.filter((s) => !!s)?.sort() ?? [], loadedAtOnce: true }); } finally { fetcher = null; set({ loading: false });