From 0c42bb845dbff3bc654834f541870ea035b99940 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Tue, 13 May 2025 00:28:58 +0800 Subject: [PATCH] feat(ui): AccessProviderPicker --- ui/src/components/DrawerForm.tsx | 2 +- ui/src/components/ModalForm.tsx | 2 +- ui/src/components/access/AccessEditDrawer.tsx | 2 +- ui/src/components/access/AccessEditModal.tsx | 2 +- ui/src/components/access/AccessForm.tsx | 80 +++++++----- .../access/AccessFormWebhookConfig.tsx | 4 +- .../certificate/CertificateDetailDrawer.tsx | 2 +- .../provider/ACMEDns01ProviderPicker.tsx | 29 +++-- .../provider/AccessProviderPicker.tsx | 117 ++++++++++++++++++ .../provider/AccessProviderSelect.tsx | 10 +- .../provider/DeploymentProviderPicker.tsx | 14 ++- .../workflow/WorkflowRunDetailDrawer.tsx | 2 +- .../workflow/node/ApplyNodeConfigForm.tsx | 10 +- .../workflow/node/DeployNodeConfigForm.tsx | 15 +-- ...loyNodeConfigFormAliyunCASDeployConfig.tsx | 4 +- ...ployNodeConfigFormBaotaPanelSiteConfig.tsx | 2 +- .../node/DeployNodeConfigFormLocalConfig.tsx | 10 +- .../node/DeployNodeConfigFormSSHConfig.tsx | 4 +- ...eConfigFormTencentCloudSSLDeployConfig.tsx | 2 +- .../workflow/node/NotifyNodeConfigForm.tsx | 4 +- .../components/workflow/node/_SharedNode.tsx | 2 +- ui/src/i18n/locales/en/nls.access.json | 1 + .../i18n/locales/en/nls.workflow.nodes.json | 4 +- ui/src/i18n/locales/zh/nls.access.json | 1 + .../i18n/locales/zh/nls.workflow.nodes.json | 4 +- ui/src/pages/ConsoleLayout.tsx | 2 +- ui/src/pages/workflows/WorkflowDetail.tsx | 2 +- ui/src/pages/workflows/WorkflowNew.tsx | 2 +- 28 files changed, 246 insertions(+), 89 deletions(-) create mode 100644 ui/src/components/provider/AccessProviderPicker.tsx diff --git a/ui/src/components/DrawerForm.tsx b/ui/src/components/DrawerForm.tsx index 46116095..7e530e64 100644 --- a/ui/src/components/DrawerForm.tsx +++ b/ui/src/components/DrawerForm.tsx @@ -66,7 +66,7 @@ const DrawerForm = = any>({ }); const mergedFormProps: FormProps = { - clearOnDestroy: drawerProps?.destroyOnClose ? true : undefined, + clearOnDestroy: drawerProps?.destroyOnHidden ? true : undefined, ...formProps, ...props, }; diff --git a/ui/src/components/ModalForm.tsx b/ui/src/components/ModalForm.tsx index 1bf84c79..8065d2f1 100644 --- a/ui/src/components/ModalForm.tsx +++ b/ui/src/components/ModalForm.tsx @@ -75,7 +75,7 @@ const ModalForm = = any>({ }); const mergedFormProps: FormProps = { - clearOnDestroy: modalProps?.destroyOnClose ? true : undefined, + clearOnDestroy: modalProps?.destroyOnHidden ? true : undefined, ...formProps, ...props, }; diff --git a/ui/src/components/access/AccessEditDrawer.tsx b/ui/src/components/access/AccessEditDrawer.tsx index 7fa2f5d8..d4a7a4b5 100644 --- a/ui/src/components/access/AccessEditDrawer.tsx +++ b/ui/src/components/access/AccessEditDrawer.tsx @@ -93,7 +93,7 @@ const AccessEditDrawer = ({ data, loading, trigger, scene, usage, afterSubmit, . diff --git a/ui/src/components/access/AccessEditModal.tsx b/ui/src/components/access/AccessEditModal.tsx index 9cfb5b0f..79edb113 100644 --- a/ui/src/components/access/AccessEditModal.tsx +++ b/ui/src/components/access/AccessEditModal.tsx @@ -95,7 +95,7 @@ const AccessEditModal = ({ data, loading, trigger, scene, usage, afterSubmit, .. cancelButtonProps={{ disabled: formPending }} closable confirmLoading={formPending} - destroyOnClose + destroyOnHidden loading={loading} okText={scene === "edit" ? t("common.button.save") : t("common.button.submit")} open={open} diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index 5f82ad67..02a71854 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -1,12 +1,14 @@ -import { forwardRef, useImperativeHandle, useMemo } from "react"; +import { forwardRef, useImperativeHandle, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; import { Form, type FormInstance, Input } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; +import AccessProviderPicker from "@/components/provider/AccessProviderPicker"; import AccessProviderSelect from "@/components/provider/AccessProviderSelect"; +import Show from "@/components/Show"; import { type AccessModel } from "@/domain/access"; -import { ACCESS_PROVIDERS, ACCESS_USAGES } from "@/domain/provider"; +import { ACCESS_PROVIDERS, ACCESS_USAGES, type AccessProvider } from "@/domain/provider"; import { useAntdForm, useAntdFormName } from "@/hooks"; import AccessForm1PanelConfig from "./AccessForm1PanelConfig"; @@ -107,9 +109,22 @@ const AccessForm = forwardRef(({ className, }); const formRule = createSchemaFieldRule(formSchema); const { form: formInst, formProps } = useAntdForm({ + name: "accessForm", initialValues: initialValues, }); + const providerFilter = useMemo(() => { + switch (usage) { + case "both-dns-hosting": + return (record: AccessProvider) => record.usages.includes(ACCESS_USAGES.DNS) || record.usages.includes(ACCESS_USAGES.HOSTING); + case "ca-only": + return (record: AccessProvider) => record.usages.includes(ACCESS_USAGES.CA); + case "notification-only": + return (record: AccessProvider) => record.usages.includes(ACCESS_USAGES.NOTIFICATION); + } + + return undefined; + }, [usage]); const providerLabel = useMemo(() => { switch (usage) { case "ca-only": @@ -139,10 +154,11 @@ const AccessForm = forwardRef(({ className, return undefined; }, [usage]); - const fieldProvider = Form.useWatch("provider", formInst); + const fieldProvider = Form.useWatch["provider"]>("provider", formInst); + const [fieldProviderPicked, setFieldProviderPicked] = useState(initialValues?.provider); // bugfix: Form.useWatch 在条件渲染下不生效,这里用单独的变量存放 Picker 组件选择的值 const [nestedFormInst] = Form.useForm(); - const nestedFormName = useAntdFormName({ form: nestedFormInst, name: "accessEditFormConfigForm" }); + const nestedFormName = useAntdFormName({ form: nestedFormInst, name: "accessConfigForm" }); const nestedFormEl = useMemo(() => { const nestedFormProps = { form: nestedFormInst, @@ -272,7 +288,13 @@ const AccessForm = forwardRef(({ className, case ACCESS_PROVIDERS.ZEROSSL: return ; } - }, [disabled, initialValues?.config, fieldProvider, nestedFormInst, nestedFormName]); + }, [usage, disabled, initialValues?.config, fieldProvider, nestedFormInst, nestedFormName]); + + const handleProviderPick = (value: string) => { + setFieldProviderPicked(value); + formInst.setFieldValue("provider", value); + onValuesChange?.(formInst.getFieldsValue(true)); + }; const handleFormProviderChange = (name: string) => { if (name === nestedFormName) { @@ -312,30 +334,32 @@ const AccessForm = forwardRef(({ className,
- - - + + } + > + + + - - { - if (usage == null) return true; - - switch (usage) { - case "both-dns-hosting": - return record.usages.includes(ACCESS_USAGES.DNS) || record.usages.includes(ACCESS_USAGES.HOSTING); - case "ca-only": - return record.usages.includes(ACCESS_USAGES.CA); - case "notification-only": - return record.usages.includes(ACCESS_USAGES.NOTIFICATION); - } - }} - disabled={scene !== "add"} - placeholder={providerPlaceholder} - showOptionTags={usage == null || (usage === "both-dns-hosting" ? { [ACCESS_USAGES.DNS]: true, [ACCESS_USAGES.HOSTING]: true } : false)} - showSearch={!disabled} - /> - + + + +
{nestedFormEl} diff --git a/ui/src/components/access/AccessFormWebhookConfig.tsx b/ui/src/components/access/AccessFormWebhookConfig.tsx index 4bbc6754..0108d7b3 100644 --- a/ui/src/components/access/AccessFormWebhookConfig.tsx +++ b/ui/src/components/access/AccessFormWebhookConfig.tsx @@ -283,7 +283,7 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa - +