Merge branch 'main' into feat/condition
This commit is contained in:
@@ -1,12 +1,7 @@
|
||||
import { forwardRef, memo, useEffect, useImperativeHandle, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router";
|
||||
import {
|
||||
FormOutlined as FormOutlinedIcon,
|
||||
PlusOutlined as PlusOutlinedIcon,
|
||||
QuestionCircleOutlined as QuestionCircleOutlinedIcon,
|
||||
RightOutlined as RightOutlinedIcon,
|
||||
} from "@ant-design/icons";
|
||||
import { PlusOutlined as PlusOutlinedIcon, QuestionCircleOutlined as QuestionCircleOutlinedIcon, RightOutlined as RightOutlinedIcon } from "@ant-design/icons";
|
||||
import { useControllableValue } from "ahooks";
|
||||
import {
|
||||
AutoComplete,
|
||||
@@ -19,7 +14,6 @@ import {
|
||||
Input,
|
||||
InputNumber,
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Tooltip,
|
||||
Typography,
|
||||
@@ -29,8 +23,7 @@ import { z } from "zod";
|
||||
|
||||
import AccessEditModal from "@/components/access/AccessEditModal";
|
||||
import AccessSelect from "@/components/access/AccessSelect";
|
||||
import ModalForm from "@/components/ModalForm";
|
||||
import MultipleInput from "@/components/MultipleInput";
|
||||
import MultipleSplitValueInput from "@/components/MultipleSplitValueInput";
|
||||
import ACMEDns01ProviderSelect from "@/components/provider/ACMEDns01ProviderSelect";
|
||||
import CAProviderSelect from "@/components/provider/CAProviderSelect";
|
||||
import Show from "@/components/Show";
|
||||
@@ -152,11 +145,9 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
initialValues: initialValues ?? initFormModel(),
|
||||
});
|
||||
|
||||
const fieldDomains = Form.useWatch<string>("domains", formInst);
|
||||
const fieldProvider = Form.useWatch<string>("provider", { form: formInst, preserve: true });
|
||||
const fieldProviderAccessId = Form.useWatch<string>("providerAccessId", formInst);
|
||||
const fieldCAProvider = Form.useWatch<string>("caProvider", formInst);
|
||||
const fieldNameservers = Form.useWatch<string>("nameservers", formInst);
|
||||
|
||||
const [showProvider, setShowProvider] = useState(false);
|
||||
useEffect(() => {
|
||||
@@ -294,25 +285,17 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
<Form.Provider onFormChange={handleFormProviderChange}>
|
||||
<Form className={className} style={style} {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
|
||||
<Form.Item
|
||||
name="domains"
|
||||
label={t("workflow_node.apply.form.domains.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.domains.tooltip") }}></span>}
|
||||
>
|
||||
<Space.Compact style={{ width: "100%" }}>
|
||||
<Form.Item name="domains" noStyle rules={[formRule]}>
|
||||
<Input placeholder={t("workflow_node.apply.form.domains.placeholder")} />
|
||||
</Form.Item>
|
||||
<DomainsModalInput
|
||||
value={fieldDomains}
|
||||
trigger={
|
||||
<Button disabled={disabled}>
|
||||
<FormOutlinedIcon />
|
||||
</Button>
|
||||
}
|
||||
onChange={(v) => {
|
||||
formInst.setFieldValue("domains", v);
|
||||
}}
|
||||
/>
|
||||
</Space.Compact>
|
||||
<MultipleSplitValueInput
|
||||
modalTitle={t("workflow_node.apply.form.domains.multiple_input_modal.title")}
|
||||
placeholder={t("workflow_node.apply.form.domains.placeholder")}
|
||||
placeholderInModal={t("workflow_node.apply.form.domains.multiple_input_modal.placeholder")}
|
||||
splitOptions={{ trim: true, removeEmpty: true }}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
@@ -497,36 +480,17 @@ const ApplyNodeConfigForm = forwardRef<ApplyNodeConfigFormInstance, ApplyNodeCon
|
||||
|
||||
<Form className={className} style={style} {...formProps} disabled={disabled} layout="vertical" scrollToFirstError onValuesChange={handleFormChange}>
|
||||
<Form.Item
|
||||
name="nameservers"
|
||||
label={t("workflow_node.apply.form.nameservers.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.nameservers.tooltip") }}></span>}
|
||||
>
|
||||
<Space.Compact style={{ width: "100%" }}>
|
||||
<Form.Item name="nameservers" noStyle rules={[formRule]}>
|
||||
<Input
|
||||
allowClear
|
||||
disabled={disabled}
|
||||
value={fieldNameservers}
|
||||
placeholder={t("workflow_node.apply.form.nameservers.placeholder")}
|
||||
onChange={(e) => {
|
||||
formInst.setFieldValue("nameservers", e.target.value);
|
||||
}}
|
||||
onClear={() => {
|
||||
formInst.setFieldValue("nameservers", undefined);
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<NameserversModalInput
|
||||
value={fieldNameservers}
|
||||
trigger={
|
||||
<Button disabled={disabled}>
|
||||
<FormOutlinedIcon />
|
||||
</Button>
|
||||
}
|
||||
onChange={(value) => {
|
||||
formInst.setFieldValue("nameservers", value);
|
||||
}}
|
||||
/>
|
||||
</Space.Compact>
|
||||
<MultipleSplitValueInput
|
||||
modalTitle={t("workflow_node.apply.form.nameservers.multiple_input_modal.title")}
|
||||
placeholder={t("workflow_node.apply.form.nameservers.placeholder")}
|
||||
placeholderInModal={t("workflow_node.apply.form.nameservers.multiple_input_modal.placeholder")}
|
||||
splitOptions={{ trim: true, removeEmpty: true }}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
@@ -678,84 +642,4 @@ const EmailInput = memo(
|
||||
}
|
||||
);
|
||||
|
||||
const DomainsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
domains: z.array(z.string()).refine((v) => {
|
||||
return v.every((e) => !e?.trim() || validDomainName(e.trim(), { allowWildcard: true }));
|
||||
}, t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const { form: formInst, formProps } = useAntdForm({
|
||||
name: "workflowNodeApplyConfigFormDomainsModalInput",
|
||||
initialValues: { domains: value?.split(MULTIPLE_INPUT_DELIMITER) },
|
||||
onSubmit: (values) => {
|
||||
onChange?.(
|
||||
values.domains
|
||||
.map((e) => e.trim())
|
||||
.filter((e) => !!e)
|
||||
.join(MULTIPLE_INPUT_DELIMITER)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<ModalForm
|
||||
{...formProps}
|
||||
layout="vertical"
|
||||
form={formInst}
|
||||
modalProps={{ destroyOnHidden: true }}
|
||||
title={t("workflow_node.apply.form.domains.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
width={480}
|
||||
>
|
||||
<Form.Item name="domains" rules={[formRule]}>
|
||||
<MultipleInput placeholder={t("workflow_node.apply.form.domains.multiple_input_modal.placeholder")} />
|
||||
</Form.Item>
|
||||
</ModalForm>
|
||||
);
|
||||
});
|
||||
|
||||
const NameserversModalInput = memo(({ trigger, value, onChange }: { trigger?: React.ReactNode; value?: string; onChange?: (value: string) => void }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
nameservers: z.array(z.string()).refine((v) => {
|
||||
return v.every((e) => !e?.trim() || validIPv4Address(e) || validIPv6Address(e) || validDomainName(e));
|
||||
}, t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const { form: formInst, formProps } = useAntdForm({
|
||||
name: "workflowNodeApplyConfigFormNameserversModalInput",
|
||||
initialValues: { nameservers: value?.split(MULTIPLE_INPUT_DELIMITER) },
|
||||
onSubmit: (values) => {
|
||||
onChange?.(
|
||||
values.nameservers
|
||||
.map((e) => e.trim())
|
||||
.filter((e) => !!e)
|
||||
.join(MULTIPLE_INPUT_DELIMITER)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<ModalForm
|
||||
{...formProps}
|
||||
layout="vertical"
|
||||
form={formInst}
|
||||
modalProps={{ destroyOnHidden: true }}
|
||||
title={t("workflow_node.apply.form.nameservers.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
width={480}
|
||||
>
|
||||
<Form.Item name="nameservers" rules={[formRule]}>
|
||||
<MultipleInput placeholder={t("workflow_node.apply.form.nameservers.multiple_input_modal.placeholder")} />
|
||||
</Form.Item>
|
||||
</ModalForm>
|
||||
);
|
||||
});
|
||||
|
||||
export default memo(ApplyNodeConfigForm);
|
||||
|
||||
@@ -82,6 +82,7 @@ import DeployNodeConfigFormTencentCloudVODConfig from "./DeployNodeConfigFormTen
|
||||
import DeployNodeConfigFormTencentCloudWAFConfig from "./DeployNodeConfigFormTencentCloudWAFConfig";
|
||||
import DeployNodeConfigFormUCloudUCDNConfig from "./DeployNodeConfigFormUCloudUCDNConfig.tsx";
|
||||
import DeployNodeConfigFormUCloudUS3Config from "./DeployNodeConfigFormUCloudUS3Config.tsx";
|
||||
import DeployNodeConfigFormUniCloudWebHostConfig from "./DeployNodeConfigFormUniCloudWebHostConfig.tsx";
|
||||
import DeployNodeConfigFormUpyunCDNConfig from "./DeployNodeConfigFormUpyunCDNConfig.tsx";
|
||||
import DeployNodeConfigFormUpyunFileConfig from "./DeployNodeConfigFormUpyunFileConfig.tsx";
|
||||
import DeployNodeConfigFormVolcEngineALBConfig from "./DeployNodeConfigFormVolcEngineALBConfig.tsx";
|
||||
@@ -318,6 +319,8 @@ const DeployNodeConfigForm = forwardRef<DeployNodeConfigFormInstance, DeployNode
|
||||
return <DeployNodeConfigFormUCloudUCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.UCLOUD_US3:
|
||||
return <DeployNodeConfigFormUCloudUS3Config {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.UNICLOUD_WEBHOST:
|
||||
return <DeployNodeConfigFormUniCloudWebHostConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.UPYUN_CDN:
|
||||
return <DeployNodeConfigFormUpyunCDNConfig {...nestedFormProps} />;
|
||||
case DEPLOYMENT_PROVIDERS.UPYUN_FILE:
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import { memo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons";
|
||||
import { Alert, Button, Form, type FormInstance, Input, Space } from "antd";
|
||||
import { Alert, Form, type FormInstance, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import ModalForm from "@/components/ModalForm";
|
||||
import MultipleInput from "@/components/MultipleInput";
|
||||
import { useAntdForm } from "@/hooks";
|
||||
import MultipleSplitValueInput from "@/components/MultipleSplitValueInput";
|
||||
|
||||
type DeployNodeConfigFormAliyunCASDeployConfigFieldValues = Nullish<{
|
||||
region: string;
|
||||
@@ -61,9 +57,6 @@ const DeployNodeConfigFormAliyunCASDeployConfig = ({
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const fieldResourceIds = Form.useWatch<string>("resourceIds", formInst);
|
||||
const fieldContactIds = Form.useWatch<string>("contactIds", formInst);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
@@ -87,69 +80,31 @@ const DeployNodeConfigFormAliyunCASDeployConfig = ({
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="resourceIds"
|
||||
label={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.tooltip") }}></span>}
|
||||
>
|
||||
<Space.Compact style={{ width: "100%" }}>
|
||||
<Form.Item name="resourceIds" noStyle rules={[formRule]}>
|
||||
<Input
|
||||
allowClear
|
||||
disabled={disabled}
|
||||
value={fieldResourceIds}
|
||||
placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.placeholder")}
|
||||
onChange={(e) => {
|
||||
formInst.setFieldValue("resourceIds", e.target.value);
|
||||
}}
|
||||
onClear={() => {
|
||||
formInst.setFieldValue("resourceIds", "");
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<ResourceIdsModalInput
|
||||
value={fieldResourceIds}
|
||||
trigger={
|
||||
<Button disabled={disabled}>
|
||||
<FormOutlinedIcon />
|
||||
</Button>
|
||||
}
|
||||
onChange={(value) => {
|
||||
formInst.setFieldValue("resourceIds", value);
|
||||
}}
|
||||
/>
|
||||
</Space.Compact>
|
||||
<MultipleSplitValueInput
|
||||
modalTitle={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.title")}
|
||||
placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.placeholder")}
|
||||
placeholderInModal={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.placeholder")}
|
||||
splitOptions={{ trim: true, removeEmpty: true }}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="contactIds"
|
||||
label={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.tooltip") }}></span>}
|
||||
>
|
||||
<Space.Compact style={{ width: "100%" }}>
|
||||
<Form.Item name="contactIds" noStyle rules={[formRule]}>
|
||||
<Input
|
||||
allowClear
|
||||
disabled={disabled}
|
||||
value={fieldContactIds}
|
||||
placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.placeholder")}
|
||||
onChange={(e) => {
|
||||
formInst.setFieldValue("contactIds", e.target.value);
|
||||
}}
|
||||
onClear={() => {
|
||||
formInst.setFieldValue("contactIds", "");
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<ContactIdsModalInput
|
||||
value={fieldContactIds}
|
||||
trigger={
|
||||
<Button disabled={disabled}>
|
||||
<FormOutlinedIcon />
|
||||
</Button>
|
||||
}
|
||||
onChange={(value) => {
|
||||
formInst.setFieldValue("contactIds", value);
|
||||
}}
|
||||
/>
|
||||
</Space.Compact>
|
||||
<MultipleSplitValueInput
|
||||
modalTitle={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.title")}
|
||||
placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.placeholder")}
|
||||
placeholderInModal={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.placeholder")}
|
||||
splitOptions={{ trim: true, removeEmpty: true }}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
@@ -159,84 +114,4 @@ const DeployNodeConfigFormAliyunCASDeployConfig = ({
|
||||
);
|
||||
};
|
||||
|
||||
const ResourceIdsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
resourceIds: z.array(z.string()).refine((v) => {
|
||||
return v.every((e) => !e?.trim() || /^[1-9]\d*$/.test(e));
|
||||
}, t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.errmsg.invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const { form: formInst, formProps } = useAntdForm({
|
||||
name: "workflowNodeDeployConfigFormAliyunCASResourceIdsModalInput",
|
||||
initialValues: { resourceIds: value?.split(MULTIPLE_INPUT_DELIMITER) },
|
||||
onSubmit: (values) => {
|
||||
onChange?.(
|
||||
values.resourceIds
|
||||
.map((e) => e.trim())
|
||||
.filter((e) => !!e)
|
||||
.join(MULTIPLE_INPUT_DELIMITER)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<ModalForm
|
||||
{...formProps}
|
||||
layout="vertical"
|
||||
form={formInst}
|
||||
modalProps={{ destroyOnHidden: true }}
|
||||
title={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
width={480}
|
||||
>
|
||||
<Form.Item name="resourceIds" rules={[formRule]}>
|
||||
<MultipleInput placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_resource_ids.multiple_input_modal.placeholder")} />
|
||||
</Form.Item>
|
||||
</ModalForm>
|
||||
);
|
||||
});
|
||||
|
||||
const ContactIdsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
contactIds: z.array(z.string()).refine((v) => {
|
||||
return v.every((e) => !e?.trim() || /^[1-9]\d*$/.test(e));
|
||||
}, t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.errmsg.invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const { form: formInst, formProps } = useAntdForm({
|
||||
name: "workflowNodeDeployConfigFormAliyunCASDeploymentJobContactIdsModalInput",
|
||||
initialValues: { contactIds: value?.split(MULTIPLE_INPUT_DELIMITER) },
|
||||
onSubmit: (values) => {
|
||||
onChange?.(
|
||||
values.contactIds
|
||||
.map((e) => e.trim())
|
||||
.filter((e) => !!e)
|
||||
.join(MULTIPLE_INPUT_DELIMITER)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<ModalForm
|
||||
{...formProps}
|
||||
layout="vertical"
|
||||
form={formInst}
|
||||
modalProps={{ destroyOnHidden: true }}
|
||||
title={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
width={480}
|
||||
>
|
||||
<Form.Item name="contactIds" rules={[formRule]}>
|
||||
<MultipleInput placeholder={t("workflow_node.deploy.form.aliyun_cas_deploy_contact_ids.multiple_input_modal.placeholder")} />
|
||||
</Form.Item>
|
||||
</ModalForm>
|
||||
);
|
||||
});
|
||||
|
||||
export default DeployNodeConfigFormAliyunCASDeployConfig;
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
import { memo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons";
|
||||
import { Button, Form, type FormInstance, Input, Select, Space } from "antd";
|
||||
import { Form, type FormInstance, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import ModalForm from "@/components/ModalForm";
|
||||
import MultipleInput from "@/components/MultipleInput";
|
||||
import MultipleSplitValueInput from "@/components/MultipleSplitValueInput";
|
||||
import Show from "@/components/Show";
|
||||
import { useAntdForm } from "@/hooks";
|
||||
|
||||
type DeployNodeConfigFormBaotaPanelSiteConfigFieldValues = Nullish<{
|
||||
siteType: string;
|
||||
@@ -71,7 +67,6 @@ const DeployNodeConfigFormBaotaPanelSiteConfig = ({
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const fieldSiteType = Form.useWatch<string>("siteType", formInst);
|
||||
const fieldSiteNames = Form.useWatch<string>("siteNames", formInst);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
@@ -110,80 +105,21 @@ const DeployNodeConfigFormBaotaPanelSiteConfig = ({
|
||||
|
||||
<Show when={fieldSiteType === SITE_TYPE_OTHER}>
|
||||
<Form.Item
|
||||
name="siteNames"
|
||||
label={t("workflow_node.deploy.form.baotapanel_site_names.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.baotapanel_site_names.tooltip") }}></span>}
|
||||
>
|
||||
<Space.Compact style={{ width: "100%" }}>
|
||||
<Form.Item name="siteNames" noStyle rules={[formRule]}>
|
||||
<Input
|
||||
allowClear
|
||||
disabled={disabled}
|
||||
value={fieldSiteNames}
|
||||
placeholder={t("workflow_node.deploy.form.baotapanel_site_names.placeholder")}
|
||||
onChange={(e) => {
|
||||
formInst.setFieldValue("siteNames", e.target.value);
|
||||
}}
|
||||
onClear={() => {
|
||||
formInst.setFieldValue("siteNames", "");
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<SiteNamesModalInput
|
||||
value={fieldSiteNames}
|
||||
trigger={
|
||||
<Button disabled={disabled}>
|
||||
<FormOutlinedIcon />
|
||||
</Button>
|
||||
}
|
||||
onChange={(value) => {
|
||||
formInst.setFieldValue("siteNames", value);
|
||||
}}
|
||||
/>
|
||||
</Space.Compact>
|
||||
<MultipleSplitValueInput
|
||||
modalTitle={t("workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.title")}
|
||||
placeholder={t("workflow_node.deploy.form.baotapanel_site_names.placeholder")}
|
||||
placeholderInModal={t("workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.placeholder")}
|
||||
splitOptions={{ trim: true, removeEmpty: true }}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Show>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
const SiteNamesModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
siteNames: z.array(z.string()).refine((v) => {
|
||||
return v.every((e) => !!e?.trim());
|
||||
}, t("workflow_node.deploy.form.baotapanel_site_names.errmsg.invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const { form: formInst, formProps } = useAntdForm({
|
||||
name: "workflowNodeDeployConfigFormBaotaPanelSiteNamesModalInput",
|
||||
initialValues: { siteNames: value?.split(MULTIPLE_INPUT_DELIMITER) },
|
||||
onSubmit: (values) => {
|
||||
onChange?.(
|
||||
values.siteNames
|
||||
.map((e) => e.trim())
|
||||
.filter((e) => !!e)
|
||||
.join(MULTIPLE_INPUT_DELIMITER)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<ModalForm
|
||||
{...formProps}
|
||||
layout="vertical"
|
||||
form={formInst}
|
||||
modalProps={{ destroyOnHidden: true }}
|
||||
title={t("workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
width={480}
|
||||
>
|
||||
<Form.Item name="siteNames" rules={[formRule]}>
|
||||
<MultipleInput placeholder={t("workflow_node.deploy.form.baotapanel_site_names.multiple_input_modal.placeholder")} />
|
||||
</Form.Item>
|
||||
</ModalForm>
|
||||
);
|
||||
});
|
||||
|
||||
export default DeployNodeConfigFormBaotaPanelSiteConfig;
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import { memo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons";
|
||||
import { Alert, AutoComplete, Button, Form, type FormInstance, Input, Space } from "antd";
|
||||
import { Alert, AutoComplete, Form, type FormInstance, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import ModalForm from "@/components/ModalForm";
|
||||
import MultipleInput from "@/components/MultipleInput";
|
||||
import { useAntdForm } from "@/hooks";
|
||||
import MultipleSplitValueInput from "@/components/MultipleSplitValueInput";
|
||||
|
||||
type DeployNodeConfigFormTencentCloudSSLDeployConfigFieldValues = Nullish<{
|
||||
region: string;
|
||||
@@ -56,8 +52,6 @@ const DeployNodeConfigFormTencentCloudSSLDeployConfig = ({
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const fieldResourceIds = Form.useWatch<string>("resourceIds", formInst);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
@@ -94,36 +88,17 @@ const DeployNodeConfigFormTencentCloudSSLDeployConfig = ({
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="resourceIds"
|
||||
label={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.tooltip") }}></span>}
|
||||
>
|
||||
<Space.Compact style={{ width: "100%" }}>
|
||||
<Form.Item name="resourceIds" noStyle rules={[formRule]}>
|
||||
<Input
|
||||
allowClear
|
||||
disabled={disabled}
|
||||
value={fieldResourceIds}
|
||||
placeholder={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.placeholder")}
|
||||
onChange={(e) => {
|
||||
formInst.setFieldValue("resourceIds", e.target.value);
|
||||
}}
|
||||
onClear={() => {
|
||||
formInst.setFieldValue("resourceIds", "");
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<ResourceIdsModalInput
|
||||
value={fieldResourceIds}
|
||||
trigger={
|
||||
<Button disabled={disabled}>
|
||||
<FormOutlinedIcon />
|
||||
</Button>
|
||||
}
|
||||
onChange={(value) => {
|
||||
formInst.setFieldValue("resourceIds", value);
|
||||
}}
|
||||
/>
|
||||
</Space.Compact>
|
||||
<MultipleSplitValueInput
|
||||
modalTitle={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.title")}
|
||||
placeholder={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.placeholder")}
|
||||
placeholderInModal={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.placeholder")}
|
||||
splitOptions={{ trim: true, removeEmpty: true }}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
@@ -133,44 +108,4 @@ const DeployNodeConfigFormTencentCloudSSLDeployConfig = ({
|
||||
);
|
||||
};
|
||||
|
||||
const ResourceIdsModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
resourceIds: z.array(z.string()).refine((v) => {
|
||||
return v.every((e) => !e?.trim() || /^[A-Za-z0-9*._-|]+$/.test(e));
|
||||
}, t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.errmsg.invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const { form: formInst, formProps } = useAntdForm({
|
||||
name: "workflowNodeDeployConfigFormTencentCloudSSLDeployResourceIdsModalInput",
|
||||
initialValues: { resourceIds: value?.split(MULTIPLE_INPUT_DELIMITER) },
|
||||
onSubmit: (values) => {
|
||||
onChange?.(
|
||||
values.resourceIds
|
||||
.map((e) => e.trim())
|
||||
.filter((e) => !!e)
|
||||
.join(MULTIPLE_INPUT_DELIMITER)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<ModalForm
|
||||
{...formProps}
|
||||
layout="vertical"
|
||||
form={formInst}
|
||||
modalProps={{ destroyOnHidden: true }}
|
||||
title={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
width={480}
|
||||
>
|
||||
<Form.Item name="resourceIds" rules={[formRule]}>
|
||||
<MultipleInput placeholder={t("workflow_node.deploy.form.tencentcloud_ssl_deploy_resource_ids.multiple_input_modal.placeholder")} />
|
||||
</Form.Item>
|
||||
</ModalForm>
|
||||
);
|
||||
});
|
||||
|
||||
export default DeployNodeConfigFormTencentCloudSSLDeployConfig;
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
type DeployNodeConfigFormUniCloudWebHostConfigFieldValues = Nullish<{
|
||||
spaceProvider: string;
|
||||
spaceId: string;
|
||||
domain: string;
|
||||
}>;
|
||||
|
||||
export type DeployNodeConfigFormUniCloudWebHostConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: DeployNodeConfigFormUniCloudWebHostConfigFieldValues;
|
||||
onValuesChange?: (values: DeployNodeConfigFormUniCloudWebHostConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const initFormModel = (): DeployNodeConfigFormUniCloudWebHostConfigFieldValues => {
|
||||
return {
|
||||
spaceProvider: "tencent",
|
||||
spaceId: "",
|
||||
domain: "",
|
||||
};
|
||||
};
|
||||
|
||||
const DeployNodeConfigFormUniCloudWebHostConfig = ({
|
||||
form: formInst,
|
||||
formName,
|
||||
disabled,
|
||||
initialValues,
|
||||
onValuesChange,
|
||||
}: DeployNodeConfigFormUniCloudWebHostConfigProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
spaceProvider: z.string().trim().nonempty(t("workflow_node.deploy.form.unicloud_webhost_space_provider.placeholder")),
|
||||
spaceId: z.string().trim().nonempty(t("workflow_node.deploy.form.unicloud_webhost_space_id.placeholder")),
|
||||
domain: z.string().refine((v) => validDomainName(v), t("common.errmsg.domain_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="spaceProvider" label={t("workflow_node.deploy.form.unicloud_webhost_space_provider.label")} rules={[formRule]}>
|
||||
<Select
|
||||
options={["aliyun", "tencent"].map((s) => ({
|
||||
label: t(`workflow_node.deploy.form.unicloud_webhost_space_provider.option.${s}.label`),
|
||||
value: s,
|
||||
}))}
|
||||
placeholder={t("workflow_node.deploy.form.unicloud_webhost_space_provider.placeholder")}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="spaceId"
|
||||
label={t("workflow_node.deploy.form.unicloud_webhost_space_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.unicloud_webhost_space_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.unicloud_webhost_space_id.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="domain" label={t("workflow_node.deploy.form.unicloud_webhost_domain.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("workflow_node.deploy.form.unicloud_webhost_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeConfigFormUniCloudWebHostConfig;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input } from "antd";
|
||||
import { Alert, Form, type FormInstance, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -44,6 +44,10 @@ const DeployNodeConfigFormUpyunCDNConfig = ({ form: formInst, formName, disabled
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item>
|
||||
<Alert type="info" message={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.upyun_cdn.guide") }}></span>} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.upyun_cdn_domain.label")}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input } from "antd";
|
||||
import { Alert, Form, type FormInstance, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
@@ -50,6 +50,10 @@ const DeployNodeConfigFormUpyunFileConfig = ({
|
||||
name={formName}
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item>
|
||||
<Alert type="info" message={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.upyun_file.guide") }}></span>} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.upyun_file_domain.label")}
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import { memo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FormOutlined as FormOutlinedIcon } from "@ant-design/icons";
|
||||
import { Button, Form, type FormInstance, Input, Space } from "antd";
|
||||
import { Form, type FormInstance } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import ModalForm from "@/components/ModalForm";
|
||||
import MultipleInput from "@/components/MultipleInput";
|
||||
import { useAntdForm } from "@/hooks";
|
||||
import MultipleSplitValueInput from "@/components/MultipleSplitValueInput";
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
type DeployNodeConfigFormWangsuCDNConfigFieldValues = Nullish<{
|
||||
@@ -52,8 +48,6 @@ const DeployNodeConfigFormWangsuCDNConfig = ({
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
const fieldDomains = Form.useWatch<string>("domains", formInst);
|
||||
|
||||
const handleFormChange = (_: unknown, values: z.infer<typeof formSchema>) => {
|
||||
onValuesChange?.(values);
|
||||
};
|
||||
@@ -68,79 +62,20 @@ const DeployNodeConfigFormWangsuCDNConfig = ({
|
||||
onValuesChange={handleFormChange}
|
||||
>
|
||||
<Form.Item
|
||||
name="domains"
|
||||
label={t("workflow_node.deploy.form.wangsu_cdn_domains.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.wangsu_cdn_domains.tooltip") }}></span>}
|
||||
>
|
||||
<Space.Compact style={{ width: "100%" }}>
|
||||
<Form.Item name="domains" noStyle rules={[formRule]}>
|
||||
<Input
|
||||
allowClear
|
||||
disabled={disabled}
|
||||
value={fieldDomains}
|
||||
placeholder={t("workflow_node.deploy.form.wangsu_cdn_domains.placeholder")}
|
||||
onChange={(e) => {
|
||||
formInst.setFieldValue("domains", e.target.value);
|
||||
}}
|
||||
onClear={() => {
|
||||
formInst.setFieldValue("domains", "");
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<SiteNamesModalInput
|
||||
value={fieldDomains}
|
||||
trigger={
|
||||
<Button disabled={disabled}>
|
||||
<FormOutlinedIcon />
|
||||
</Button>
|
||||
}
|
||||
onChange={(value) => {
|
||||
formInst.setFieldValue("domains", value);
|
||||
}}
|
||||
/>
|
||||
</Space.Compact>
|
||||
<MultipleSplitValueInput
|
||||
modalTitle={t("workflow_node.deploy.form.wangsu_cdn_domains.multiple_input_modal.title")}
|
||||
placeholder={t("workflow_node.deploy.form.wangsu_cdn_domains.placeholder")}
|
||||
placeholderInModal={t("workflow_node.deploy.form.wangsu_cdn_domains.multiple_input_modal.placeholder")}
|
||||
splitOptions={{ trim: true, removeEmpty: true }}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
const SiteNamesModalInput = memo(({ value, trigger, onChange }: { value?: string; trigger?: React.ReactNode; onChange?: (value: string) => void }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
domains: z.array(z.string()).refine((v) => {
|
||||
return v.every((e) => validDomainName(e));
|
||||
}, t("workflow_node.deploy.form.wangsu_cdn_domains.errmsg.invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const { form: formInst, formProps } = useAntdForm({
|
||||
name: "workflowNodeDeployConfigFormWangsuCDNNamesModalInput",
|
||||
initialValues: { domains: value?.split(MULTIPLE_INPUT_DELIMITER) },
|
||||
onSubmit: (values) => {
|
||||
onChange?.(
|
||||
values.domains
|
||||
.map((e) => e.trim())
|
||||
.filter((e) => !!e)
|
||||
.join(MULTIPLE_INPUT_DELIMITER)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<ModalForm
|
||||
{...formProps}
|
||||
layout="vertical"
|
||||
form={formInst}
|
||||
modalProps={{ destroyOnHidden: true }}
|
||||
title={t("workflow_node.deploy.form.wangsu_cdn_domains.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
width={480}
|
||||
>
|
||||
<Form.Item name="domains" rules={[formRule]}>
|
||||
<MultipleInput placeholder={t("workflow_node.deploy.form.wangsu_cdn_domains.multiple_input_modal.placeholder")} />
|
||||
</Form.Item>
|
||||
</ModalForm>
|
||||
);
|
||||
});
|
||||
|
||||
export default DeployNodeConfigFormWangsuCDNConfig;
|
||||
|
||||
@@ -17,8 +17,10 @@ import { useAntdForm, useAntdFormName, useZustandShallowSelector } from "@/hooks
|
||||
import { useAccessesStore } from "@/stores/access";
|
||||
import { useNotifyChannelsStore } from "@/stores/notify";
|
||||
|
||||
import NotifyNodeConfigFormDiscordBotConfig from "./NotifyNodeConfigFormDiscordBotConfig";
|
||||
import NotifyNodeConfigFormEmailConfig from "./NotifyNodeConfigFormEmailConfig";
|
||||
import NotifyNodeConfigFormMattermostConfig from "./NotifyNodeConfigFormMattermostConfig";
|
||||
import NotifyNodeConfigFormSlackBotConfig from "./NotifyNodeConfigFormSlackBotConfig";
|
||||
import NotifyNodeConfigFormTelegramBotConfig from "./NotifyNodeConfigFormTelegramBotConfig";
|
||||
import NotifyNodeConfigFormWebhookConfig from "./NotifyNodeConfigFormWebhookConfig";
|
||||
|
||||
@@ -110,10 +112,14 @@ const NotifyNodeConfigForm = forwardRef<NotifyNodeConfigFormInstance, NotifyNode
|
||||
NOTICE: If you add new child component, please keep ASCII order.
|
||||
*/
|
||||
switch (fieldProvider) {
|
||||
case NOTIFICATION_PROVIDERS.DISCORDBOT:
|
||||
return <NotifyNodeConfigFormDiscordBotConfig {...nestedFormProps} />;
|
||||
case NOTIFICATION_PROVIDERS.EMAIL:
|
||||
return <NotifyNodeConfigFormEmailConfig {...nestedFormProps} />;
|
||||
case NOTIFICATION_PROVIDERS.MATTERMOST:
|
||||
return <NotifyNodeConfigFormMattermostConfig {...nestedFormProps} />;
|
||||
case NOTIFICATION_PROVIDERS.SLACKBOT:
|
||||
return <NotifyNodeConfigFormSlackBotConfig {...nestedFormProps} />;
|
||||
case NOTIFICATION_PROVIDERS.TELEGRAMBOT:
|
||||
return <NotifyNodeConfigFormTelegramBotConfig {...nestedFormProps} />;
|
||||
case NOTIFICATION_PROVIDERS.WEBHOOK:
|
||||
|
||||
@@ -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 NotifyNodeConfigFormDiscordBotConfigFieldValues = Nullish<{
|
||||
channelId?: string;
|
||||
}>;
|
||||
|
||||
export type NotifyNodeConfigFormDiscordBotConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: NotifyNodeConfigFormDiscordBotConfigFieldValues;
|
||||
onValuesChange?: (values: NotifyNodeConfigFormDiscordBotConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const initFormModel = (): NotifyNodeConfigFormDiscordBotConfigFieldValues => {
|
||||
return {};
|
||||
};
|
||||
|
||||
const NotifyNodeConfigFormDiscordBotConfig = ({
|
||||
form: formInst,
|
||||
formName,
|
||||
disabled,
|
||||
initialValues,
|
||||
onValuesChange,
|
||||
}: NotifyNodeConfigFormDiscordBotConfigProps) => {
|
||||
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.discordbot_channel_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.notify.form.discordbot_channel_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input allowClear placeholder={t("workflow_node.notify.form.discordbot_channel_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotifyNodeConfigFormDiscordBotConfig;
|
||||
@@ -0,0 +1,55 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, type FormInstance, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
type NotifyNodeConfigFormSlackBotConfigFieldValues = Nullish<{
|
||||
channelId?: string;
|
||||
}>;
|
||||
|
||||
export type NotifyNodeConfigFormSlackBotConfigProps = {
|
||||
form: FormInstance;
|
||||
formName: string;
|
||||
disabled?: boolean;
|
||||
initialValues?: NotifyNodeConfigFormSlackBotConfigFieldValues;
|
||||
onValuesChange?: (values: NotifyNodeConfigFormSlackBotConfigFieldValues) => void;
|
||||
};
|
||||
|
||||
const initFormModel = (): NotifyNodeConfigFormSlackBotConfigFieldValues => {
|
||||
return {};
|
||||
};
|
||||
|
||||
const NotifyNodeConfigFormSlackBotConfig = ({ form: formInst, formName, disabled, initialValues, onValuesChange }: NotifyNodeConfigFormSlackBotConfigProps) => {
|
||||
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.slackbot_channel_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.notify.form.slackbot_channel_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input allowClear placeholder={t("workflow_node.notify.form.slackbot_channel_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default NotifyNodeConfigFormSlackBotConfig;
|
||||
@@ -38,7 +38,7 @@ const NotifyNodeConfigFormTelegramBotConfig = ({
|
||||
.refine((v) => {
|
||||
if (v == null || v + "" === "") return true;
|
||||
return !Number.isNaN(+v!) && +v! !== 0;
|
||||
}, t("workflow_node.notify.form.telegram_bot_chat_id.placeholder"))
|
||||
}, t("workflow_node.notify.form.telegrambot_chat_id.placeholder"))
|
||||
)
|
||||
.nullish(),
|
||||
});
|
||||
@@ -59,11 +59,11 @@ const NotifyNodeConfigFormTelegramBotConfig = ({
|
||||
>
|
||||
<Form.Item
|
||||
name="chatId"
|
||||
label={t("workflow_node.notify.form.telegram_bot_chat_id.label")}
|
||||
label={t("workflow_node.notify.form.telegrambot_chat_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.notify.form.telegram_bot_chat_id.tooltip") }}></span>}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.notify.form.telegrambot_chat_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input allowClear placeholder={t("workflow_node.notify.form.telegram_bot_chat_id.placeholder")} />
|
||||
<Input allowClear placeholder={t("workflow_node.notify.form.telegrambot_chat_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { memo, useRef } from "react";
|
||||
import { memo, useMemo, useRef } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import {
|
||||
CloseCircleOutlined as CloseCircleOutlinedIcon,
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
MoreOutlined as MoreOutlinedIcon,
|
||||
} from "@ant-design/icons";
|
||||
import { useControllableValue } from "ahooks";
|
||||
import { Button, Card, Drawer, Dropdown, Input, type InputRef, Modal, Popover, Space } from "antd";
|
||||
import { Button, Card, Drawer, Dropdown, Input, type InputRef, type MenuProps, Modal, Popover, Space } from "antd";
|
||||
import { produce } from "immer";
|
||||
import { isEqual } from "radash";
|
||||
|
||||
@@ -59,12 +59,13 @@ const SharedNodeTitle = ({ className, style, node, disabled }: SharedNodeTitlePr
|
||||
type SharedNodeMenuProps = SharedNodeProps & {
|
||||
branchId?: string;
|
||||
branchIndex?: number;
|
||||
menus?: Array<"rename" | "duplicate" | "remove">;
|
||||
trigger: React.ReactNode;
|
||||
afterUpdate?: () => void;
|
||||
afterDelete?: () => void;
|
||||
};
|
||||
|
||||
const isBranchingNode = (node: WorkflowNode) => {
|
||||
const isNodeBranchLike = (node: WorkflowNode) => {
|
||||
return (
|
||||
node.type === WorkflowNodeType.Branch ||
|
||||
node.type === WorkflowNodeType.Condition ||
|
||||
@@ -74,7 +75,11 @@ const isBranchingNode = (node: WorkflowNode) => {
|
||||
);
|
||||
};
|
||||
|
||||
const SharedNodeMenu = ({ trigger, node, disabled, branchId, branchIndex, afterUpdate, afterDelete }: SharedNodeMenuProps) => {
|
||||
const isNodeReadOnly = (node: WorkflowNode) => {
|
||||
return node.type === WorkflowNodeType.Start || node.type === WorkflowNodeType.End;
|
||||
};
|
||||
|
||||
const SharedNodeMenu = ({ menus, trigger, node, disabled, branchId, branchIndex, afterUpdate, afterDelete }: SharedNodeMenuProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { updateNode, removeNode, removeBranch } = useWorkflowStore(useZustandShallowSelector(["updateNode", "removeNode", "removeBranch"]));
|
||||
@@ -101,7 +106,7 @@ const SharedNodeMenu = ({ trigger, node, disabled, branchId, branchIndex, afterU
|
||||
};
|
||||
|
||||
const handleDeleteClick = async () => {
|
||||
if (isBranchingNode(node)) {
|
||||
if (isNodeBranchLike(node)) {
|
||||
await removeBranch(branchId!, branchIndex!);
|
||||
} else {
|
||||
await removeNode(node.id);
|
||||
@@ -110,56 +115,76 @@ const SharedNodeMenu = ({ trigger, node, disabled, branchId, branchIndex, afterU
|
||||
afterDelete?.();
|
||||
};
|
||||
|
||||
const menuItems = useMemo(() => {
|
||||
let temp = [
|
||||
{
|
||||
key: "rename",
|
||||
disabled: disabled,
|
||||
label: isNodeBranchLike(node) ? t("workflow_node.action.rename_branch") : t("workflow_node.action.rename_node"),
|
||||
icon: <FormOutlinedIcon />,
|
||||
onClick: () => {
|
||||
nameRef.current = node.name;
|
||||
|
||||
const dialog = modalApi.confirm({
|
||||
title: isNodeBranchLike(node) ? t("workflow_node.action.rename_branch") : t("workflow_node.action.rename_node"),
|
||||
content: (
|
||||
<div className="pb-2 pt-4">
|
||||
<Input
|
||||
ref={nameInputRef}
|
||||
autoFocus
|
||||
defaultValue={node.name}
|
||||
onChange={(e) => (nameRef.current = e.target.value)}
|
||||
onPressEnter={async () => {
|
||||
await handleRenameConfirm();
|
||||
dialog.destroy();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
icon: null,
|
||||
okText: t("common.button.save"),
|
||||
onOk: handleRenameConfirm,
|
||||
});
|
||||
setTimeout(() => nameInputRef.current?.focus(), 1);
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "divider",
|
||||
},
|
||||
{
|
||||
key: "remove",
|
||||
disabled: disabled || isNodeReadOnly(node),
|
||||
label: isNodeBranchLike(node) ? t("workflow_node.action.remove_branch") : t("workflow_node.action.remove_node"),
|
||||
icon: <CloseCircleOutlinedIcon />,
|
||||
danger: true,
|
||||
onClick: handleDeleteClick,
|
||||
},
|
||||
] satisfies MenuProps["items"];
|
||||
|
||||
if (menus) {
|
||||
temp = temp.filter((item) => item.type === "divider" || menus.includes(item.key as "rename" | "remove"));
|
||||
temp = temp.filter((item, index, array) => {
|
||||
if (item.type !== "divider") return true;
|
||||
return index === 0 || array[index - 1].type !== "divider";
|
||||
});
|
||||
if (temp[0]?.type === "divider") {
|
||||
temp.shift();
|
||||
}
|
||||
if (temp[temp.length - 1]?.type === "divider") {
|
||||
temp.pop();
|
||||
}
|
||||
}
|
||||
|
||||
return temp;
|
||||
}, [disabled, node]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{ModelContextHolder}
|
||||
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: "rename",
|
||||
disabled: disabled,
|
||||
label: isBranchingNode(node) ? t("workflow_node.action.rename_branch") : t("workflow_node.action.rename_node"),
|
||||
icon: <FormOutlinedIcon />,
|
||||
onClick: () => {
|
||||
nameRef.current = node.name;
|
||||
|
||||
const dialog = modalApi.confirm({
|
||||
title: isBranchingNode(node) ? t("workflow_node.action.rename_branch") : t("workflow_node.action.rename_node"),
|
||||
content: (
|
||||
<div className="pb-2 pt-4">
|
||||
<Input
|
||||
ref={nameInputRef}
|
||||
autoFocus
|
||||
defaultValue={node.name}
|
||||
onChange={(e) => (nameRef.current = e.target.value)}
|
||||
onPressEnter={async () => {
|
||||
await handleRenameConfirm();
|
||||
dialog.destroy();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
),
|
||||
icon: null,
|
||||
okText: t("common.button.save"),
|
||||
onOk: handleRenameConfirm,
|
||||
});
|
||||
setTimeout(() => nameInputRef.current?.focus(), 1);
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "divider",
|
||||
},
|
||||
{
|
||||
key: "remove",
|
||||
disabled: disabled || node.type === WorkflowNodeType.Start,
|
||||
label: isBranchingNode(node) ? t("workflow_node.action.remove_branch") : t("workflow_node.action.remove_node"),
|
||||
icon: <CloseCircleOutlinedIcon />,
|
||||
danger: true,
|
||||
onClick: handleDeleteClick,
|
||||
},
|
||||
],
|
||||
items: menuItems,
|
||||
}}
|
||||
trigger={["click"]}
|
||||
>
|
||||
@@ -264,7 +289,6 @@ const SharedNodeConfigDrawer = ({
|
||||
|
||||
const { promise, resolve, reject } = Promise.withResolvers();
|
||||
if (changed) {
|
||||
console.log(oldValues, newValues);
|
||||
modalApi.confirm({
|
||||
title: t("common.text.operation_confirm"),
|
||||
content: t("workflow_node.unsaved_changes.confirm"),
|
||||
@@ -288,6 +312,7 @@ const SharedNodeConfigDrawer = ({
|
||||
destroyOnHidden
|
||||
extra={
|
||||
<SharedNodeMenu
|
||||
menus={["rename", "remove"]}
|
||||
node={node}
|
||||
disabled={disabled}
|
||||
trigger={<Button icon={<EllipsisOutlinedIcon />} type="text" />}
|
||||
|
||||
Reference in New Issue
Block a user