From fd8ac3ae375b4a76572e70e8732375b9bf188196 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Tue, 25 Mar 2025 19:52:09 +0800 Subject: [PATCH] feat(ui): allow select dns-01 provider on application --- internal/pkg/core/uploader/uploader.go | 2 +- ui/src/components/access/AccessSelect.tsx | 4 +-- .../provider/AccessProviderSelect.tsx | 28 +++++++++++++------ .../provider/ApplyDNSProviderSelect.tsx | 28 +++++++++++++------ .../provider/DeployProviderSelect.tsx | 28 +++++++++++++------ .../workflow/node/DeployNodeConfigForm.tsx | 2 +- .../i18n/locales/en/nls.workflow.nodes.json | 4 ++- .../i18n/locales/zh/nls.workflow.nodes.json | 4 ++- 8 files changed, 67 insertions(+), 33 deletions(-) diff --git a/internal/pkg/core/uploader/uploader.go b/internal/pkg/core/uploader/uploader.go index 06cecec0..5edcdce4 100644 --- a/internal/pkg/core/uploader/uploader.go +++ b/internal/pkg/core/uploader/uploader.go @@ -27,6 +27,6 @@ type Uploader interface { // 表示证书上传结果的数据结构,包含上传后的证书 ID、名称和其他数据。 type UploadResult struct { CertId string `json:"certId"` - CertName string `json:"certName"` + CertName string `json:"certName,omitzero"` ExtendedData map[string]any `json:"extendedData,omitempty"` } diff --git a/ui/src/components/access/AccessSelect.tsx b/ui/src/components/access/AccessSelect.tsx index 3ad60348..7077e78d 100644 --- a/ui/src/components/access/AccessSelect.tsx +++ b/ui/src/components/access/AccessSelect.tsx @@ -21,9 +21,9 @@ const AccessSelect = ({ filter, ...props }: AccessTypeSelectProps) => { const [options, setOptions] = useState>([]); useEffect(() => { - const items = filter != null ? accesses.filter(filter) : accesses; + const filteredItems = filter != null ? accesses.filter(filter) : accesses; setOptions( - items.map((item) => ({ + filteredItems.map((item) => ({ key: item.id, value: item.id, label: item.name, diff --git a/ui/src/components/provider/AccessProviderSelect.tsx b/ui/src/components/provider/AccessProviderSelect.tsx index 97cd35fd..0e0a992c 100644 --- a/ui/src/components/provider/AccessProviderSelect.tsx +++ b/ui/src/components/provider/AccessProviderSelect.tsx @@ -1,22 +1,32 @@ -import { memo } from "react"; +import { memo, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Avatar, Select, type SelectProps, Space, Tag, Typography } from "antd"; -import { ACCESS_USAGES, accessProvidersMap } from "@/domain/provider"; +import { ACCESS_USAGES, type AccessProvider, accessProvidersMap } from "@/domain/provider"; export type AccessProviderSelectProps = Omit< SelectProps, "filterOption" | "filterSort" | "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender" ->; +> & { + filter?: (record: AccessProvider) => boolean; +}; -const AccessProviderSelect = (props: AccessProviderSelectProps) => { +const AccessProviderSelect = ({ filter, ...props }: AccessProviderSelectProps) => { const { t } = useTranslation(); - const options = Array.from(accessProvidersMap.values()).map((item) => ({ - key: item.type, - value: item.type, - label: t(item.name), - })); + const [options, setOptions] = useState>([]); + useEffect(() => { + const allItems = Array.from(accessProvidersMap.values()); + const filteredItems = filter != null ? allItems.filter(filter) : allItems; + setOptions( + filteredItems.map((item) => ({ + key: item.type, + value: item.type, + label: t(item.name), + data: item, + })) + ); + }, [filter]); const renderOption = (key: string) => { const provider = accessProvidersMap.get(key); diff --git a/ui/src/components/provider/ApplyDNSProviderSelect.tsx b/ui/src/components/provider/ApplyDNSProviderSelect.tsx index c88cfebf..f7e3c259 100644 --- a/ui/src/components/provider/ApplyDNSProviderSelect.tsx +++ b/ui/src/components/provider/ApplyDNSProviderSelect.tsx @@ -1,22 +1,32 @@ -import { memo } from "react"; +import { memo, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Avatar, Select, type SelectProps, Space, Typography } from "antd"; -import { applyDNSProvidersMap } from "@/domain/provider"; +import { type ApplyDNSProvider, applyDNSProvidersMap } from "@/domain/provider"; export type ApplyDNSProviderSelectProps = Omit< SelectProps, "filterOption" | "filterSort" | "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender" ->; +> & { + filter?: (record: ApplyDNSProvider) => boolean; +}; -const ApplyDNSProviderSelect = (props: ApplyDNSProviderSelectProps) => { +const ApplyDNSProviderSelect = ({ filter, ...props }: ApplyDNSProviderSelectProps) => { const { t } = useTranslation(); - const options = Array.from(applyDNSProvidersMap.values()).map((item) => ({ - key: item.type, - value: item.type, - label: t(item.name), - })); + const [options, setOptions] = useState>([]); + useEffect(() => { + const allItems = Array.from(applyDNSProvidersMap.values()); + const filteredItems = filter != null ? allItems.filter(filter) : allItems; + setOptions( + filteredItems.map((item) => ({ + key: item.type, + value: item.type, + label: t(item.name), + data: item, + })) + ); + }, [filter]); const renderOption = (key: string) => { const provider = applyDNSProvidersMap.get(key); diff --git a/ui/src/components/provider/DeployProviderSelect.tsx b/ui/src/components/provider/DeployProviderSelect.tsx index cc2b13ea..5be10cb7 100644 --- a/ui/src/components/provider/DeployProviderSelect.tsx +++ b/ui/src/components/provider/DeployProviderSelect.tsx @@ -1,22 +1,32 @@ -import { memo } from "react"; +import { memo, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { Avatar, Select, type SelectProps, Space, Typography } from "antd"; -import { deployProvidersMap } from "@/domain/provider"; +import { type DeployProvider, deployProvidersMap } from "@/domain/provider"; export type DeployProviderSelectProps = Omit< SelectProps, "filterOption" | "filterSort" | "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender" ->; +> & { + filter?: (record: DeployProvider) => boolean; +}; -const DeployProviderSelect = (props: DeployProviderSelectProps) => { +const DeployProviderSelect = ({ filter, ...props }: DeployProviderSelectProps) => { const { t } = useTranslation(); - const options = Array.from(deployProvidersMap.values()).map((item) => ({ - key: item.type, - value: item.type, - label: t(item.name), - })); + const [options, setOptions] = useState>([]); + useEffect(() => { + const allItems = Array.from(deployProvidersMap.values()); + const filteredItems = filter != null ? allItems.filter(filter) : allItems; + setOptions( + filteredItems.map((item) => ({ + key: item.type, + value: item.type, + label: t(item.name), + data: item, + })) + ); + }, [filter]); const renderOption = (key: string) => { const provider = deployProvidersMap.get(key); diff --git a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx index 8941432f..948f59f2 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigForm.tsx @@ -400,7 +400,6 @@ const DeployNodeConfigForm = forwardRef { if (fieldProvider) { return deployProvidersMap.get(fieldProvider)?.provider === record.provider; @@ -409,6 +408,7 @@ const DeployNodeConfigForm = forwardRef diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index 2135dc72..58ac67ee 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -31,6 +31,8 @@ "workflow_node.apply.form.contact_email.label": "Contact email", "workflow_node.apply.form.contact_email.placeholder": "Please enter contact email", "workflow_node.apply.form.contact_email.tooltip": "Contact information required for SSL certificate application. Please pay attention to the rate limits.", + "workflow_node.apply.form.challenge_type.label": "Challenge type", + "workflow_node.apply.form.challenge_type.placeholder": "Please select challenge type", "workflow_node.apply.form.provider.label": "DNS provider", "workflow_node.apply.form.provider.placeholder": "Please select DNS provider of the domains", "workflow_node.apply.form.provider_access.label": "DNS provider authorization", @@ -75,7 +77,7 @@ "workflow_node.apply.form.skip_before_expiry_days.prefix": "If the certificate expiration time exceeds", "workflow_node.apply.form.skip_before_expiry_days.suffix": ", skip to re-apply.", "workflow_node.apply.form.skip_before_expiry_days.unit": "days", - "workflow_node.apply.form.skip_before_expiry_days.tooltip": "Be careful not to exceed the validity period limit of the CA, otherwise the certificate may never be renewed.", + "workflow_node.apply.form.skip_before_expiry_days.tooltip": "Be careful not to exceed the validity period limit of the issued certificate, otherwise the certificate may never be renewed.", "workflow_node.deploy.label": "Deployment", "workflow_node.deploy.search.provider.placeholder": "Search deploy target ...", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 4fc41e8d..0207a4bf 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -31,6 +31,8 @@ "workflow_node.apply.form.contact_email.label": "联系邮箱", "workflow_node.apply.form.contact_email.placeholder": "请输入联系邮箱", "workflow_node.apply.form.contact_email.tooltip": "申请签发 SSL 证书时所需的联系方式。请注意 Let's Encrypt 账户注册的速率限制。点此了解更多。", + "workflow_node.apply.form.challenge_type.label": "质询方式", + "workflow_node.apply.form.challenge_type.placeholder": "请选择质询方式", "workflow_node.apply.form.provider.label": "DNS 提供商", "workflow_node.apply.form.provider.placeholder": "请选择 DNS 提供商", "workflow_node.apply.form.provider_access.label": "DNS 提供商授权", @@ -75,7 +77,7 @@ "workflow_node.apply.form.skip_before_expiry_days.prefix": "当上次签发的证书距到期时间超过", "workflow_node.apply.form.skip_before_expiry_days.suffix": "时,跳过重新申请。", "workflow_node.apply.form.skip_before_expiry_days.unit": "天", - "workflow_node.apply.form.skip_before_expiry_days.tooltip": "注意不要超过 CA 的证书有效期限制,否则证书可能永远不会续期。", + "workflow_node.apply.form.skip_before_expiry_days.tooltip": "注意不要超过颁发的证书最大有效期,否则证书可能永远不会续期。", "workflow_node.deploy.label": "部署证书", "workflow_node.deploy.search.provider.placeholder": "搜索部署目标……",