From 4ab6b72e6f3182b950d6c15fcf029a6f653c597c Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Sun, 30 Mar 2025 20:25:29 +0800 Subject: [PATCH] feat(ui): different provider range of accesses in AccessForm --- internal/applicant/applicant.go | 12 +-- ui/src/components/access/AccessEditModal.tsx | 15 ++-- ui/src/components/access/AccessForm.tsx | 73 ++++++++++++++++--- .../workflow/node/ApplyNodeConfigForm.tsx | 7 +- .../workflow/node/DeployNodeConfigForm.tsx | 3 +- ui/src/i18n/locales/en/nls.access.json | 6 +- ui/src/i18n/locales/zh/nls.access.json | 4 + ui/src/pages/accesses/AccessList.tsx | 6 +- 8 files changed, 94 insertions(+), 32 deletions(-) diff --git a/internal/applicant/applicant.go b/internal/applicant/applicant.go index caca4bb0..52e43991 100644 --- a/internal/applicant/applicant.go +++ b/internal/applicant/applicant.go @@ -50,8 +50,8 @@ type applicantOptions struct { DnsPropagationTimeout int32 DnsTTL int32 DisableFollowCNAME bool - ReplacedARIAcctId string - ReplacedARICertId string + ReplacedARIAcct string + ReplacedARICert string } func NewWithApplyNode(node *domain.WorkflowNode) (Applicant, error) { @@ -124,8 +124,8 @@ func NewWithApplyNode(node *domain.WorkflowNode) (Applicant, error) { lastCertX509, _ := certcrypto.ParsePEMCertificate([]byte(lastCertificate.Certificate)) if lastCertX509 != nil { replacedARICertId, _ := certificate.MakeARICertID(lastCertX509) - options.ReplacedARIAcctId = lastCertificate.ACMEAccountUrl - options.ReplacedARICertId = replacedARICertId + options.ReplacedARIAcct = lastCertificate.ACMEAccountUrl + options.ReplacedARICert = replacedARICertId } } } @@ -184,8 +184,8 @@ func apply(challengeProvider challenge.Provider, options *applicantOptions) (*Ap Domains: options.Domains, Bundle: true, } - if options.ReplacedARICertId != "" && options.ReplacedARIAcctId == user.Registration.URI { - certRequest.ReplacesCertID = options.ReplacedARICertId + if options.ReplacedARIAcct == user.Registration.URI { + certRequest.ReplacesCertID = options.ReplacedARICert } certResource, err := client.Certificate.Obtain(certRequest) if err != nil { diff --git a/ui/src/components/access/AccessEditModal.tsx b/ui/src/components/access/AccessEditModal.tsx index 66154866..0d181877 100644 --- a/ui/src/components/access/AccessEditModal.tsx +++ b/ui/src/components/access/AccessEditModal.tsx @@ -14,13 +14,14 @@ export type AccessEditModalProps = { data?: AccessFormProps["initialValues"]; loading?: boolean; open?: boolean; - preset: AccessFormProps["preset"]; + range?: AccessFormProps["range"]; + scene: AccessFormProps["scene"]; trigger?: React.ReactNode; onOpenChange?: (open: boolean) => void; afterSubmit?: (record: AccessModel) => void; }; -const AccessEditModal = ({ data, loading, trigger, preset, afterSubmit, ...props }: AccessEditModalProps) => { +const AccessEditModal = ({ data, loading, trigger, scene, range, afterSubmit, ...props }: AccessEditModalProps) => { const { t } = useTranslation(); const [notificationApi, NotificationContextHolder] = notification.useNotification(); @@ -50,13 +51,13 @@ const AccessEditModal = ({ data, loading, trigger, preset, afterSubmit, ...props try { let values: AccessModel = formRef.current!.getFieldsValue(); - if (preset === "add") { + if (scene === "add") { if (data?.id) { throw "Invalid props: `data`"; } values = await createAccess(values); - } else if (preset === "edit") { + } else if (scene === "edit") { if (!data?.id) { throw "Invalid props: `data`"; } @@ -96,15 +97,15 @@ const AccessEditModal = ({ data, loading, trigger, preset, afterSubmit, ...props confirmLoading={formPending} destroyOnClose loading={loading} - okText={preset === "edit" ? t("common.button.save") : t("common.button.submit")} + okText={scene === "edit" ? t("common.button.save") : t("common.button.submit")} open={open} - title={t(`access.action.${preset}`)} + title={t(`access.action.${scene}`)} width={480} onOk={handleOkClick} onCancel={handleCancelClick} >
- +
diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index 7b1a8101..12fd8fc9 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -6,7 +6,7 @@ import { z } from "zod"; import AccessProviderSelect from "@/components/provider/AccessProviderSelect"; import { type AccessModel } from "@/domain/access"; -import { ACCESS_PROVIDERS } from "@/domain/provider"; +import { ACCESS_PROVIDERS, ACCESS_USAGES } from "@/domain/provider"; import { useAntdForm, useAntdFormName } from "@/hooks"; import AccessForm1PanelConfig from "./AccessForm1PanelConfig"; @@ -55,14 +55,16 @@ import AccessFormWestcnConfig from "./AccessFormWestcnConfig"; import AccessFormZeroSSLConfig from "./AccessFormZeroSSLConfig"; type AccessFormFieldValues = Partial>; -type AccessFormPresets = "add" | "edit"; +type AccessFormRanges = "both-dns-hosting" | "ca-only" | "notify-only"; +type AccessFormScenes = "add" | "edit"; export type AccessFormProps = { className?: string; style?: React.CSSProperties; disabled?: boolean; initialValues?: AccessFormFieldValues; - preset: AccessFormPresets; + range?: AccessFormRanges; + scene: AccessFormScenes; onValuesChange?: (values: AccessFormFieldValues) => void; }; @@ -72,7 +74,7 @@ export type AccessFormInstance = { validateFields: FormInstance["validateFields"]; }; -const AccessForm = forwardRef(({ className, style, disabled, initialValues, preset, onValuesChange }, ref) => { +const AccessForm = forwardRef(({ className, style, disabled, initialValues, range, scene, onValuesChange }, ref) => { const { t } = useTranslation(); const formSchema = z.object({ @@ -81,7 +83,14 @@ const AccessForm = forwardRef(({ className, .min(1, t("access.form.name.placeholder")) .max(64, t("common.errmsg.string_max", { max: 64 })) .trim(), - provider: z.nativeEnum(ACCESS_PROVIDERS, { message: t("access.form.provider.placeholder") }), + provider: z.nativeEnum(ACCESS_PROVIDERS, { + message: + range === "ca-only" + ? t("access.form.certificate_authority.placeholder") + : range === "notify-only" + ? t("access.form.notification_channel.placeholder") + : t("access.form.provider.placeholder"), + }), config: z.any(), }); const formRule = createSchemaFieldRule(formSchema); @@ -89,6 +98,35 @@ const AccessForm = forwardRef(({ className, initialValues: initialValues, }); + const providerLabel = useMemo(() => { + switch (range) { + case "ca-only": + return t("access.form.certificate_authority.label"); + case "notify-only": + return t("access.form.notification_channel.label"); + } + + return t("access.form.provider.label"); + }, [range]); + const providerPlaceholder = useMemo(() => { + switch (range) { + case "ca-only": + return t("access.form.certificate_authority.placeholder"); + case "notify-only": + return t("access.form.notification_channel.placeholder"); + } + + return t("access.form.provider.placeholder"); + }, [range]); + const providerTooltip = useMemo(() => { + switch (range) { + case "both-dns-hosting": + return ; + } + + return undefined; + }, [range]); + const fieldProvider = Form.useWatch("provider", formInst); const [nestedFormInst] = Form.useForm(); @@ -238,13 +276,24 @@ const AccessForm = forwardRef(({ className, - } - > - + + { + if (range == null) return true; + + switch (range) { + 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 "notify-only": + return record.usages.includes(ACCESS_USAGES.NOTIFICATION); + } + }} + disabled={scene !== "add"} + placeholder={providerPlaceholder} + showSearch={!disabled} + /> diff --git a/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx b/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx index 5bb4fb0c..40ad5e68 100644 --- a/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/ApplyNodeConfigForm.tsx @@ -352,7 +352,8 @@ const ApplyNodeConfigForm = forwardRef
{t("workflow_node.apply.form.provider_access.button")} @@ -424,7 +425,9 @@ const ApplyNodeConfigForm = forwardRef
{t("workflow_node.apply.form.ca_provider_access.button")} diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 9b905f87..3fa34133 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -399,7 +399,8 @@ const DeployNodeConfigForm = forwardRef {t("workflow_node.deploy.form.provider_access.button")} diff --git a/ui/src/i18n/locales/en/nls.access.json b/ui/src/i18n/locales/en/nls.access.json index 5cb4e7b0..409203d8 100644 --- a/ui/src/i18n/locales/en/nls.access.json +++ b/ui/src/i18n/locales/en/nls.access.json @@ -15,7 +15,7 @@ "access.props.provider": "Provider", "access.props.provider.usage.dns": "DNS provider", "access.props.provider.usage.hosting": "Hosting provider", - "access.props.provider.usage.ca": "CA", + "access.props.provider.usage.ca": "Certificate authority", "access.props.provider.usage.notification": "Notification channel", "access.props.ca": "Certificate authority", "access.props.channel": "Notification channel", @@ -27,6 +27,10 @@ "access.form.provider.label": "Provider", "access.form.provider.placeholder": "Please select a provider", "access.form.provider.tooltip": "DNS provider: The provider that hosts your domain names and manages your DNS records.
Host provider: The provider that hosts your servers or cloud services for deploying certificates.

Cannot be edited after saving.", + "access.form.certificate_authority.label": "Certificate authority", + "access.form.certificate_authority.placeholder": "Please select a certificate authority", + "access.form.notification_channel.label": "Notification channel", + "access.form.notification_channel.placeholder": "Please select a notification channel", "access.form.1panel_api_url.label": "1Panel URL", "access.form.1panel_api_url.placeholder": "Please enter 1Panel URL", "access.form.1panel_api_url.tooltip": "For more information, see https://docs.1panel.pro/dev_manual/api_manual/", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index 016392fb..3f072589 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -27,6 +27,10 @@ "access.form.provider.label": "提供商", "access.form.provider.placeholder": "请选择提供商", "access.form.provider.tooltip": "提供商分为两种类型:
【DNS 提供商】你的 DNS 托管方,通常等同于域名注册商,用于在申请证书时管理您的域名解析记录。
【主机提供商】你的服务器或云服务的托管方,用于部署签发的证书。

该字段保存后不可修改。", + "access.form.certificate_authority.label": "证书颁发机构", + "access.form.certificate_authority.placeholder": "请选择证书颁发机构", + "access.form.notification_channel.label": "通知渠道", + "access.form.notification_channel.placeholder": "请选择通知渠道", "access.form.1panel_api_url.label": "1Panel URL", "access.form.1panel_api_url.placeholder": "请输入 1Panel URL", "access.form.1panel_api_url.tooltip": "这是什么?请参阅 https://1panel.cn/docs/dev_manual/api_manual/", diff --git a/ui/src/pages/accesses/AccessList.tsx b/ui/src/pages/accesses/AccessList.tsx index 66cdeab8..d3c78f65 100644 --- a/ui/src/pages/accesses/AccessList.tsx +++ b/ui/src/pages/accesses/AccessList.tsx @@ -85,7 +85,7 @@ const AccessList = () => {