mirror of
https://github.com/usual2970/certimate.git
synced 2025-07-21 02:18:00 +00:00
feat: support overwriting the default config of notifiers
This commit is contained in:
@@ -218,8 +218,6 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
};
|
||||
|
||||
const handleProviderAccessSelect = (value: string) => {
|
||||
if (fieldProviderAccessId === value) return;
|
||||
|
||||
// 切换授权信息时联动 DNS 提供商
|
||||
const access = accesses.find((access) => access.id === value);
|
||||
const provider = Array.from(acmeDns01ProvidersMap.values()).find((provider) => provider.provider === access?.provider);
|
||||
@@ -230,8 +228,6 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
};
|
||||
|
||||
const handleCAProviderSelect = (value?: string | undefined) => {
|
||||
if (fieldCAProvider === value) return;
|
||||
|
||||
// 切换 CA 提供商时联动授权信息
|
||||
if (value === "") {
|
||||
setTimeout(() => {
|
||||
@@ -368,6 +364,7 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
const provider = accessProvidersMap.get(record.provider);
|
||||
if (provider?.usages?.includes(ACCESS_USAGES.DNS)) {
|
||||
formInst.setFieldValue("providerAccessId", record.id);
|
||||
handleProviderAccessSelect(record.id);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
@@ -322,8 +322,6 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
};
|
||||
|
||||
const handleProviderSelect = (value?: string | undefined) => {
|
||||
if (fieldProvider === value) return;
|
||||
|
||||
// 切换部署目标时重置表单,避免其他部署目标的配置字段影响当前部署目标
|
||||
if (initialValues?.provider === value) {
|
||||
formInst.resetFields();
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { forwardRef, memo, useEffect, useImperativeHandle, useState } from "react";
|
||||
import { forwardRef, memo, useEffect, useImperativeHandle, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router";
|
||||
import { PlusOutlined as PlusOutlinedIcon, RightOutlined as RightOutlinedIcon } from "@ant-design/icons";
|
||||
@@ -9,13 +9,17 @@ import { z } from "zod";
|
||||
import AccessEditModal from "@/components/access/AccessEditModal";
|
||||
import AccessSelect from "@/components/access/AccessSelect";
|
||||
import NotificationProviderSelect from "@/components/provider/NotificationProviderSelect";
|
||||
import { ACCESS_USAGES, accessProvidersMap, notificationProvidersMap } from "@/domain/provider";
|
||||
import { ACCESS_USAGES, NOTIFICATION_PROVIDERS, accessProvidersMap, notificationProvidersMap } from "@/domain/provider";
|
||||
import { notifyChannelsMap } from "@/domain/settings";
|
||||
import { type WorkflowNodeConfigForNotify } from "@/domain/workflow";
|
||||
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
|
||||
import { useAntdForm, useAntdFormName, useZustandShallowSelector } from "@/hooks";
|
||||
import { useAccessesStore } from "@/stores/access";
|
||||
import { useNotifyChannelsStore } from "@/stores/notify";
|
||||
|
||||
import NotifyNodeConfigFormEmailConfig from "./NotifyNodeConfigFormEmailConfig";
|
||||
import NotifyNodeConfigFormMattermostConfig from "./NotifyNodeConfigFormMattermostConfig";
|
||||
import NotifyNodeConfigFormTelegramConfig from "./NotifyNodeConfigFormTelegramConfig";
|
||||
|
||||
type NotifyNodeConfigFormFieldValues = Partial<WorkflowNodeConfigForNotify>;
|
||||
|
||||
export type NotifyNodeConfigFormProps = {
|
||||
@@ -65,6 +69,7 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
||||
providerAccessId: z
|
||||
.string({ message: t("workflow_node.notify.form.provider_access.placeholder") })
|
||||
.nonempty(t("workflow_node.notify.form.provider_access.placeholder")),
|
||||
providerConfig: z.any().nullish(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const { form: formInst, formProps } = useAntdForm({
|
||||
@@ -88,9 +93,31 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
||||
}
|
||||
}, [accesses, fieldProviderAccessId]);
|
||||
|
||||
const handleProviderSelect = (value: string) => {
|
||||
if (fieldProvider === value) return;
|
||||
const [nestedFormInst] = Form.useForm();
|
||||
const nestedFormName = useAntdFormName({ form: nestedFormInst, name: "workflowNodeNotifyConfigFormProviderConfigForm" });
|
||||
const nestedFormEl = useMemo(() => {
|
||||
const nestedFormProps = {
|
||||
form: nestedFormInst,
|
||||
formName: nestedFormName,
|
||||
disabled: disabled,
|
||||
initialValues: initialValues?.providerConfig,
|
||||
};
|
||||
|
||||
/*
|
||||
注意:如果追加新的子组件,请保持以 ASCII 排序。
|
||||
NOTICE: If you add new child component, please keep ASCII order.
|
||||
*/
|
||||
switch (fieldProvider) {
|
||||
case NOTIFICATION_PROVIDERS.EMAIL:
|
||||
return <NotifyNodeConfigFormEmailConfig {...nestedFormProps} />;
|
||||
case NOTIFICATION_PROVIDERS.MATTERMOST:
|
||||
return <NotifyNodeConfigFormMattermostConfig {...nestedFormProps} />;
|
||||
case NOTIFICATION_PROVIDERS.TELEGRAM:
|
||||
return <NotifyNodeConfigFormTelegramConfig {...nestedFormProps} />;
|
||||
}
|
||||
}, [disabled, initialValues?.providerConfig, fieldProvider, nestedFormInst, nestedFormName]);
|
||||
|
||||
const handleProviderSelect = (value: string) => {
|
||||
// 切换消息通知提供商时联动授权信息
|
||||
if (initialValues?.provider === value) {
|
||||
formInst.setFieldValue("providerAccessId", initialValues?.providerAccessId);
|
||||
@@ -104,8 +131,6 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
||||
};
|
||||
|
||||
const handleProviderAccessSelect = (value: string) => {
|
||||
if (fieldProviderAccessId === value) return;
|
||||
|
||||
// 切换授权信息时联动消息通知提供商
|
||||
const access = accesses.find((access) => access.id === value);
|
||||
const provider = Array.from(notificationProvidersMap.values()).find((provider) => provider.provider === access?.provider);
|
||||
@@ -122,13 +147,21 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
||||
useImperativeHandle(ref, () => {
|
||||
return {
|
||||
getFieldsValue: () => {
|
||||
return formInst.getFieldsValue(true);
|
||||
const values = formInst.getFieldsValue(true);
|
||||
values.providerConfig = nestedFormInst.getFieldsValue();
|
||||
return values;
|
||||
},
|
||||
resetFields: (fields) => {
|
||||
return formInst.resetFields(fields as (keyof NotifyNodeConfigFormFieldValues)[]);
|
||||
formInst.resetFields(fields);
|
||||
|
||||
if (!!fields && fields.includes("providerConfig")) {
|
||||
nestedFormInst.resetFields(fields);
|
||||
}
|
||||
},
|
||||
validateFields: (nameList, config) => {
|
||||
return formInst.validateFields(nameList, config);
|
||||
const t1 = formInst.validateFields(nameList, config);
|
||||
const t2 = nestedFormInst.validateFields(undefined, config);
|
||||
return Promise.all([t1, t2]).then(() => t1);
|
||||
},
|
||||
} as NotifyNodeConfigFormInstance;
|
||||
});
|
||||
@@ -207,6 +240,7 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
||||
const provider = accessProvidersMap.get(record.provider);
|
||||
if (provider?.usages?.includes(ACCESS_USAGES.NOTIFICATION)) {
|
||||
formInst.setFieldValue("providerAccessId", record.id);
|
||||
handleProviderAccessSelect(record.id);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@@ -224,6 +258,8 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
|
||||
{nestedFormEl}
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
@@ -0,0 +1,80 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validEmailAddress } from "@/utils/validators";
|
||||
|
||||
type NotifyNodeConfigFormEmailConfigFieldValues = Nullish<{
|
||||
senderAddress?: string;
|
||||
receiverAddress?: string;
|
||||
}>;
|
||||
|
||||
export type NotifyNodeConfigFormEmailConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: NotifyNodeConfigFormEmailConfigFieldValues;
|
||||
onValuesChange?: (values: NotifyNodeConfigFormEmailConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const initFormModel = (): NotifyNodeConfigFormEmailConfigFieldValues => {
|
||||
return {};
|
||||
};
|
||||
|
||||
const NotifyNodeConfigFormEmailConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: NotifyNodeConfigFormEmailConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
senderAddress: z
|
||||
.string()
|
||||
.nullish()
|
||||
.refine((v) => {
|
||||
if (!v) return true;
|
||||
return validEmailAddress(v);
|
||||
}, t("common.errmsg.email_invalid")),
|
||||
receiverAddress: z
|
||||
.string()
|
||||
.nullish()
|
||||
.refine((v) => {
|
||||
if (!v) return true;
|
||||
return validEmailAddress(v);
|
||||
}, t("common.errmsg.email_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={formInst}
|
||||
disabled={disabled}
|
||||
initialValues={initialValues ?? initFormModel()}
|
||||
layout="vertical"
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item
|
||||
name="senderAddress"
|
||||
label={t("workflow_node.notify.form.email_sender_address.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.notify.form.email_sender_address.tooltip") }}></span>}
|
||||
>
|
||||
<Input type="email" placeholder={t("workflow_node.notify.form.email_sender_address.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="receiverAddress"
|
||||
label={t("workflow_node.notify.form.email_receiver_address.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.notify.form.email_receiver_address.tooltip") }}></span>}
|
||||
>
|
||||
<Input type="email" placeholder={t("workflow_node.notify.form.email_receiver_address.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotifyNodeConfigFormEmailConfig;
|
@@ -0,0 +1,61 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
type NotifyNodeConfigFormMattermostConfigFieldValues = Nullish<{
|
||||
channelId?: string;
|
||||
}>;
|
||||
|
||||
export type NotifyNodeConfigFormMattermostConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: NotifyNodeConfigFormMattermostConfigFieldValues;
|
||||
onValuesChange?: (values: NotifyNodeConfigFormMattermostConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const initFormModel = (): NotifyNodeConfigFormMattermostConfigFieldValues => {
|
||||
return {};
|
||||
};
|
||||
|
||||
const NotifyNodeConfigFormMattermostConfig = ({
|
||||
form: formInst,
|
||||
formName,
|
||||
disabled,
|
||||
initialValues,
|
||||
onValuesChange,
|
||||
}: NotifyNodeConfigFormMattermostConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
channelId: z.string().nullish(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={formInst}
|
||||
disabled={disabled}
|
||||
initialValues={initialValues ?? initFormModel()}
|
||||
layout="vertical"
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item
|
||||
name="channelId"
|
||||
label={t("workflow_node.notify.form.mattermost_channel_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.notify.form.mattermost_channel_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.notify.form.mattermost_channel_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotifyNodeConfigFormMattermostConfig;
|
@@ -0,0 +1,66 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
type NotifyNodeConfigFormTelegramConfigFieldValues = Nullish<{
|
||||
chatId?: string | number;
|
||||
}>;
|
||||
|
||||
export type NotifyNodeConfigFormTelegramConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: NotifyNodeConfigFormTelegramConfigFieldValues;
|
||||
onValuesChange?: (values: NotifyNodeConfigFormTelegramConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const initFormModel = (): NotifyNodeConfigFormTelegramConfigFieldValues => {
|
||||
return {};
|
||||
};
|
||||
|
||||
const NotifyNodeConfigFormTelegramConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: NotifyNodeConfigFormTelegramConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
chatId: z
|
||||
.preprocess(
|
||||
(v) => (v == null || v === "" ? undefined : Number(v)),
|
||||
z
|
||||
.number()
|
||||
.nullish()
|
||||
.refine((v) => {
|
||||
if (v == null || v + "" === "") return true;
|
||||
return /^\d+$/.test(v + "") && +v! > 0;
|
||||
}, t("workflow_node.notify.form.telegram_chat_id.placeholder"))
|
||||
)
|
||||
.nullish(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form
|
||||
form={formInst}
|
||||
disabled={disabled}
|
||||
initialValues={initialValues ?? initFormModel()}
|
||||
layout="vertical"
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item
|
||||
name="chatId"
|
||||
label={t("workflow_node.notify.form.telegram_chat_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.notify.form.telegram_chat_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input type="number" placeholder={t("workflow_node.notify.form.telegram_chat_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotifyNodeConfigFormTelegramConfig;
|
Reference in New Issue
Block a user