From d33b8caf1428f2b1ce2dc3ec0432280e7fbb5814 Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Sun, 27 Apr 2025 22:06:04 +0800 Subject: [PATCH] feat: support overwriting the default webhook data of deployers and notifiers --- ui/src/components/access/AccessForm.tsx | 7 +- .../access/AccessFormEmailConfig.tsx | 4 +- .../access/AccessFormMattermostConfig.tsx | 2 +- .../access/AccessFormTelegramConfig.tsx | 2 +- .../access/AccessFormWebhookConfig.tsx | 133 +++++++++++++++++- .../workflow/node/ApplyNodeConfigForm.tsx | 2 +- .../DeployNodeConfigFormWebhookConfig.tsx | 69 ++++----- .../workflow/node/NotifyNodeConfigForm.tsx | 18 ++- .../node/NotifyNodeConfigFormEmailConfig.tsx | 4 +- .../NotifyNodeConfigFormMattermostConfig.tsx | 2 +- .../NotifyNodeConfigFormTelegramConfig.tsx | 2 +- .../NotifyNodeConfigFormWebhookConfig.tsx | 86 +++++++++++ ui/src/i18n/locales/en/nls.access.json | 10 +- .../i18n/locales/en/nls.workflow.nodes.json | 26 ++-- ui/src/i18n/locales/zh/nls.access.json | 8 ++ .../i18n/locales/zh/nls.workflow.nodes.json | 20 ++- 16 files changed, 320 insertions(+), 75 deletions(-) create mode 100644 ui/src/components/workflow/node/NotifyNodeConfigFormWebhookConfig.tsx diff --git a/ui/src/components/access/AccessForm.tsx b/ui/src/components/access/AccessForm.tsx index c88e5bef..6f820bb3 100644 --- a/ui/src/components/access/AccessForm.tsx +++ b/ui/src/components/access/AccessForm.tsx @@ -246,7 +246,12 @@ const AccessForm = forwardRef(({ className, case ACCESS_PROVIDERS.WANGSU: return ; case ACCESS_PROVIDERS.WEBHOOK: - return ; + return ( + + ); case ACCESS_PROVIDERS.WESTCN: return ; case ACCESS_PROVIDERS.ZEROSSL: diff --git a/ui/src/components/access/AccessFormEmailConfig.tsx b/ui/src/components/access/AccessFormEmailConfig.tsx index 65023f68..ae79794a 100644 --- a/ui/src/components/access/AccessFormEmailConfig.tsx +++ b/ui/src/components/access/AccessFormEmailConfig.tsx @@ -112,11 +112,11 @@ const AccessFormEmailConfig = ({ form: formInst, formName, disabled, initialValu - + - + ); diff --git a/ui/src/components/access/AccessFormMattermostConfig.tsx b/ui/src/components/access/AccessFormMattermostConfig.tsx index f4a99ece..a583cc19 100644 --- a/ui/src/components/access/AccessFormMattermostConfig.tsx +++ b/ui/src/components/access/AccessFormMattermostConfig.tsx @@ -70,7 +70,7 @@ const AccessFormMattermostConfig = ({ form: formInst, formName, disabled, initia rules={[formRule]} tooltip={} > - + ); diff --git a/ui/src/components/access/AccessFormTelegramConfig.tsx b/ui/src/components/access/AccessFormTelegramConfig.tsx index 43b20f00..a4eccafb 100644 --- a/ui/src/components/access/AccessFormTelegramConfig.tsx +++ b/ui/src/components/access/AccessFormTelegramConfig.tsx @@ -72,7 +72,7 @@ const AccessFormTelegramConfig = ({ form: formInst, formName, disabled, initialV rules={[formRule]} tooltip={} > - + ); diff --git a/ui/src/components/access/AccessFormWebhookConfig.tsx b/ui/src/components/access/AccessFormWebhookConfig.tsx index 0a22d93e..f05d3097 100644 --- a/ui/src/components/access/AccessFormWebhookConfig.tsx +++ b/ui/src/components/access/AccessFormWebhookConfig.tsx @@ -1,8 +1,9 @@ import { useTranslation } from "react-i18next"; -import { Form, type FormInstance, Input, Select, Switch } from "antd"; +import { Alert, Button, Form, type FormInstance, Input, Select, Switch } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; +import Show from "@/components/Show"; import { type AccessConfigForWebhook } from "@/domain/access"; type AccessFormWebhookConfigFieldValues = Nullish; @@ -12,6 +13,7 @@ export type AccessFormWebhookConfigProps = { formName: string; disabled?: boolean; initialValues?: AccessFormWebhookConfigFieldValues; + usage?: "deployment" | "notification" | "none"; onValuesChange?: (values: AccessFormWebhookConfigFieldValues) => void; }; @@ -21,10 +23,27 @@ const initFormModel = (): AccessFormWebhookConfigFieldValues => { method: "POST", headers: "Content-Type: application/json", allowInsecureConnections: false, + defaultDataForDeployment: JSON.stringify( + { + name: "${DOMAINS}", + cert: "${CERTIFICATE}", + privkey: "${PRIVATE_KEY}", + }, + null, + 2 + ), + defaultDataForNotification: JSON.stringify( + { + subject: "${SUBJECT}", + message: "${MESSAGE}", + }, + null, + 2 + ), }; }; -const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: AccessFormWebhookConfigProps) => { +const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialValues, usage, onValuesChange }: AccessFormWebhookConfigProps) => { const { t } = useTranslation(); const formSchema = z.object({ @@ -47,6 +66,34 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa return true; }, t("access.form.webhook_headers.errmsg.invalid")), allowInsecureConnections: z.boolean().nullish(), + defaultDataForDeployment: z + .string() + .nullish() + .refine((v) => { + if (usage && usage !== "deployment") return true; + if (!v) return true; + + try { + const obj = JSON.parse(v); + return typeof obj === "object" && !Array.isArray(obj); + } catch { + return false; + } + }, t("access.form.webhook_default_data.errmsg.json_invalid")), + defaultDataForNotification: z + .string() + .nullish() + .refine((v) => { + if (usage && usage !== "notification") return true; + if (!v) return true; + + try { + const obj = JSON.parse(v); + return typeof obj === "object" && !Array.isArray(obj); + } catch { + return false; + } + }, t("access.form.webhook_default_data.errmsg.json_invalid")), }); const formRule = createSchemaFieldRule(formSchema); @@ -57,6 +104,34 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa formInst.setFieldValue("headers", value); }; + const handleWebhookDataForDeploymentBlur = (e: React.FocusEvent) => { + const value = e.target.value; + try { + const json = JSON.stringify(JSON.parse(value), null, 2); + formInst.setFieldValue("defaultDataForDeployment", json); + } catch { + return; + } + }; + + const handleWebhookDataForNotificationBlur = (e: React.FocusEvent) => { + const value = e.target.value; + try { + const json = JSON.stringify(JSON.parse(value), null, 2); + formInst.setFieldValue("defaultDataForNotification", json); + } catch { + return; + } + }; + + const handlePresetDataForDeploymentClick = () => { + formInst.setFieldValue("defaultDataForDeployment", initFormModel().defaultDataForDeployment); + }; + + const handlePresetDataForNotificationClick = () => { + formInst.setFieldValue("defaultDataForNotification", initFormModel().defaultDataForNotification); + }; + const handleFormChange = (_: unknown, values: z.infer) => { onValuesChange?.(values); }; @@ -90,6 +165,60 @@ const AccessFormWebhookConfig = ({ form: formInst, formName, disabled, initialVa + + + + + + + + + + } /> + + + + + + + + + + + + + } /> + + + { - if (!!record.reserve && record.reserve !== "ca") return false; + if (record.reserve !== "ca") return false; if (fieldCAProvider) return caProvidersMap.get(fieldCAProvider)?.provider === record.provider; const provider = accessProvidersMap.get(record.provider); diff --git a/ui/src/components/workflow/node/DeployNodeConfigFormWebhookConfig.tsx b/ui/src/components/workflow/node/DeployNodeConfigFormWebhookConfig.tsx index b916abf1..8305da8c 100644 --- a/ui/src/components/workflow/node/DeployNodeConfigFormWebhookConfig.tsx +++ b/ui/src/components/workflow/node/DeployNodeConfigFormWebhookConfig.tsx @@ -1,5 +1,5 @@ import { useTranslation } from "react-i18next"; -import { Alert, Button, Form, type FormInstance, Input } from "antd"; +import { Alert, Form, type FormInstance, Input } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; @@ -16,31 +16,26 @@ export type DeployNodeConfigFormWebhookConfigProps = { }; const initFormModel = (): DeployNodeConfigFormWebhookConfigFieldValues => { - return { - webhookData: JSON.stringify( - { - name: "${DOMAINS}", - cert: "${CERTIFICATE}", - privkey: "${PRIVATE_KEY}", - }, - null, - 2 - ), - }; + return {}; }; const DeployNodeConfigFormWebhookConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: DeployNodeConfigFormWebhookConfigProps) => { const { t } = useTranslation(); const formSchema = z.object({ - webhookData: z.string({ message: t("workflow_node.deploy.form.webhook_data.placeholder") }).refine((v) => { - try { - JSON.parse(v); - return true; - } catch { - return false; - } - }, t("workflow_node.deploy.form.webhook_data.errmsg.json_invalid")), + webhookData: z + .string() + .nullish() + .refine((v) => { + if (!v) return true; + + try { + const obj = JSON.parse(v); + return typeof obj === "object" && !Array.isArray(obj); + } catch { + return false; + } + }, t("workflow_node.deploy.form.webhook_data.errmsg.json_invalid")), }); const formRule = createSchemaFieldRule(formSchema); @@ -54,10 +49,6 @@ const DeployNodeConfigFormWebhookConfig = ({ form: formInst, formName, disabled, } }; - const handlePresetDataClick = () => { - formInst.setFieldValue("webhookData", initFormModel().webhookData); - }; - const handleFormChange = (_: unknown, values: z.infer) => { onValuesChange?.(values); }; @@ -71,24 +62,18 @@ const DeployNodeConfigFormWebhookConfig = ({ form: formInst, formName, disabled, name={formName} onValuesChange={handleFormChange} > - - - - - + } + > + diff --git a/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx b/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx index 71110e32..13dc1019 100644 --- a/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx +++ b/ui/src/components/workflow/node/NotifyNodeConfigForm.tsx @@ -2,13 +2,14 @@ import { forwardRef, memo, useEffect, useImperativeHandle, useMemo, useState } f import { useTranslation } from "react-i18next"; import { Link } from "react-router"; import { PlusOutlined as PlusOutlinedIcon, RightOutlined as RightOutlinedIcon } from "@ant-design/icons"; -import { Button, Form, type FormInstance, Input, Select } from "antd"; +import { Button, Divider, Form, type FormInstance, Input, Select, Typography } from "antd"; import { createSchemaFieldRule } from "antd-zod"; import { z } from "zod"; import AccessEditModal from "@/components/access/AccessEditModal"; import AccessSelect from "@/components/access/AccessSelect"; import NotificationProviderSelect from "@/components/provider/NotificationProviderSelect"; +import Show from "@/components/Show"; import { ACCESS_USAGES, NOTIFICATION_PROVIDERS, accessProvidersMap, notificationProvidersMap } from "@/domain/provider"; import { notifyChannelsMap } from "@/domain/settings"; import { type WorkflowNodeConfigForNotify } from "@/domain/workflow"; @@ -19,6 +20,7 @@ import { useNotifyChannelsStore } from "@/stores/notify"; import NotifyNodeConfigFormEmailConfig from "./NotifyNodeConfigFormEmailConfig"; import NotifyNodeConfigFormMattermostConfig from "./NotifyNodeConfigFormMattermostConfig"; import NotifyNodeConfigFormTelegramConfig from "./NotifyNodeConfigFormTelegramConfig"; +import NotifyNodeConfigFormWebhookConfig from "./NotifyNodeConfigFormWebhookConfig"; type NotifyNodeConfigFormFieldValues = Partial; @@ -114,6 +116,8 @@ const NotifyNodeConfigForm = forwardRef; case NOTIFICATION_PROVIDERS.TELEGRAM: return ; + case NOTIFICATION_PROVIDERS.WEBHOOK: + return ; } }, [disabled, initialValues?.providerConfig, fieldProvider, nestedFormInst, nestedFormName]); @@ -250,7 +254,7 @@ const NotifyNodeConfigForm = forwardRef { - if (!!record.reserve && record.reserve !== "notification") return false; + if (record.reserve !== "notification") return false; const provider = accessProvidersMap.get(record.provider); return !!provider?.usages?.includes(ACCESS_USAGES.NOTIFICATION); @@ -261,7 +265,15 @@ const NotifyNodeConfigForm = forwardRef - {nestedFormEl} + + + + {t("workflow_node.notify.form.params_config.label")} + + + + {nestedFormEl} + ); } diff --git a/ui/src/components/workflow/node/NotifyNodeConfigFormEmailConfig.tsx b/ui/src/components/workflow/node/NotifyNodeConfigFormEmailConfig.tsx index f7129a10..b6bfed17 100644 --- a/ui/src/components/workflow/node/NotifyNodeConfigFormEmailConfig.tsx +++ b/ui/src/components/workflow/node/NotifyNodeConfigFormEmailConfig.tsx @@ -62,7 +62,7 @@ const NotifyNodeConfigFormEmailConfig = ({ form: formInst, formName, disabled, i rules={[formRule]} tooltip={} > - + } > - + ); diff --git a/ui/src/components/workflow/node/NotifyNodeConfigFormMattermostConfig.tsx b/ui/src/components/workflow/node/NotifyNodeConfigFormMattermostConfig.tsx index 75f72c3c..c091298b 100644 --- a/ui/src/components/workflow/node/NotifyNodeConfigFormMattermostConfig.tsx +++ b/ui/src/components/workflow/node/NotifyNodeConfigFormMattermostConfig.tsx @@ -52,7 +52,7 @@ const NotifyNodeConfigFormMattermostConfig = ({ rules={[formRule]} tooltip={} > - + ); diff --git a/ui/src/components/workflow/node/NotifyNodeConfigFormTelegramConfig.tsx b/ui/src/components/workflow/node/NotifyNodeConfigFormTelegramConfig.tsx index b3cd6788..07774413 100644 --- a/ui/src/components/workflow/node/NotifyNodeConfigFormTelegramConfig.tsx +++ b/ui/src/components/workflow/node/NotifyNodeConfigFormTelegramConfig.tsx @@ -57,7 +57,7 @@ const NotifyNodeConfigFormTelegramConfig = ({ form: formInst, formName, disabled rules={[formRule]} tooltip={} > - + ); diff --git a/ui/src/components/workflow/node/NotifyNodeConfigFormWebhookConfig.tsx b/ui/src/components/workflow/node/NotifyNodeConfigFormWebhookConfig.tsx new file mode 100644 index 00000000..acaf00c2 --- /dev/null +++ b/ui/src/components/workflow/node/NotifyNodeConfigFormWebhookConfig.tsx @@ -0,0 +1,86 @@ +import { useTranslation } from "react-i18next"; +import { Alert, Form, type FormInstance, Input } from "antd"; +import { createSchemaFieldRule } from "antd-zod"; +import { z } from "zod"; + +type NotifyNodeConfigFormWebhookConfigFieldValues = Nullish<{ + webhookData: string; +}>; + +export type NotifyNodeConfigFormWebhookConfigProps = { + form: FormInstance; + formName: string; + disabled?: boolean; + initialValues?: NotifyNodeConfigFormWebhookConfigFieldValues; + onValuesChange?: (values: NotifyNodeConfigFormWebhookConfigFieldValues) => void; +}; + +const initFormModel = (): NotifyNodeConfigFormWebhookConfigFieldValues => { + return {}; +}; + +const NotifyNodeConfigFormWebhookConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: NotifyNodeConfigFormWebhookConfigProps) => { + const { t } = useTranslation(); + + const formSchema = z.object({ + webhookData: z + .string() + .nullish() + .refine((v) => { + if (!v) return true; + + try { + const obj = JSON.parse(v); + return typeof obj === "object" && !Array.isArray(obj); + } catch { + return false; + } + }, t("workflow_node.notify.form.webhook_data.errmsg.json_invalid")), + }); + const formRule = createSchemaFieldRule(formSchema); + + const handleWebhookDataBlur = (e: React.FocusEvent) => { + const value = e.target.value; + try { + const json = JSON.stringify(JSON.parse(value), null, 2); + formInst.setFieldValue("webhookData", json); + } catch { + return; + } + }; + + const handleFormChange = (_: unknown, values: z.infer) => { + onValuesChange?.(values); + }; + + return ( +
+ } + > + + + + + } /> + +
+ ); +}; + +export default NotifyNodeConfigFormWebhookConfig; diff --git a/ui/src/i18n/locales/en/nls.access.json b/ui/src/i18n/locales/en/nls.access.json index 20144481..a9930db3 100644 --- a/ui/src/i18n/locales/en/nls.access.json +++ b/ui/src/i18n/locales/en/nls.access.json @@ -28,7 +28,7 @@ "access.form.name.placeholder": "Please enter authorization name", "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.provider.tooltip": "DNS provider: The provider that hosts your domain names and manages your DNS records.
Hosting 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", @@ -346,6 +346,14 @@ "access.form.webhook_headers.placeholder": "Please enter Webhook request headers", "access.form.webhook_headers.errmsg.invalid": "Please enter a valid request headers", "access.form.webhook_headers.tooltip": "Format:
key1: val2
key2: val2


Example:
Content-Type: application/json
User-Agent: certimate
", + "access.form.webhook_default_data.errmsg.json_invalid": "Please enter a valiod JSON string", + "access.form.webhook_default_data_for_deployment.label": "Webhook data for deployment (Optional)", + "access.form.webhook_default_data_for_deployment.placeholder": "Please enter Webhook data", + "access.form.webhook_default_data_for_deployment.guide": "Tips: The Webhook data should be in JSON format.

The values in JSON support template variables, which will be replaced by actual values when sent to the Webhook URL. Supported variables:
  1. ${DOMAIN}: The primary domain of the certificate (CommonName).
  2. ${DOMAINS}: The domain list of the certificate (SubjectAltNames).
  3. ${CERTIFICATE}: The PEM format content of the certificate file.
  4. ${PRIVATE_KEY}: The PEM format content of the private key file.

When the request method is GET, the data will be passed as query string. Otherwise, the data will be encoded in the format indicated by the Content-Type in the request headers. Supported formats:
  1. application/json (default).
  2. application/x-www-form-urlencoded: Nested data is not supported.
  3. multipart/form-data: Nested data is not supported.
  4. ", + "access.form.webhook_default_data_for_notification.label": "Webhook data for notification (Optional)", + "access.form.webhook_default_data_for_notification.placeholder": "Please enter Webhook data", + "access.form.webhook_default_data_for_notification.guide": "Tips: The Webhook data should be in JSON format.

    The values in JSON support template variables, which will be replaced by actual values when sent to the Webhook URL. Supported variables:
    1. ${SUBJECT}: The subject of notification.
    2. ${MESSAGE}: The message of notification.

    When the request method is GET, the data will be passed as query string. Otherwise, the data will be encoded in the format indicated by the Content-Type in the request headers. Supported formats:
    1. application/json (default).
    2. application/x-www-form-urlencoded: Nested data is not supported.
    3. multipart/form-data: Nested data is not supported.
    4. ", + "access.form.webhook_default_data_preset.button": "Use preset template", "access.form.webhook_allow_insecure_conns.label": "Insecure SSL/TLS connections", "access.form.webhook_allow_insecure_conns.tooltip": "Allowing insecure connections may lead to data leak or tampering. Use this option only when under trusted networks.", "access.form.webhook_allow_insecure_conns.switch.on": "Allow", diff --git a/ui/src/i18n/locales/en/nls.workflow.nodes.json b/ui/src/i18n/locales/en/nls.workflow.nodes.json index aa91b8af..8a353e51 100644 --- a/ui/src/i18n/locales/en/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/en/nls.workflow.nodes.json @@ -93,8 +93,8 @@ "workflow_node.deploy.search.provider.placeholder": "Search deploy target ...", "workflow_node.deploy.form.provider.label": "Deploy target", "workflow_node.deploy.form.provider.placeholder": "Please select deploy target", - "workflow_node.deploy.form.provider_access.label": "Host provider authorization", - "workflow_node.deploy.form.provider_access.placeholder": "Please select an authorization of host provider", + "workflow_node.deploy.form.provider_access.label": "Hosting provider authorization", + "workflow_node.deploy.form.provider_access.placeholder": "Please select an authorization of Hosting provider", "workflow_node.deploy.form.provider_access.tooltip": "Used to invoke API during deployment.", "workflow_node.deploy.form.provider_access.button": "Create", "workflow_node.deploy.form.provider_access.guide_for_local": "Tips: If you are running Certimate in Docker, the \"Local\" refers to the container rather than the host.", @@ -685,11 +685,11 @@ "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.label": "Wangsu Cloud CDN Webhook ID (Optional)", "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.placeholder": "Please enter Wangsu Cloud CDN Webhook ID", "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.tooltip": "For more information, see https://cdnpro.console.wangsu.com/v2/index/#/certificate", - "workflow_node.deploy.form.webhook_data.label": "Webhook data (JSON format)", - "workflow_node.deploy.form.webhook_data.placeholder": "Please enter Webhook data", - "workflow_node.deploy.form.webhook_data.guide": "Tips: The Webhook data should be a key-value pair in JSON format. The values in JSON support template variables, which will be replaced by actual values when sent to the Webhook URL.

      Supported variables:
      ${DOMAIN}: The primary domain of the certificate (CommonName).
      ${DOMAINS}: The domain list of the certificate (SubjectAltNames).
      ${CERTIFICATE}: The PEM format content of the certificate file.
      ${PRIVATE_KEY}: The PEM format content of the private key file.", + "workflow_node.deploy.form.webhook_data.label": "Webhook data (Optional)", + "workflow_node.deploy.form.webhook_data.placeholder": "Please enter Webhook data to override the default value", + "workflow_node.deploy.form.webhook_data.tooltip": "Leave it blank to use the default Webhook data provided by the authorization.", + "workflow_node.deploy.form.webhook_data.guide": "Supported variables:
      1. ${DOMAIN}: The primary domain of the certificate (CommonName).
      2. ${DOMAINS}: The domain list of the certificate (SubjectAltNames).
      3. ${CERTIFICATE}: The PEM format content of the certificate file.
      4. ${PRIVATE_KEY}: The PEM format content of the private key file.

      Please visit the authorization management page for addtional notes.", "workflow_node.deploy.form.webhook_data.errmsg.json_invalid": "Please enter a valiod JSON string", - "workflow_node.deploy.form.webhook_data_preset.button": "Use preset template", "workflow_node.deploy.form.strategy_config.label": "Strategy settings", "workflow_node.deploy.form.skip_on_last_succeeded.label": "Repeated deployment", "workflow_node.deploy.form.skip_on_last_succeeded.prefix": "If the last deployment was successful, ", @@ -720,18 +720,24 @@ "workflow_node.notify.form.provider_access.label": "Notification provider authorization", "workflow_node.notify.form.provider_access.placeholder": "Please select an authorization of notification provider", "workflow_node.notify.form.provider_access.button": "Create", + "workflow_node.notify.form.params_config.label": "Parameter settings", "workflow_node.notify.form.email_sender_address.label": "Sender email address (Optional)", - "workflow_node.notify.form.email_sender_address.placeholder": "Please enter sender email address", + "workflow_node.notify.form.email_sender_address.placeholder": "Please enter sender email address to override the default value", "workflow_node.notify.form.email_sender_address.tooltip": "Leave it blank to use the default sender email address provided by the authorization.", "workflow_node.notify.form.email_receiver_address.label": "Receiver email address (Optional)", - "workflow_node.notify.form.email_receiver_address.placeholder": "Please enter receiver email address", + "workflow_node.notify.form.email_receiver_address.placeholder": "Please enter receiver email address to override the default value", "workflow_node.notify.form.email_receiver_address.tooltip": "Leave it blank to use the default receiver email address provided by the selected authorization.", "workflow_node.notify.form.mattermost_channel_id.label": "Mattermost channel ID (Optional)", - "workflow_node.notify.form.mattermost_channel_id.placeholder": "Please enter Mattermost channel ID", + "workflow_node.notify.form.mattermost_channel_id.placeholder": "Please enter Mattermost channel ID to override the default value", "workflow_node.notify.form.mattermost_channel_id.tooltip": "Leave it blank to use the default channel ID provided by the authorization.", "workflow_node.notify.form.telegram_chat_id.label": "Telegram chat ID (Optional)", - "workflow_node.notify.form.telegram_chat_id.placeholder": "Please enter Telegram chat ID", + "workflow_node.notify.form.telegram_chat_id.placeholder": "Please enter Telegram chat ID to override the default value", "workflow_node.notify.form.telegram_chat_id.tooltip": "Leave it blank to use the default chat ID provided by the selected authorization.", + "workflow_node.notify.form.webhook_data.label": "Webhook data (Optional)", + "workflow_node.notify.form.webhook_data.placeholder": "Please enter Webhook data to override the default value", + "workflow_node.notify.form.webhook_data.tooltip": "Leave it blank to use the default Webhook data provided by the authorization.", + "workflow_node.notify.form.webhook_data.guide": "Supported variables:
      1. ${SUBJECT}: The subject of notification.
      2. ${MESSAGE}: The message of notification.

      Please visit the authorization management page for addtional notes.", + "workflow_node.notify.form.webhook_data.errmsg.json_invalid": "Please enter a valiod JSON string", "workflow_node.end.label": "End", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index 9de079d1..0f26e632 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -346,6 +346,14 @@ "access.form.webhook_headers.placeholder": "请输入 Webhook 请求标头", "access.form.webhook_headers.errmsg.invalid": "请输入有效的请求标头", "access.form.webhook_headers.tooltip": "格式:
      key1: val2
      key2: val2


      示例:
      Content-Type: application/json
      User-Agent: certimate
      ", + "access.form.webhook_default_data.errmsg.json_invalid": "请输入有效的 JSON 格式字符串", + "access.form.webhook_default_data_for_deployment.label": "默认的 Webhook 部署证书回调数据(可选)", + "access.form.webhook_default_data_for_deployment.placeholder": "请输入默认的 Webhook 回调数据", + "access.form.webhook_default_data_for_deployment.guide": "小贴士:回调数据是一个 JSON 格式的数据。

      其中值支持模板变量,将在被发送到指定的 Webhook URL 时被替换为实际值;其他内容将保持原样。支持的变量:
      1. ${DOMAIN}:证书的主域名(即 CommonName)。
      2. ${DOMAINS}:证书的多域名列表(即 SubjectAltNames)。
      3. ${CERTIFICATE}:证书文件 PEM 格式内容。
      4. ${PRIVATE_KEY}:私钥文件 PEM 格式内容。

      当请求谓词为 GET 时,回调数据将作为查询参数;否则,回调数据将按照请求标头中 Content-Type 所指示的格式进行编码。支持的格式:
      1. application/json(默认)。
      2. application/x-www-form-urlencoded:不支持嵌套数据。
      3. multipart/form-data:不支持嵌套数据。
      4. ", + "access.form.webhook_default_data_for_notification.label": "默认的 Webhook 推送通知回调数据(可选)", + "access.form.webhook_default_data_for_notification.placeholder": "请输入默认的 Webhook 回调数据", + "access.form.webhook_default_data_for_notification.guide": "小贴士:回调数据是一个 JSON 格式的数据。

        其中值支持模板变量,将在被发送到指定的 Webhook URL 时被替换为实际值;其他内容将保持原样。支持的变量:
        1. ${DOMAIN}:证书的主域名(即 CommonName)。
        2. ${SUBJECT}:通知主题。
        3. ${MESSAGE}:通知内容。

        当请求谓词为 GET 时,回调数据将作为查询参数;否则,回调数据将按照请求标头中 Content-Type 所指示的格式进行编码。支持的格式:
        1. application/json(默认)。
        2. application/x-www-form-urlencoded:不支持嵌套数据。
        3. multipart/form-data:不支持嵌套数据。
        4. ", + "access.form.webhook_default_data_preset.button": "使用预设模板", "access.form.webhook_allow_insecure_conns.label": "忽略 SSL/TLS 证书错误", "access.form.webhook_allow_insecure_conns.tooltip": "忽略 SSL/TLS 证书错误可能导致数据泄露或被篡改。建议仅在可信网络下启用。", "access.form.webhook_allow_insecure_conns.switch.on": "允许", diff --git a/ui/src/i18n/locales/zh/nls.workflow.nodes.json b/ui/src/i18n/locales/zh/nls.workflow.nodes.json index 31bcf762..d58ebe90 100644 --- a/ui/src/i18n/locales/zh/nls.workflow.nodes.json +++ b/ui/src/i18n/locales/zh/nls.workflow.nodes.json @@ -684,11 +684,11 @@ "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.label": "网宿云 CDN Pro 部署任务 Webhook ID(可选)", "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.placeholder": "请输入网宿云 CDN Pro 部署任务 Webhook ID", "workflow_node.deploy.form.wangsu_cdnpro_webhook_id.tooltip": "这是什么?请参阅 https://cdnpro.console.wangsu.com/v2/index/#/certificate", - "workflow_node.deploy.form.webhook_data.label": "Webhook 回调数据(JSON 格式)", + "workflow_node.deploy.form.webhook_data.label": "Webhook 回调数据(可选)", "workflow_node.deploy.form.webhook_data.placeholder": "请输入 Webhook 回调数据", - "workflow_node.deploy.form.webhook_data.guide": "小贴士:回调数据是一个 JSON 格式的键值对。其中值支持模板变量,将在被发送到指定的 Webhook URL 时被替换为实际值;其他内容将保持原样。

          支持的变量:
          ${DOMAIN}:证书的主域名(即 CommonName
          ${DOMAINS}:证书的多域名列表(即 SubjectAltNames
          ${CERTIFICATE}:证书文件 PEM 格式内容
          ${PRIVATE_KEY}:私钥文件 PEM 格式内容", + "workflow_node.deploy.form.webhook_data.tooltip": "不填写时,将使用所选部署目标授权的默认 Webhook 回调数据。", + "workflow_node.deploy.form.webhook_data.guide": "支持的变量:
          1. ${DOMAIN}:证书的主域名(即 CommonName)。
          2. ${DOMAINS}:证书的多域名列表(即 SubjectAltNames)。
          3. ${CERTIFICATE}:证书文件 PEM 格式内容。
          4. ${PRIVATE_KEY}:私钥文件 PEM 格式内容。

          其他注意事项请前往授权管理页面查看。", "workflow_node.deploy.form.webhook_data.errmsg.json_invalid": "请输入有效的 JSON 格式字符串", - "workflow_node.deploy.form.webhook_data_preset.button": "使用预设模板", "workflow_node.deploy.form.strategy_config.label": "执行策略", "workflow_node.deploy.form.skip_on_last_succeeded.label": "重复部署", "workflow_node.deploy.form.skip_on_last_succeeded.prefix": "当上次部署相同证书成功时,", @@ -719,18 +719,24 @@ "workflow_node.notify.form.provider_access.label": "通知渠道授权", "workflow_node.notify.form.provider_access.placeholder": "请选择通知渠道授权", "workflow_node.notify.form.provider_access.button": "新建", + "workflow_node.notify.form.params_config.label": "参数设置", "workflow_node.notify.form.email_sender_address.label": "发送邮箱地址(可选)", - "workflow_node.notify.form.email_sender_address.placeholder": "请输入发送邮箱地址", + "workflow_node.notify.form.email_sender_address.placeholder": "请输入发送邮箱地址以覆盖默认值", "workflow_node.notify.form.email_sender_address.tooltip": "不填写时,将使用所选通知渠道授权的默认发送邮箱地址。", "workflow_node.notify.form.email_receiver_address.label": "接收邮箱地址(可选)", - "workflow_node.notify.form.email_receiver_address.placeholder": "请输入接收邮箱地址", + "workflow_node.notify.form.email_receiver_address.placeholder": "请输入接收邮箱地址以覆盖默认值", "workflow_node.notify.form.email_receiver_address.tooltip": "不填写时,将使用所选通知渠道授权的默认接收邮箱地址。", "workflow_node.notify.form.mattermost_channel_id.label": "Mattermost 频道 ID(可选)", - "workflow_node.notify.form.mattermost_channel_id.placeholder": "请输入 Mattermost 频道 ID", + "workflow_node.notify.form.mattermost_channel_id.placeholder": "请输入 Mattermost 频道 ID 以覆盖默认值", "workflow_node.notify.form.mattermost_channel_id.tooltip": "不填写时,将使用所选通知渠道授权的默认频道 ID。", "workflow_node.notify.form.telegram_chat_id.label": "Telegram 会话 ID(可选)", - "workflow_node.notify.form.telegram_chat_id.placeholder": "请输入 Telegram 会话 ID", + "workflow_node.notify.form.telegram_chat_id.placeholder": "请输入 Telegram 会话 ID 以覆盖默认值", "workflow_node.notify.form.telegram_chat_id.tooltip": "不填写时,将使用所选通知渠道授权的默认会话 ID。", + "workflow_node.notify.form.webhook_data.label": "Webhook 回调数据(可选)", + "workflow_node.notify.form.webhook_data.placeholder": "请输入 Webhook 回调数据以覆盖默认值", + "workflow_node.notify.form.webhook_data.tooltip": "不填写时,将使用所选部署目标授权的默认 Webhook 回调数据。", + "workflow_node.notify.form.webhook_data.guide": "支持的变量:
          1. ${DOMAIN}:证书的主域名(即 CommonName)。
          2. ${DOMAINS}:证书的多域名列表(即 SubjectAltNames)。
          3. ${CERTIFICATE}:证书文件 PEM 格式内容。
          4. ${PRIVATE_KEY}:私钥文件 PEM 格式内容。

          其他注意事项请前往授权管理页面查看。", + "workflow_node.notify.form.webhook_data.errmsg.json_invalid": "请输入有效的 JSON 格式字符串", "workflow_node.end.label": "结束",