mirror of
https://github.com/woodchen-ink/certimate.git
synced 2025-07-18 09:21:56 +08:00
feat(ui): new DeployNodeForm using antd
This commit is contained in:
parent
cb7a465d6c
commit
6f088fd76a
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
aliyunCdn "github.com/alibabacloud-go/cdn-20180510/v5/client"
|
||||
@ -20,7 +21,7 @@ type AliyunCDNDeployerConfig struct {
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// 阿里云 AccessKeySecret。
|
||||
AccessKeySecret string `json:"accessKeySecret"`
|
||||
// 加速域名(不支持泛域名)。
|
||||
// 加速域名(支持泛域名)。
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
@ -58,10 +59,13 @@ func NewWithLogger(config *AliyunCDNDeployerConfig, logger logger.Logger) (*Aliy
|
||||
}
|
||||
|
||||
func (d *AliyunCDNDeployer) Deploy(ctx context.Context, certPem string, privkeyPem string) (*deployer.DeployResult, error) {
|
||||
// "*.example.com" → ".example.com",适配阿里云 CDN 要求的泛域名格式
|
||||
domain := strings.TrimPrefix(d.config.Domain, "*")
|
||||
|
||||
// 设置 CDN 域名域名证书
|
||||
// REF: https://help.aliyun.com/zh/cdn/developer-reference/api-cdn-2018-05-10-setcdndomainsslcertificate
|
||||
setCdnDomainSSLCertificateReq := &aliyunCdn.SetCdnDomainSSLCertificateRequest{
|
||||
DomainName: tea.String(d.config.Domain),
|
||||
DomainName: tea.String(domain),
|
||||
CertName: tea.String(fmt.Sprintf("certimate-%d", time.Now().UnixMilli())),
|
||||
CertType: tea.String("upload"),
|
||||
SSLProtocol: tea.String("on"),
|
||||
|
@ -19,7 +19,7 @@ type BaiduCloudCDNDeployerConfig struct {
|
||||
AccessKeyId string `json:"accessKeyId"`
|
||||
// 百度智能云 SecretAccessKey。
|
||||
SecretAccessKey string `json:"secretAccessKey"`
|
||||
// 加速域名(不支持泛域名)。
|
||||
// 加速域名(支持泛域名)。
|
||||
Domain string `json:"domain"`
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,7 @@ func (d *WebhookDeployer) Deploy(ctx context.Context, certPem string, privkeyPem
|
||||
return nil, xerrors.Wrap(err, "failed to parse x509")
|
||||
}
|
||||
|
||||
// TODO: 自定义回调数据
|
||||
reqBody, _ := json.Marshal(&webhookData{
|
||||
SubjectAltNames: strings.Join(certX509.DNSNames, ","),
|
||||
Certificate: certPem,
|
||||
|
@ -1,9 +1,8 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { accessProvidersMap } from "@/domain/access";
|
||||
import { accessProvidersMap, deployProvidersMap } from "@/domain/provider";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useAccessStore } from "@/stores/access";
|
||||
import { deployTargetsMap } from "@/domain/domain";
|
||||
|
||||
type AccessSelectProps = {
|
||||
providerType: string;
|
||||
@ -24,8 +23,7 @@ const AccessSelect = ({ value, onValueChange, providerType }: AccessSelectProps)
|
||||
}, [value]);
|
||||
|
||||
const targetAccesses = accesses.filter((item) => {
|
||||
console.log(item, providerType);
|
||||
return item.configType === deployTargetsMap.get(providerType)?.provider;
|
||||
return item.configType === deployProvidersMap.get(providerType)?.provider;
|
||||
});
|
||||
|
||||
return (
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Dropdown } from "antd";
|
||||
import { Plus as PlusIcon } from "lucide-react";
|
||||
import { PlusOutlined as PlusOutlinedIcon } from "@ant-design/icons";
|
||||
|
||||
import { useZustandShallowSelector } from "@/hooks";
|
||||
import { newWorkflowNode, workflowNodeDropdownList, WorkflowNodeType } from "@/domain/workflow";
|
||||
@ -22,7 +22,7 @@ const AddNode = ({ data }: NodeProps | BrandNodeProps) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="before:content-[''] before:w-[2px] before:bg-stone-200 before:absolute before:h-full before:left-[50%] before:-translate-x-[50%] before:top-0 pt-6 pb-9 relative flex flex-col items-center">
|
||||
<div className="before:content-[''] before:w-[2px] before:bg-stone-200 before:absolute before:h-full before:left-[50%] before:-translate-x-[50%] before:top-0 py-6 relative">
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: workflowNodeDropdownList.map((item) => {
|
||||
@ -56,8 +56,8 @@ const AddNode = ({ data }: NodeProps | BrandNodeProps) => {
|
||||
}}
|
||||
trigger={["click"]}
|
||||
>
|
||||
<div className="bg-stone-400 hover:bg-stone-500 rounded-full z-10 relative outline-none">
|
||||
<PlusIcon className="text-white" size={18} />
|
||||
<div className="bg-stone-400 hover:bg-stone-500 rounded-full size-5 z-[1] relative flex items-center justify-center cursor-pointer">
|
||||
<PlusOutlinedIcon className="text-white" />
|
||||
</div>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
@ -32,7 +32,7 @@ const BranchNode = memo(({ data }: BrandNodeProps) => {
|
||||
}}
|
||||
size={"sm"}
|
||||
variant={"outline"}
|
||||
className="text-xs px-2 h-6 rounded-full absolute -top-3 left-[50%] -translate-x-1/2 z-10 dark:text-stone-200"
|
||||
className="text-xs px-2 h-6 rounded-full absolute -top-3 left-[50%] -translate-x-1/2 z-[1] dark:text-stone-200"
|
||||
>
|
||||
{t("workflow.node.addBranch.label")}
|
||||
</Button>
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { useWorkflowStore } from "@/stores/workflow";
|
||||
import AddNode from "./AddNode";
|
||||
import { NodeProps } from "./types";
|
||||
import { useZustandShallowSelector } from "@/hooks";
|
||||
import { Dropdown } from "antd";
|
||||
import { Ellipsis, Trash2 } from "lucide-react";
|
||||
import { DeleteOutlined as DeleteOutlinedIcon, EllipsisOutlined as EllipsisOutlinedIcon } from "@ant-design/icons";
|
||||
|
||||
import AddNode from "./AddNode";
|
||||
import { useZustandShallowSelector } from "@/hooks";
|
||||
import { useWorkflowStore } from "@/stores/workflow";
|
||||
import { type NodeProps } from "./types";
|
||||
|
||||
const ConditionNode = ({ data, branchId, branchIndex }: NodeProps) => {
|
||||
const { updateNode, removeBranch } = useWorkflowStore(useZustandShallowSelector(["updateNode", "removeBranch"]));
|
||||
@ -12,14 +13,14 @@ const ConditionNode = ({ data, branchId, branchIndex }: NodeProps) => {
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<div className="rounded-md shadow-md w-[261px] mt-10 relative z-10">
|
||||
<div className="rounded-md shadow-md w-[261px] mt-10 relative z-[1]">
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: "delete",
|
||||
label: "删除分支",
|
||||
icon: <Trash2 size={16} />,
|
||||
icon: <DeleteOutlinedIcon />,
|
||||
danger: true,
|
||||
onClick: () => {
|
||||
removeBranch(branchId ?? "", branchIndex ?? 0);
|
||||
@ -30,7 +31,7 @@ const ConditionNode = ({ data, branchId, branchIndex }: NodeProps) => {
|
||||
trigger={["click"]}
|
||||
>
|
||||
<div className="absolute right-2 top-1 cursor-pointer">
|
||||
<Ellipsis size={17} className="text-stone-600" />
|
||||
<EllipsisOutlinedIcon size={17} className="text-stone-600" />
|
||||
</div>
|
||||
</Dropdown>
|
||||
|
||||
|
@ -1,31 +1,33 @@
|
||||
import { WorkflowNode } from "@/domain/workflow";
|
||||
import { memo } from "react";
|
||||
import DeployToAliyunOSS from "./DeployToAliyunOss";
|
||||
|
||||
import { type WorkflowNode } from "@/domain/workflow";
|
||||
import DeployToAliyunALB from "./DeployToAliyunALB";
|
||||
import DeployToAliyunCDN from "./DeployToAliyunCDN";
|
||||
import DeployToAliyunCLB from "./DeployToAliyunCLB";
|
||||
import DeployToAliyunNLB from "./DeployToAliyunNLB";
|
||||
import DeployToAliyunOSS from "./DeployToAliyunOss";
|
||||
import DeployToBaiduCloudCDN from "./DeployToBaiduCloudCDN";
|
||||
import DeployToBytePlusCDN from "./DeployToByteplusCDN";
|
||||
import DeployToDogeCloudCDN from "./DeployToDogeCloudCDN";
|
||||
import DeployToHuaweiCloudCDN from "./DeployToHuaweiCloudCDN";
|
||||
import DeployToHuaweiCloudELB from "./DeployToHuaweiCloudELB";
|
||||
import DeployToKubernetesSecret from "./DeployToKubernetesSecret";
|
||||
import DeployToLocal from "./DeployToLocal";
|
||||
import DeployToQiniuCDN from "./DeployToQiniuCDN";
|
||||
import DeployToWebhook from "./DeployToWebhook";
|
||||
import DeployToSSH from "./DeployToSSH";
|
||||
import DeployToTencentCDN from "./DeployToTencentCDN";
|
||||
import DeployToTencentCLB from "./DeployToTencentCLB";
|
||||
import DeployToTencentCOS from "./DeployToTencentCOS";
|
||||
import DeployToTencentTEO from "./DeployToTencentTEO";
|
||||
import DeployToSSH from "./DeployToSSH";
|
||||
import DeployToLocal from "./DeployToLocal";
|
||||
import DeployToByteplusCDN from "./DeployToByteplusCDN";
|
||||
import DeployToVolcengineCDN from "./DeployToVolcengineCDN";
|
||||
import DeployToVolcengineLive from "./DeployToVolcengineLive";
|
||||
import DeployToTencentEO from "./DeployToTencentTEO";
|
||||
import DeployToVolcEngineCDN from "./DeployToVolcengineCDN";
|
||||
import DeployToVolcEngineLive from "./DeployToVolcengineLive";
|
||||
import DeployToWebhook from "./DeployToWebhook";
|
||||
|
||||
export type DeployFormProps = {
|
||||
data: WorkflowNode;
|
||||
defaultProivder?: string;
|
||||
};
|
||||
|
||||
const DeployForm = ({ data, defaultProivder }: DeployFormProps) => {
|
||||
return <div className="dark:text-stone-200">{getForm(data, defaultProivder)}</div>;
|
||||
};
|
||||
@ -68,17 +70,17 @@ const getForm = (data: WorkflowNode, defaultProivder?: string) => {
|
||||
case "tencentcloud-cos":
|
||||
return <DeployToTencentCOS data={data} />;
|
||||
case "tencentcloud-eo":
|
||||
return <DeployToTencentTEO data={data} />;
|
||||
return <DeployToTencentEO data={data} />;
|
||||
case "ssh":
|
||||
return <DeployToSSH data={data} />;
|
||||
case "local":
|
||||
return <DeployToLocal data={data} />;
|
||||
case "byteplus-cdn":
|
||||
return <DeployToByteplusCDN data={data} />;
|
||||
return <DeployToBytePlusCDN data={data} />;
|
||||
case "volcengine-cdn":
|
||||
return <DeployToVolcengineCDN data={data} />;
|
||||
return <DeployToVolcEngineCDN data={data} />;
|
||||
case "volcengine-live":
|
||||
return <DeployToVolcengineLive data={data} />;
|
||||
return <DeployToVolcEngineLive data={data} />;
|
||||
default:
|
||||
return <></>;
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
import { WorkflowNode } from "@/domain/workflow";
|
||||
import { memo, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Show from "../Show";
|
||||
import DeployForm from "./DeployForm";
|
||||
import { DeployTarget, deployTargets } from "@/domain/domain";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
import DeployNodeForm from "./node/DeployNodeForm";
|
||||
import { deployProvidersMap } from "@/domain/provider";
|
||||
import { type WorkflowNode } from "@/domain/workflow";
|
||||
|
||||
type DeployPanelBodyProps = {
|
||||
data: WorkflowNode;
|
||||
};
|
||||
|
||||
const DeployPanelBody = ({ data }: DeployPanelBodyProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@ -21,33 +23,22 @@ const DeployPanelBody = ({ data }: DeployPanelBodyProps) => {
|
||||
return (
|
||||
<>
|
||||
{/* 默认展示服务商列表 */}
|
||||
<Show when={!providerType} fallback={<DeployForm data={data} defaultProivder={providerType} />}>
|
||||
<Show when={!providerType} fallback={<DeployNodeForm data={data} defaultProivderType={providerType} />}>
|
||||
<div className="text-lg font-semibold text-gray-700">选择服务商</div>
|
||||
{deployTargets
|
||||
.reduce((acc: DeployTarget[][], provider, index) => {
|
||||
if (index % 2 === 0) {
|
||||
acc.push([provider]);
|
||||
} else {
|
||||
acc[acc.length - 1].push(provider);
|
||||
}
|
||||
return acc;
|
||||
}, [])
|
||||
.map((providerRow, rowIndex) => (
|
||||
<div key={rowIndex} className="flex space-x-5">
|
||||
{providerRow.map((provider, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex space-x-2 w-[47%] items-center cursor-pointer hover:bg-slate-100 p-2 rounded-sm"
|
||||
onClick={() => {
|
||||
setProviderType(provider.type);
|
||||
}}
|
||||
>
|
||||
<img src={provider.icon} alt={provider.type} className="w-8 h-8" />
|
||||
<div className="text-muted-foreground text-sm">{t(provider.name)}</div>
|
||||
</div>
|
||||
))}
|
||||
{Array.from(deployProvidersMap.values()).map((provider, index) => {
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className="flex space-x-2 w-[47%] items-center cursor-pointer hover:bg-slate-100 p-2 rounded-sm"
|
||||
onClick={() => {
|
||||
setProviderType(provider.type);
|
||||
}}
|
||||
>
|
||||
<img src={provider.icon} alt={provider.type} className="w-8 h-8" />
|
||||
<div className="text-muted-foreground text-sm">{t(provider.name)}</div>
|
||||
</div>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</Show>
|
||||
</>
|
||||
);
|
||||
|
@ -1,15 +1,16 @@
|
||||
import { WorkflowNode, WorkflowNodeType } from "@/domain/workflow";
|
||||
import AddNode from "./AddNode";
|
||||
import { useWorkflowStore } from "@/stores/workflow";
|
||||
import { useZustandShallowSelector } from "@/hooks";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Dropdown } from "antd";
|
||||
import { Ellipsis, Trash2 } from "lucide-react";
|
||||
import { DeleteOutlined as DeleteOutlinedIcon, EllipsisOutlined as EllipsisOutlinedIcon } from "@ant-design/icons";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
import AddNode from "./AddNode";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import PanelBody from "./PanelBody";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Show from "../Show";
|
||||
import { deployTargetsMap } from "@/domain/domain";
|
||||
import { useZustandShallowSelector } from "@/hooks";
|
||||
import { deployProvidersMap } from "@/domain/provider";
|
||||
import { notifyChannelsMap } from "@/domain/settings";
|
||||
import { type WorkflowNode, WorkflowNodeType } from "@/domain/workflow";
|
||||
import { useWorkflowStore } from "@/stores/workflow";
|
||||
|
||||
type NodeProps = {
|
||||
data: WorkflowNode;
|
||||
@ -56,7 +57,7 @@ const Node = ({ data }: NodeProps) => {
|
||||
case WorkflowNodeType.Apply:
|
||||
return <div className="text-muted-foreground truncate">{data.config?.domain as string}</div>;
|
||||
case WorkflowNodeType.Deploy: {
|
||||
const provider = deployTargetsMap.get(data.config?.providerType as string);
|
||||
const provider = deployProvidersMap.get(data.config?.providerType as string);
|
||||
return (
|
||||
<div className="flex space-x-2 items-center text-muted-foreground">
|
||||
<img src={provider?.icon} className="w-6 h-6" />
|
||||
@ -90,7 +91,7 @@ const Node = ({ data }: NodeProps) => {
|
||||
{
|
||||
key: "delete",
|
||||
label: t(`${i18nPrefix}.delete.label`),
|
||||
icon: <Trash2 size={16} />,
|
||||
icon: <DeleteOutlinedIcon />,
|
||||
danger: true,
|
||||
onClick: () => {
|
||||
removeNode(data.id);
|
||||
@ -101,7 +102,7 @@ const Node = ({ data }: NodeProps) => {
|
||||
trigger={["click"]}
|
||||
>
|
||||
<div className="absolute right-2 top-1 cursor-pointer">
|
||||
<Ellipsis className="text-white" size={17} />
|
||||
<EllipsisOutlinedIcon className="text-white" size={17} />
|
||||
</div>
|
||||
</Dropdown>
|
||||
</>
|
||||
|
@ -4,6 +4,7 @@ import { useControllableValue } from "ahooks";
|
||||
import { AutoComplete, Button, Divider, Form, Input, Select, Space, Switch, Tooltip, Typography, type AutoCompleteProps } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { FormOutlined as FormOutlinedIcon, PlusOutlined as PlusOutlinedIcon, QuestionCircleOutlined as QuestionCircleOutlinedIcon } from "@ant-design/icons";
|
||||
import { produce } from "immer";
|
||||
import z from "zod";
|
||||
|
||||
import AccessEditModal from "@/components/access/AccessEditModal";
|
||||
@ -12,7 +13,8 @@ import ModalForm from "@/components/core/ModalForm";
|
||||
import MultipleInput from "@/components/core/MultipleInput";
|
||||
import { usePanel } from "../PanelProvider";
|
||||
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
|
||||
import { ACCESS_USAGES, accessProvidersMap } from "@/domain/access";
|
||||
import { ACCESS_USAGES } from "@/domain/access";
|
||||
import { accessProvidersMap } from "@/domain/provider";
|
||||
import { type WorkflowNode, type WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useContactStore } from "@/stores/contact";
|
||||
import { useWorkflowStore } from "@/stores/workflow";
|
||||
@ -42,33 +44,27 @@ const ApplyNodeForm = ({ data }: ApplyNodeFormProps) => {
|
||||
const { hidePanel } = usePanel();
|
||||
|
||||
const formSchema = z.object({
|
||||
domain: z.string({ message: t("workflow.nodes.apply.form.domains.placeholder") }).refine(
|
||||
(v) => {
|
||||
return String(v)
|
||||
.split(MULTIPLE_INPUT_DELIMITER)
|
||||
.every((e) => validDomainName(e, true));
|
||||
},
|
||||
{ message: t("common.errmsg.domain_invalid") }
|
||||
),
|
||||
email: z.string({ message: t("workflow.nodes.apply.form.email.placeholder") }).email("common.errmsg.email_invalid"),
|
||||
access: z.string({ message: t("workflow.nodes.apply.form.access.placeholder") }).min(1, t("workflow.nodes.apply.form.access.placeholder")),
|
||||
domain: z.string({ message: t("workflow_node.apply.form.domains.placeholder") }).refine((v) => {
|
||||
return String(v)
|
||||
.split(MULTIPLE_INPUT_DELIMITER)
|
||||
.every((e) => validDomainName(e, true));
|
||||
}, t("common.errmsg.domain_invalid")),
|
||||
email: z.string({ message: t("workflow_node.apply.form.email.placeholder") }).email("common.errmsg.email_invalid"),
|
||||
access: z.string({ message: t("workflow_node.apply.form.access.placeholder") }).min(1, t("workflow_node.apply.form.access.placeholder")),
|
||||
keyAlgorithm: z.string().nullish(),
|
||||
nameservers: z
|
||||
.string()
|
||||
.refine(
|
||||
(v) => {
|
||||
if (!v) return true;
|
||||
return String(v)
|
||||
.split(MULTIPLE_INPUT_DELIMITER)
|
||||
.every((e) => validIPv4Address(e) || validIPv6Address(e) || validDomainName(e));
|
||||
},
|
||||
{ message: t("common.errmsg.host_invalid") }
|
||||
)
|
||||
.nullish(),
|
||||
.nullish()
|
||||
.refine((v) => {
|
||||
if (!v) return true;
|
||||
return String(v)
|
||||
.split(MULTIPLE_INPUT_DELIMITER)
|
||||
.every((e) => validIPv4Address(e) || validIPv6Address(e) || validDomainName(e));
|
||||
}, t("common.errmsg.host_invalid")),
|
||||
propagationTimeout: z
|
||||
.union([
|
||||
z.number().int().gte(1, t("workflow.nodes.apply.form.propagation_timeout.placeholder")),
|
||||
z.string().refine((v) => !v || (parseInt(v) === +v && +v > 0), { message: t("workflow.nodes.apply.form.propagation_timeout.placeholder") }),
|
||||
z.number().int().gte(1, t("workflow_node.apply.form.propagation_timeout.placeholder")),
|
||||
z.string().refine((v) => !v || /^[1-9]\d*$/.test(v), t("workflow_node.apply.form.propagation_timeout.placeholder")),
|
||||
])
|
||||
.nullish(),
|
||||
disableFollowCNAME: z.boolean().nullish(),
|
||||
@ -81,8 +77,14 @@ const ApplyNodeForm = ({ data }: ApplyNodeFormProps) => {
|
||||
} = useAntdForm<z.infer<typeof formSchema>>({
|
||||
initialValues: data?.config ?? initFormModel(),
|
||||
onSubmit: async (values) => {
|
||||
await updateNode({ ...data, config: { ...values }, validated: true });
|
||||
await formInst.validateFields();
|
||||
await addEmail(values.email);
|
||||
await updateNode(
|
||||
produce(data, (draft) => {
|
||||
draft.config = { ...values };
|
||||
draft.validated = true;
|
||||
})
|
||||
);
|
||||
hidePanel();
|
||||
},
|
||||
});
|
||||
@ -106,15 +108,15 @@ const ApplyNodeForm = ({ data }: ApplyNodeFormProps) => {
|
||||
<Form {...formProps} form={formInst} disabled={formPending} layout="vertical">
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow.nodes.apply.form.domains.label")}
|
||||
label={t("workflow_node.apply.form.domains.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow.nodes.apply.form.domains.tooltip") }}></span>}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.domains.tooltip") }}></span>}
|
||||
>
|
||||
<Space.Compact style={{ width: "100%" }}>
|
||||
<Input
|
||||
disabled={formPending}
|
||||
value={fieldDomains}
|
||||
placeholder={t("workflow.nodes.apply.form.domains.placeholder")}
|
||||
placeholder={t("workflow_node.apply.form.domains.placeholder")}
|
||||
onChange={handleFieldDomainsChange}
|
||||
/>
|
||||
<FormFieldDomainsModalForm
|
||||
@ -134,19 +136,19 @@ const ApplyNodeForm = ({ data }: ApplyNodeFormProps) => {
|
||||
|
||||
<Form.Item
|
||||
name="email"
|
||||
label={t("workflow.nodes.apply.form.email.label")}
|
||||
label={t("workflow_node.apply.form.email.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow.nodes.apply.form.email.tooltip") }}></span>}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.email.tooltip") }}></span>}
|
||||
>
|
||||
<FormFieldEmailSelect placeholder={t("workflow.nodes.apply.form.email.placeholder")} />
|
||||
<FormFieldEmailSelect placeholder={t("workflow_node.apply.form.email.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Form.Item className="mb-0">
|
||||
<label className="block mb-1">
|
||||
<div className="flex items-center justify-between gap-4 w-full">
|
||||
<div className="flex-grow max-w-full truncate">
|
||||
<span>{t("workflow.nodes.apply.form.access.label")}</span>
|
||||
<Tooltip title={t("workflow.nodes.apply.form.access.tooltip")}>
|
||||
<span>{t("workflow_node.apply.form.access.label")}</span>
|
||||
<Tooltip title={t("workflow_node.apply.form.access.tooltip")}>
|
||||
<Typography.Text className="ms-1" type="secondary">
|
||||
<QuestionCircleOutlinedIcon />
|
||||
</Typography.Text>
|
||||
@ -158,7 +160,7 @@ const ApplyNodeForm = ({ data }: ApplyNodeFormProps) => {
|
||||
trigger={
|
||||
<Button size="small" type="link">
|
||||
<PlusOutlinedIcon />
|
||||
{t("workflow.nodes.apply.form.access.button")}
|
||||
{t("workflow_node.apply.form.access.button")}
|
||||
</Button>
|
||||
}
|
||||
onSubmit={(record) => {
|
||||
@ -173,7 +175,7 @@ const ApplyNodeForm = ({ data }: ApplyNodeFormProps) => {
|
||||
</label>
|
||||
<Form.Item name="access" rules={[formRule]}>
|
||||
<AccessSelect
|
||||
placeholder={t("workflow.nodes.apply.form.access.placeholder")}
|
||||
placeholder={t("workflow_node.apply.form.access.placeholder")}
|
||||
filter={(record) => {
|
||||
const provider = accessProvidersMap.get(record.configType);
|
||||
return ACCESS_USAGES.ALL === provider?.usage || ACCESS_USAGES.APPLY === provider?.usage;
|
||||
@ -183,33 +185,33 @@ const ApplyNodeForm = ({ data }: ApplyNodeFormProps) => {
|
||||
</Form.Item>
|
||||
|
||||
<Divider className="my-1">
|
||||
<Typography.Text className="text-xs" type="secondary">
|
||||
{t("workflow.nodes.apply.form.advanced_settings.label")}
|
||||
<Typography.Text className="font-normal text-xs" type="secondary">
|
||||
{t("workflow_node.apply.form.advanced_config.label")}
|
||||
</Typography.Text>
|
||||
</Divider>
|
||||
|
||||
<Form.Item name="keyAlgorithm" label={t("workflow.nodes.apply.form.key_algorithm.label")} rules={[formRule]}>
|
||||
<Form.Item name="keyAlgorithm" label={t("workflow_node.apply.form.key_algorithm.label")} rules={[formRule]}>
|
||||
<Select
|
||||
options={["RSA2048", "RSA3072", "RSA4096", "RSA8192", "EC256", "EC384"].map((e) => ({
|
||||
label: e,
|
||||
value: e,
|
||||
}))}
|
||||
placeholder={t("workflow.nodes.apply.form.key_algorithm.placeholder")}
|
||||
placeholder={t("workflow_node.apply.form.key_algorithm.placeholder")}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="nameservers"
|
||||
label={t("workflow.nodes.apply.form.nameservers.label")}
|
||||
label={t("workflow_node.apply.form.nameservers.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow.nodes.apply.form.nameservers.tooltip") }}></span>}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.nameservers.tooltip") }}></span>}
|
||||
>
|
||||
<Space.Compact style={{ width: "100%" }}>
|
||||
<Input
|
||||
allowClear
|
||||
disabled={formPending}
|
||||
value={fieldNameservers}
|
||||
placeholder={t("workflow.nodes.apply.form.nameservers.placeholder")}
|
||||
placeholder={t("workflow_node.apply.form.nameservers.placeholder")}
|
||||
onChange={handleFieldNameserversChange}
|
||||
/>
|
||||
<FormFieldNameserversModalForm
|
||||
@ -229,25 +231,25 @@ const ApplyNodeForm = ({ data }: ApplyNodeFormProps) => {
|
||||
|
||||
<Form.Item
|
||||
name="propagationTimeout"
|
||||
label={t("workflow.nodes.apply.form.propagation_timeout.label")}
|
||||
label={t("workflow_node.apply.form.propagation_timeout.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow.nodes.apply.form.propagation_timeout.tooltip") }}></span>}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.propagation_timeout.tooltip") }}></span>}
|
||||
>
|
||||
<Input
|
||||
type="number"
|
||||
allowClear
|
||||
min={0}
|
||||
max={3600}
|
||||
placeholder={t("workflow.nodes.apply.form.propagation_timeout.placeholder")}
|
||||
addonAfter={t("workflow.nodes.apply.form.propagation_timeout.suffix")}
|
||||
placeholder={t("workflow_node.apply.form.propagation_timeout.placeholder")}
|
||||
addonAfter={t("workflow_node.apply.form.propagation_timeout.suffix")}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="disableFollowCNAME"
|
||||
label={t("workflow.nodes.apply.form.disable_follow_cname.label")}
|
||||
label={t("workflow_node.apply.form.disable_follow_cname.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow.nodes.apply.form.disable_follow_cname.tooltip") }}></span>}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.apply.form.disable_follow_cname.tooltip") }}></span>}
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
@ -339,12 +341,9 @@ const FormFieldDomainsModalForm = ({
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
domains: z.array(z.string()).refine(
|
||||
(v) => {
|
||||
return v.every((e) => !e?.trim() || validDomainName(e.trim(), true));
|
||||
},
|
||||
{ message: t("common.errmsg.domain_invalid") }
|
||||
),
|
||||
domains: z.array(z.string()).refine((v) => {
|
||||
return v.every((e) => !e?.trim() || validDomainName(e.trim(), true));
|
||||
}, t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const [formInst] = Form.useForm<z.infer<typeof formSchema>>();
|
||||
@ -372,14 +371,14 @@ const FormFieldDomainsModalForm = ({
|
||||
form={formInst}
|
||||
initialValues={model}
|
||||
modalProps={{ destroyOnClose: true }}
|
||||
title={t("workflow.nodes.apply.form.domains.multiple_input_modal.title")}
|
||||
title={t("workflow_node.apply.form.domains.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
width={480}
|
||||
onFinish={handleFinish}
|
||||
>
|
||||
<Form.Item name="domains" rules={[formRule]}>
|
||||
<MultipleInput placeholder={t("workflow.nodes.apply.form.domains.multiple_input_modal.placeholder")} />
|
||||
<MultipleInput placeholder={t("workflow_node.apply.form.domains.multiple_input_modal.placeholder")} />
|
||||
</Form.Item>
|
||||
</ModalForm>
|
||||
);
|
||||
@ -389,12 +388,9 @@ const FormFieldNameserversModalForm = ({ data, trigger, onFinish }: { data: stri
|
||||
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));
|
||||
},
|
||||
{ message: t("common.errmsg.domain_invalid") }
|
||||
),
|
||||
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 [formInst] = Form.useForm<z.infer<typeof formSchema>>();
|
||||
@ -422,14 +418,14 @@ const FormFieldNameserversModalForm = ({ data, trigger, onFinish }: { data: stri
|
||||
form={formInst}
|
||||
initialValues={model}
|
||||
modalProps={{ destroyOnClose: true }}
|
||||
title={t("workflow.nodes.apply.form.nameservers.multiple_input_modal.title")}
|
||||
title={t("workflow_node.apply.form.nameservers.multiple_input_modal.title")}
|
||||
trigger={trigger}
|
||||
validateTrigger="onSubmit"
|
||||
width={480}
|
||||
onFinish={handleFinish}
|
||||
>
|
||||
<Form.Item name="nameservers" rules={[formRule]}>
|
||||
<MultipleInput placeholder={t("workflow.nodes.apply.form.nameservers.multiple_input_modal.placeholder")} />
|
||||
<MultipleInput placeholder={t("workflow_node.apply.form.nameservers.multiple_input_modal.placeholder")} />
|
||||
</Form.Item>
|
||||
</ModalForm>
|
||||
);
|
||||
|
282
ui/src/components/workflow/node/DeployNodeForm.tsx
Normal file
282
ui/src/components/workflow/node/DeployNodeForm.tsx
Normal file
@ -0,0 +1,282 @@
|
||||
import { memo, useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Avatar, Button, Divider, Form, Select, Space, Tooltip, Typography } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { PlusOutlined as PlusOutlinedIcon, QuestionCircleOutlined as QuestionCircleOutlinedIcon } from "@ant-design/icons";
|
||||
import { produce } from "immer";
|
||||
import z from "zod";
|
||||
|
||||
import AccessEditModal from "@/components/access/AccessEditModal";
|
||||
import AccessSelect from "@/components/access/AccessSelect";
|
||||
import { usePanel } from "../PanelProvider";
|
||||
import DeployNodeFormAliyunALBFields from "./DeployNodeFormAliyunALBFields";
|
||||
import DeployNodeFormAliyunCLBFields from "./DeployNodeFormAliyunCLBFields";
|
||||
import DeployNodeFormAliyunCDNFields from "./DeployNodeFormAliyunCDNFields";
|
||||
import DeployNodeFormAliyunDCDNFields from "./DeployNodeFormAliyunDCDNFields";
|
||||
import DeployNodeFormAliyunNLBFields from "./DeployNodeFormAliyunNLBFields";
|
||||
import DeployNodeFormAliyunOSSFields from "./DeployNodeFormAliyunOSSFields";
|
||||
import DeployNodeFormBaiduCloudCDNFields from "./DeployNodeFormBaiduCloudCDNFields";
|
||||
import DeployNodeFormBytePlusCDNFields from "./DeployNodeFormBytePlusCDNFields";
|
||||
import DeployNodeFormDogeCloudCDNFields from "./DeployNodeFormDogeCloudCDNFields";
|
||||
import DeployNodeFormHuaweiCloudCDNFields from "./DeployNodeFormHuaweiCloudCDNFields";
|
||||
import DeployNodeFormHuaweiCloudELBFields from "./DeployNodeFormHuaweiCloudELBFields";
|
||||
import DeployNodeFormKubernetesSecretFields from "./DeployNodeFormKubernetesSecretFields";
|
||||
import DeployNodeFormLocalFields from "./DeployNodeFormLocalFields";
|
||||
import DeployNodeFormQiniuCDNFields from "./DeployNodeFormQiniuCDNFields";
|
||||
import DeployNodeFormSSHFields from "./DeployNodeFormSSHFields";
|
||||
import DeployNodeFormTencentCloudCDNFields from "./DeployNodeFormTencentCloudCDNFields";
|
||||
import DeployNodeFormTencentCloudCLBFields from "./DeployNodeFormTencentCloudCLBFields";
|
||||
import DeployNodeFormTencentCloudCOSFields from "./DeployNodeFormTencentCloudCOSFields";
|
||||
import DeployNodeFormTencentCloudECDNFields from "./DeployNodeFormTencentCloudECDNFields";
|
||||
import DeployNodeFormTencentCloudEOFields from "./DeployNodeFormTencentCloudEOFields";
|
||||
import DeployNodeFormVolcEngineCDNFields from "./DeployNodeFormVolcEngineCDNFields";
|
||||
import DeployNodeFormVolcEngineLiveFields from "./DeployNodeFormVolcEngineLiveFields";
|
||||
import DeployNodeFormWebhookFields from "./DeployNodeFormWebhookFields";
|
||||
import { useAntdForm, useZustandShallowSelector } from "@/hooks";
|
||||
import { ACCESS_USAGES } from "@/domain/access";
|
||||
import { accessProvidersMap, deployProvidersMap } from "@/domain/provider";
|
||||
import { type WorkflowNode, type WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore } from "@/stores/workflow";
|
||||
|
||||
export type DeployFormProps = {
|
||||
data: WorkflowNode;
|
||||
defaultProivderType?: string;
|
||||
};
|
||||
|
||||
const initFormModel = (): WorkflowNodeConfig => {
|
||||
return {};
|
||||
};
|
||||
|
||||
const DeployNodeForm = ({ data, defaultProivderType }: DeployFormProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useZustandShallowSelector(["updateNode", "getWorkflowOuptutBeforeId"]));
|
||||
const { hidePanel } = usePanel();
|
||||
|
||||
const formSchema = z.object({
|
||||
providerType: z
|
||||
.string({ message: t("workflow_node.deploy.form.provider_type.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.provider_type.placeholder")),
|
||||
access: z
|
||||
.string({ message: t("workflow_node.deploy.form.provider_access.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.provider_access.placeholder")),
|
||||
certificate: z.string({ message: t("workflow_node.deploy.form.certificate.placeholder") }).nonempty(t("workflow_node.deploy.form.certificate.placeholder")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const {
|
||||
form: formInst,
|
||||
formPending,
|
||||
formProps,
|
||||
} = useAntdForm<z.infer<typeof formSchema>>({
|
||||
initialValues: data?.config ?? initFormModel(),
|
||||
onSubmit: async (values) => {
|
||||
await formInst.validateFields();
|
||||
await updateNode(
|
||||
produce(data, (draft) => {
|
||||
draft.config = { ...values };
|
||||
draft.validated = true;
|
||||
})
|
||||
);
|
||||
hidePanel();
|
||||
},
|
||||
});
|
||||
|
||||
const [previousOutput, setPreviousOutput] = useState<WorkflowNode[]>([]);
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
setPreviousOutput(rs);
|
||||
}, [data, getWorkflowOuptutBeforeId]);
|
||||
|
||||
const fieldProviderType = Form.useWatch("providerType", formInst);
|
||||
// const fieldAccess = Form.useWatch("access", formInst);
|
||||
|
||||
const formFieldsComponent = useMemo(() => {
|
||||
/*
|
||||
注意:如果追加新的子组件,请保持以 ASCII 排序。
|
||||
NOTICE: If you add new child component, please keep ASCII order.
|
||||
*/
|
||||
switch (fieldProviderType) {
|
||||
case "aliyun-alb":
|
||||
return <DeployNodeFormAliyunALBFields />;
|
||||
case "aliyun-clb":
|
||||
return <DeployNodeFormAliyunCLBFields />;
|
||||
case "aliyun-cdn":
|
||||
return <DeployNodeFormAliyunCDNFields />;
|
||||
case "aliyun-dcdn":
|
||||
return <DeployNodeFormAliyunDCDNFields />;
|
||||
case "aliyun-nlb":
|
||||
return <DeployNodeFormAliyunNLBFields />;
|
||||
case "aliyun-oss":
|
||||
return <DeployNodeFormAliyunOSSFields />;
|
||||
case "baiducloud-cdn":
|
||||
return <DeployNodeFormBaiduCloudCDNFields />;
|
||||
case "byteplus-cdn":
|
||||
return <DeployNodeFormBytePlusCDNFields />;
|
||||
case "dogecloud-cdn":
|
||||
return <DeployNodeFormDogeCloudCDNFields />;
|
||||
case "huaweicloud-cdn":
|
||||
return <DeployNodeFormHuaweiCloudCDNFields />;
|
||||
case "huaweicloud-elb":
|
||||
return <DeployNodeFormHuaweiCloudELBFields />;
|
||||
case "k8s-secret":
|
||||
return <DeployNodeFormKubernetesSecretFields />;
|
||||
case "local":
|
||||
return <DeployNodeFormLocalFields />;
|
||||
case "qiniu-cdn":
|
||||
return <DeployNodeFormQiniuCDNFields />;
|
||||
case "ssh":
|
||||
return <DeployNodeFormSSHFields />;
|
||||
case "tencentcloud-cdn":
|
||||
return <DeployNodeFormTencentCloudCDNFields />;
|
||||
case "tencentcloud-clb":
|
||||
return <DeployNodeFormTencentCloudCLBFields />;
|
||||
case "tencentcloud-cos":
|
||||
return <DeployNodeFormTencentCloudCOSFields />;
|
||||
case "tencentcloud-ecdn":
|
||||
return <DeployNodeFormTencentCloudECDNFields />;
|
||||
case "tencentcloud-eo":
|
||||
return <DeployNodeFormTencentCloudEOFields />;
|
||||
case "volcengine-cdn":
|
||||
return <DeployNodeFormVolcEngineCDNFields />;
|
||||
case "volcengine-live":
|
||||
return <DeployNodeFormVolcEngineLiveFields />;
|
||||
case "webhook":
|
||||
return <DeployNodeFormWebhookFields />;
|
||||
}
|
||||
}, [fieldProviderType]);
|
||||
|
||||
const handleProviderTypeSelect = (value: string) => {
|
||||
if (fieldProviderType === value) return;
|
||||
|
||||
// 切换部署目标时重置表单,避免其他部署目标的配置字段影响当前部署目标
|
||||
if (data.config?.providerType === value) {
|
||||
formInst.resetFields();
|
||||
} else {
|
||||
const oldValues = formInst.getFieldsValue();
|
||||
const newValues: Record<string, unknown> = {};
|
||||
for (const key in oldValues) {
|
||||
if (key === "providerType" || key === "access" || key === "certificate") {
|
||||
newValues[key] = oldValues[key];
|
||||
} else {
|
||||
newValues[key] = undefined;
|
||||
}
|
||||
}
|
||||
formInst.setFieldsValue(newValues);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Form {...formProps} form={formInst} disabled={formPending} layout="vertical">
|
||||
<Form.Item name="providerType" label={t("workflow_node.deploy.form.provider_type.label")} rules={[formRule]} initialValue={defaultProivderType}>
|
||||
<Select
|
||||
showSearch
|
||||
placeholder={t("workflow_node.deploy.form.provider_type.placeholder")}
|
||||
filterOption={(searchValue, option) => {
|
||||
const type = String(option?.value ?? "");
|
||||
const target = deployProvidersMap.get(type);
|
||||
const filter = (v?: string) => v?.toLowerCase()?.includes(searchValue.toLowerCase()) ?? false;
|
||||
return filter(type) || filter(t(target?.name ?? ""));
|
||||
}}
|
||||
onSelect={handleProviderTypeSelect}
|
||||
>
|
||||
{Array.from(deployProvidersMap.values()).map((item) => {
|
||||
return (
|
||||
<Select.Option key={item.type} label={t(item.name)} value={item.type} title={t(item.name)}>
|
||||
<Space className="flex-grow max-w-full truncate" size={4}>
|
||||
<Avatar src={item.icon} size="small" />
|
||||
<Typography.Text className="leading-loose" ellipsis>
|
||||
{t(item.name)}
|
||||
</Typography.Text>
|
||||
</Space>
|
||||
</Select.Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb-0">
|
||||
<label className="block mb-1">
|
||||
<div className="flex items-center justify-between gap-4 w-full">
|
||||
<div className="flex-grow max-w-full truncate">
|
||||
<span>{t("workflow_node.deploy.form.provider_access.label")}</span>
|
||||
<Tooltip title={t("workflow_node.deploy.form.provider_access.tooltip")}>
|
||||
<Typography.Text className="ms-1" type="secondary">
|
||||
<QuestionCircleOutlinedIcon />
|
||||
</Typography.Text>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<AccessEditModal
|
||||
data={{ configType: deployProvidersMap.get(defaultProivderType!)?.provider }}
|
||||
preset="add"
|
||||
trigger={
|
||||
<Button size="small" type="link">
|
||||
<PlusOutlinedIcon />
|
||||
{t("workflow_node.deploy.form.provider_access.button")}
|
||||
</Button>
|
||||
}
|
||||
onSubmit={(record) => {
|
||||
const provider = accessProvidersMap.get(record.configType);
|
||||
if (ACCESS_USAGES.ALL === provider?.usage || ACCESS_USAGES.DEPLOY === provider?.usage) {
|
||||
formInst.setFieldValue("access", record.id);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
<Form.Item name="access" rules={[formRule]}>
|
||||
<AccessSelect
|
||||
placeholder={t("workflow_node.deploy.form.provider_access.placeholder")}
|
||||
filter={(record) => {
|
||||
if (defaultProivderType) {
|
||||
return deployProvidersMap.get(defaultProivderType)?.provider === record.configType;
|
||||
}
|
||||
|
||||
const provider = accessProvidersMap.get(record.configType);
|
||||
return ACCESS_USAGES.ALL === provider?.usage || ACCESS_USAGES.APPLY === provider?.usage;
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="certificate"
|
||||
label={t("workflow_node.deploy.form.certificate.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.certificate.tooltip") }}></span>}
|
||||
>
|
||||
<Select
|
||||
options={previousOutput.map((item) => {
|
||||
return {
|
||||
label: item.name,
|
||||
options: item.output?.map((output) => {
|
||||
return {
|
||||
label: `${item.name} - ${output.label}`,
|
||||
value: `${item.id}#${output.name}`,
|
||||
};
|
||||
}),
|
||||
};
|
||||
})}
|
||||
placeholder={t("workflow_node.deploy.form.certificate.placeholder")}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Divider className="my-1">
|
||||
<Typography.Text className="font-normal text-xs" type="secondary">
|
||||
{t("workflow_node.deploy.form.params_config.label")}
|
||||
</Typography.Text>
|
||||
</Divider>
|
||||
|
||||
{formFieldsComponent}
|
||||
|
||||
<Form.Item>
|
||||
<Button type="primary" htmlType="submit" loading={formPending}>
|
||||
{t("common.button.save")}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(DeployNodeForm);
|
@ -0,0 +1,87 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
|
||||
const RESOURCE_TYPE_LOADBALANCER = "loadbalancer" as const;
|
||||
const RESOURCE_TYPE_LISTENER = "listener" as const;
|
||||
|
||||
const DeployNodeFormAliyunALBFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
resourceType: z.union([z.literal(RESOURCE_TYPE_LOADBALANCER), z.literal(RESOURCE_TYPE_LISTENER)], {
|
||||
message: t("workflow_node.deploy.form.aliyun_alb_resource_type.placeholder"),
|
||||
}),
|
||||
region: z
|
||||
.string({ message: t("workflow_node.deploy.form.aliyun_alb_region.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.aliyun_alb_region.placeholder"))
|
||||
.trim(),
|
||||
loadbalancerId: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldResourceType !== RESOURCE_TYPE_LOADBALANCER || !!v?.trim(), t("workflow_node.deploy.form.aliyun_alb_loadbalancer_id.placeholder")),
|
||||
listenerId: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldResourceType !== RESOURCE_TYPE_LISTENER || !!v?.trim(), t("workflow_node.deploy.form.aliyun_alb_listener_id.placeholder")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const formInst = Form.useFormInstance();
|
||||
|
||||
const fieldResourceType = Form.useWatch("resourceType", formInst);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="resourceType" label={t("workflow_node.deploy.form.aliyun_alb_resource_type.label")} rules={[formRule]}>
|
||||
<Select placeholder={t("workflow_node.deploy.form.aliyun_alb_resource_type.placeholder")}>
|
||||
<Select.Option key={RESOURCE_TYPE_LOADBALANCER} value={RESOURCE_TYPE_LOADBALANCER}>
|
||||
{t("workflow_node.deploy.form.aliyun_alb_resource_type.option.loadbalancer.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={RESOURCE_TYPE_LISTENER} value={RESOURCE_TYPE_LISTENER}>
|
||||
{t("workflow_node.deploy.form.aliyun_alb_resource_type.option.listener.label")}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="region"
|
||||
label={t("workflow_node.deploy.form.aliyun_alb_region.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_alb_region.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_alb_region.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_LOADBALANCER}>
|
||||
<Form.Item
|
||||
name="loadbalancerId"
|
||||
label={t("workflow_node.deploy.form.aliyun_alb_loadbalancer_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_alb_loadbalancer_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_alb_loadbalancer_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_LISTENER}>
|
||||
<Form.Item
|
||||
name="listenerId"
|
||||
label={t("workflow_node.deploy.form.aliyun_alb_listener_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_alb_listener_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_alb_listener_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormAliyunALBFields;
|
@ -0,0 +1,32 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormAliyunCDNFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.aliyun_cdn_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v, true), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.aliyun_cdn_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_cdn_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_cdn_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormAliyunCDNFields;
|
@ -0,0 +1,96 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
import { validPortNumber } from "@/utils/validators";
|
||||
|
||||
const RESOURCE_TYPE_LOADBALANCER = "loadbalancer" as const;
|
||||
const RESOURCE_TYPE_LISTENER = "listener" as const;
|
||||
|
||||
const DeployNodeFormAliyunCLBFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
resourceType: z.union([z.literal(RESOURCE_TYPE_LOADBALANCER), z.literal(RESOURCE_TYPE_LISTENER)], {
|
||||
message: t("workflow_node.deploy.form.aliyun_clb_resource_type.placeholder"),
|
||||
}),
|
||||
region: z
|
||||
.string({ message: t("workflow_node.deploy.form.aliyun_clb_region.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.aliyun_clb_region.placeholder"))
|
||||
.trim(),
|
||||
loadbalancerId: z
|
||||
.string({ message: t("workflow_node.deploy.form.aliyun_clb_loadbalancer_id.placeholder") })
|
||||
.min(1, t("workflow_node.deploy.form.aliyun_clb_loadbalancer_id.placeholder"))
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim(),
|
||||
listenerPort: z
|
||||
.union([
|
||||
z
|
||||
.number()
|
||||
.refine(
|
||||
(v) => fieldResourceType === RESOURCE_TYPE_LISTENER && validPortNumber(v),
|
||||
t("workflow_node.deploy.form.aliyun_clb_listener_port.placeholder")
|
||||
),
|
||||
z
|
||||
.string()
|
||||
.refine(
|
||||
(v) => fieldResourceType === RESOURCE_TYPE_LISTENER && validPortNumber(v),
|
||||
t("workflow_node.deploy.form.aliyun_clb_listener_port.placeholder")
|
||||
),
|
||||
])
|
||||
.nullish(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const formInst = Form.useFormInstance();
|
||||
|
||||
const fieldResourceType = Form.useWatch("resourceType", formInst);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="resourceType" label={t("workflow_node.deploy.form.aliyun_clb_resource_type.label")} rules={[formRule]}>
|
||||
<Select placeholder={t("workflow_node.deploy.form.aliyun_clb_resource_type.placeholder")}>
|
||||
<Select.Option key={RESOURCE_TYPE_LOADBALANCER} value={RESOURCE_TYPE_LOADBALANCER}>
|
||||
{t("workflow_node.deploy.form.aliyun_clb_resource_type.option.loadbalancer.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={RESOURCE_TYPE_LISTENER} value={RESOURCE_TYPE_LISTENER}>
|
||||
{t("workflow_node.deploy.form.aliyun_clb_resource_type.option.listener.label")}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="region"
|
||||
label={t("workflow_node.deploy.form.aliyun_clb_region.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_clb_region.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_clb_region.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="loadbalancerId"
|
||||
label={t("workflow_node.deploy.form.aliyun_clb_loadbalancer_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_clb_loadbalancer_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_clb_loadbalancer_id.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_LISTENER}>
|
||||
<Form.Item
|
||||
name="listenerPort"
|
||||
label={t("workflow_node.deploy.form.aliyun_clb_listener_port.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_clb_listener_port.tooltip") }}></span>}
|
||||
initialValue={443}
|
||||
>
|
||||
<Input type="number" min={1} max={65535} placeholder={t("workflow_node.deploy.form.aliyun_clb_listener_port.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormAliyunCLBFields;
|
@ -0,0 +1,32 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormAliyunDCDNFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.aliyun_dcdn_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v, true), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.aliyun_dcdn_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_dcdn_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_dcdn_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormAliyunDCDNFields;
|
@ -0,0 +1,87 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
|
||||
const RESOURCE_TYPE_LOADBALANCER = "loadbalancer" as const;
|
||||
const RESOURCE_TYPE_LISTENER = "listener" as const;
|
||||
|
||||
const DeployNodeFormAliyunNLBFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
resourceType: z.union([z.literal(RESOURCE_TYPE_LOADBALANCER), z.literal(RESOURCE_TYPE_LISTENER)], {
|
||||
message: t("workflow_node.deploy.form.aliyun_nlb_resource_type.placeholder"),
|
||||
}),
|
||||
region: z
|
||||
.string({ message: t("workflow_node.deploy.form.aliyun_nlb_region.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.aliyun_nlb_region.placeholder"))
|
||||
.trim(),
|
||||
loadbalancerId: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldResourceType !== RESOURCE_TYPE_LOADBALANCER || !!v?.trim(), t("workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.placeholder")),
|
||||
listenerId: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldResourceType !== RESOURCE_TYPE_LISTENER || !!v?.trim(), t("workflow_node.deploy.form.aliyun_nlb_listener_id.placeholder")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const formInst = Form.useFormInstance();
|
||||
|
||||
const fieldResourceType = Form.useWatch("resourceType", formInst);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="resourceType" label={t("workflow_node.deploy.form.aliyun_nlb_resource_type.label")} rules={[formRule]}>
|
||||
<Select placeholder={t("workflow_node.deploy.form.aliyun_nlb_resource_type.placeholder")}>
|
||||
<Select.Option key={RESOURCE_TYPE_LOADBALANCER} value={RESOURCE_TYPE_LOADBALANCER}>
|
||||
{t("workflow_node.deploy.form.aliyun_nlb_resource_type.option.loadbalancer.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={RESOURCE_TYPE_LISTENER} value={RESOURCE_TYPE_LISTENER}>
|
||||
{t("workflow_node.deploy.form.aliyun_nlb_resource_type.option.listener.label")}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="region"
|
||||
label={t("workflow_node.deploy.form.aliyun_nlb_region.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_nlb_region.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_nlb_region.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_LOADBALANCER}>
|
||||
<Form.Item
|
||||
name="loadbalancerId"
|
||||
label={t("workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_LISTENER}>
|
||||
<Form.Item
|
||||
name="listenerId"
|
||||
label={t("workflow_node.deploy.form.aliyun_nlb_listener_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_nlb_listener_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_nlb_listener_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormAliyunNLBFields;
|
@ -0,0 +1,58 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormAliyunOSSFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
endpoint: z
|
||||
.string({ message: t("workflow_node.deploy.form.aliyun_oss_endpoint.placeholder") })
|
||||
.url(t("common.errmsg.url_invalid"))
|
||||
.trim(),
|
||||
bucket: z
|
||||
.string({ message: t("workflow_node.deploy.form.aliyun_oss_bucket.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.aliyun_oss_bucket.placeholder"))
|
||||
.trim(),
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.aliyun_oss_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v, true), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="endpoint"
|
||||
label={t("workflow_node.deploy.form.aliyun_oss_endpoint.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_oss_endpoint.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_oss_endpoint.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="bucket"
|
||||
label={t("workflow_node.deploy.form.aliyun_oss_bucket.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_oss_bucket.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_oss_bucket.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.aliyun_oss_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.aliyun_oss_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.aliyun_oss_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormAliyunOSSFields;
|
@ -0,0 +1,32 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormBaiduCloudCDNFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.baiducloud_cdn_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v, true), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.baiducloud_cdn_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.baiducloud_cdn_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.baiducloud_cdn_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormBaiduCloudCDNFields;
|
@ -0,0 +1,32 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormBytePlusCDNFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.byteplus_cdn_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v, true), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.byteplus_cdn_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.byteplus_cdn_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.byteplus_cdn_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormBytePlusCDNFields;
|
@ -0,0 +1,32 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormDogeCloudCDNFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.dogecloud_cdn_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.dogecloud_cdn_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.dogecloud_cdn_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.dogecloud_cdn_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormDogeCloudCDNFields;
|
@ -0,0 +1,45 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormHuaweiCloudCDNFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
region: z
|
||||
.string({ message: t("workflow_node.deploy.form.huaweicloud_cdn_region.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.huaweicloud_cdn_region.placeholder"))
|
||||
.trim(),
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.huaweicloud_cdn_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="region"
|
||||
label={t("workflow_node.deploy.form.huaweicloud_cdn_region.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.huaweicloud_cdn_region.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.huaweicloud_cdn_region.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.huaweicloud_cdn_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.huaweicloud_cdn_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.huaweicloud_cdn_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormHuaweiCloudCDNFields;
|
@ -0,0 +1,111 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
|
||||
const RESOURCE_TYPE_CERTIFICATE = "certificate" as const;
|
||||
const RESOURCE_TYPE_LOADBALANCER = "loadbalancer" as const;
|
||||
const RESOURCE_TYPE_LISTENER = "listener" as const;
|
||||
|
||||
const DeployNodeFormHuaweiCloudELBFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
resourceType: z.union([z.literal(RESOURCE_TYPE_CERTIFICATE), z.literal(RESOURCE_TYPE_LOADBALANCER), z.literal(RESOURCE_TYPE_LISTENER)], {
|
||||
message: t("workflow_node.deploy.form.huaweicloud_elb_resource_type.placeholder"),
|
||||
}),
|
||||
region: z
|
||||
.string({ message: t("workflow_node.deploy.form.huaweicloud_elb_region.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.huaweicloud_elb_region.placeholder"))
|
||||
.trim(),
|
||||
certificateId: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldResourceType !== RESOURCE_TYPE_CERTIFICATE || !!v?.trim(), t("workflow_node.deploy.form.huaweicloud_elb_certificate_id.placeholder")),
|
||||
loadbalancerId: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine(
|
||||
(v) => fieldResourceType !== RESOURCE_TYPE_LOADBALANCER || !!v?.trim(),
|
||||
t("workflow_node.deploy.form.huaweicloud_elb_loadbalancer_id.placeholder")
|
||||
),
|
||||
listenerId: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldResourceType !== RESOURCE_TYPE_LISTENER || !!v?.trim(), t("workflow_node.deploy.form.huaweicloud_elb_listener_id.placeholder")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const formInst = Form.useFormInstance();
|
||||
|
||||
const fieldResourceType = Form.useWatch("resourceType", formInst);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="resourceType" label={t("workflow_node.deploy.form.huaweicloud_elb_resource_type.label")} rules={[formRule]}>
|
||||
<Select placeholder={t("workflow_node.deploy.form.huaweicloud_elb_resource_type.placeholder")}>
|
||||
<Select.Option key={RESOURCE_TYPE_CERTIFICATE} value={RESOURCE_TYPE_CERTIFICATE}>
|
||||
{t("workflow_node.deploy.form.huaweicloud_elb_resource_type.option.certificate.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={RESOURCE_TYPE_LOADBALANCER} value={RESOURCE_TYPE_LOADBALANCER}>
|
||||
{t("workflow_node.deploy.form.huaweicloud_elb_resource_type.option.loadbalancer.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={RESOURCE_TYPE_LISTENER} value={RESOURCE_TYPE_LISTENER}>
|
||||
{t("workflow_node.deploy.form.huaweicloud_elb_resource_type.option.listener.label")}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="region"
|
||||
label={t("workflow_node.deploy.form.huaweicloud_elb_region.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.huaweicloud_elb_region.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.huaweicloud_elb_region.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_CERTIFICATE}>
|
||||
<Form.Item
|
||||
name="certificateId"
|
||||
label={t("workflow_node.deploy.form.huaweicloud_elb_certificate_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.huaweicloud_elb_certificate_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.huaweicloud_elb_certificate_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_LOADBALANCER}>
|
||||
<Form.Item
|
||||
name="loadbalancerId"
|
||||
label={t("workflow_node.deploy.form.huaweicloud_elb_loadbalancer_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.huaweicloud_elb_loadbalancer_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.huaweicloud_elb_loadbalancer_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_LISTENER}>
|
||||
<Form.Item
|
||||
name="listenerId"
|
||||
label={t("workflow_node.deploy.form.huaweicloud_elb_listener_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.huaweicloud_elb_listener_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.huaweicloud_elb_listener_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormHuaweiCloudELBFields;
|
@ -0,0 +1,77 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
const DeployNodeFormKubernetesSecretFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
namespace: z
|
||||
.string({ message: t("workflow_node.deploy.form.k8s_namespace.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.k8s_namespace.placeholder"))
|
||||
.max(256, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim(),
|
||||
secretName: z
|
||||
.string({ message: t("workflow_node.deploy.form.k8s_secret_name.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.k8s_secret_name.placeholder"))
|
||||
.max(256, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim(),
|
||||
secretDataKeyForCrt: z
|
||||
.string({ message: t("workflow_node.deploy.form.k8s_secret_data_key_for_crt.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.k8s_secret_data_key_for_crt.placeholder"))
|
||||
.max(256, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim(),
|
||||
secretDataKeyForKey: z
|
||||
.string({ message: t("workflow_node.deploy.form.k8s_secret_data_key_for_key.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.k8s_secret_data_key_for_key.placeholder"))
|
||||
.max(256, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="namespace"
|
||||
label={t("workflow_node.deploy.form.k8s_namespace.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.k8s_namespace.tooltip") }}></span>}
|
||||
initialValue="default"
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.k8s_namespace.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="secretName"
|
||||
label={t("workflow_node.deploy.form.k8s_secret_name.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.k8s_secret_name.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.k8s_secret_name.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="secretDataKeyForCrt"
|
||||
label={t("workflow_node.deploy.form.k8s_secret_data_key_for_crt.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.k8s_secret_data_key_for_crt.tooltip") }}></span>}
|
||||
initialValue="tls.crt"
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.k8s_secret_data_key_for_crt.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="secretDataKeyForKey"
|
||||
label={t("workflow_node.deploy.form.k8s_secret_data_key_for_key.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.k8s_secret_data_key_for_key.tooltip") }}></span>}
|
||||
initialValue="tls.key"
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.k8s_secret_data_key_for_key.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormKubernetesSecretFields;
|
305
ui/src/components/workflow/node/DeployNodeFormLocalFields.tsx
Normal file
305
ui/src/components/workflow/node/DeployNodeFormLocalFields.tsx
Normal file
@ -0,0 +1,305 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button, Dropdown, Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { DownOutlined as DownOutlinedIcon } from "@ant-design/icons";
|
||||
import { z } from "zod";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
|
||||
const FORMAT_PEM = "pem" as const;
|
||||
const FORMAT_PFX = "pfx" as const;
|
||||
const FORMAT_JKS = "jks" as const;
|
||||
|
||||
const SHELLENV_SH = "sh" as const;
|
||||
const SHELLENV_CMD = "cmd" as const;
|
||||
const SHELLENV_POWERSHELL = "powershell" as const;
|
||||
|
||||
const DeployNodeFormLocalFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
format: z.union([z.literal(FORMAT_PEM), z.literal(FORMAT_PFX), z.literal(FORMAT_JKS)], {
|
||||
message: t("domain.deployment.form.local_format.placeholder"),
|
||||
}),
|
||||
certPath: z
|
||||
.string()
|
||||
.min(1, t("workflow_node.deploy.form.local_cert_path.tooltip"))
|
||||
.max(256, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim(),
|
||||
keyPath: z
|
||||
.string()
|
||||
.max(256, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldFormat !== FORMAT_PEM || !!v?.trim(), { message: t("workflow_node.deploy.form.local_key_path.tooltip") }),
|
||||
pfxPassword: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldFormat !== FORMAT_PFX || !!v?.trim(), { message: t("workflow_node.deploy.form.local_pfx_password.tooltip") }),
|
||||
jksAlias: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldFormat !== FORMAT_JKS || !!v?.trim(), { message: t("workflow_node.deploy.form.local_jks_alias.tooltip") }),
|
||||
jksKeypass: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldFormat !== FORMAT_JKS || !!v?.trim(), { message: t("workflow_node.deploy.form.local_jks_keypass.tooltip") }),
|
||||
jksStorepass: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldFormat !== FORMAT_JKS || !!v?.trim(), { message: t("workflow_node.deploy.form.local_jks_storepass.tooltip") }),
|
||||
shellEnv: z.union([z.literal(SHELLENV_SH), z.literal(SHELLENV_CMD), z.literal(SHELLENV_POWERSHELL)], {
|
||||
message: t("domain.deployment.form.shell.placeholder"),
|
||||
}),
|
||||
preCommand: z
|
||||
.string()
|
||||
.max(20480, t("common.errmsg.string_max", { max: 20480 }))
|
||||
.nullish(),
|
||||
postCommand: z
|
||||
.string()
|
||||
.max(20480, t("common.errmsg.string_max", { max: 20480 }))
|
||||
.nullish(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const formInst = Form.useFormInstance();
|
||||
|
||||
const fieldFormat = Form.useWatch("format", formInst);
|
||||
const fieldCertPath = Form.useWatch("certPath", formInst);
|
||||
|
||||
const handleFormatSelect = (value: string) => {
|
||||
if (fieldFormat === value) return;
|
||||
|
||||
switch (value) {
|
||||
case FORMAT_PEM:
|
||||
{
|
||||
if (/(.pfx|.jks)$/.test(fieldCertPath)) {
|
||||
formInst.setFieldValue("certPath", fieldCertPath.replace(/(.pfx|.jks)$/, ".crt"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FORMAT_PFX:
|
||||
{
|
||||
if (/(.crt|.jks)$/.test(fieldCertPath)) {
|
||||
formInst.setFieldValue("certPath", fieldCertPath.replace(/(.crt|.jks)$/, ".pfx"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FORMAT_JKS:
|
||||
{
|
||||
if (/(.crt|.pfx)$/.test(fieldCertPath)) {
|
||||
formInst.setFieldValue("certPath", fieldCertPath.replace(/(.crt|.pfx)$/, ".jks"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const handlePresetScriptClick = (key: string) => {
|
||||
switch (key) {
|
||||
case "reload_nginx":
|
||||
{
|
||||
formInst.setFieldValue("shellEnv", "sh");
|
||||
formInst.setFieldValue("postCommand", "sudo service nginx reload");
|
||||
}
|
||||
break;
|
||||
|
||||
case "binding_iis":
|
||||
{
|
||||
formInst.setFieldValue("shellEnv", "powershell");
|
||||
formInst.setFieldValue(
|
||||
"postCommand",
|
||||
`# 请将以下变量替换为实际值
|
||||
$pfxPath = "<your-pfx-path>" # PFX 文件路径
|
||||
$pfxPassword = "<your-pfx-password>" # PFX 密码
|
||||
$siteName = "<your-site-name>" # IIS 网站名称
|
||||
$domain = "<your-domain-name>" # 域名
|
||||
$ipaddr = "<your-binding-ip>" # 绑定 IP,“*”表示所有 IP 绑定
|
||||
$port = "<your-binding-port>" # 绑定端口
|
||||
|
||||
|
||||
# 导入证书到本地计算机的个人存储区
|
||||
$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable
|
||||
# 获取 Thumbprint
|
||||
$thumbprint = $cert.Thumbprint
|
||||
# 导入 WebAdministration 模块
|
||||
Import-Module WebAdministration
|
||||
# 检查是否已存在 HTTPS 绑定
|
||||
$existingBinding = Get-WebBinding -Name "$siteName" -Protocol "https" -Port $port -HostHeader "$domain" -ErrorAction SilentlyContinue
|
||||
if (!$existingBinding) {
|
||||
# 添加新的 HTTPS 绑定
|
||||
New-WebBinding -Name "$siteName" -Protocol "https" -Port $port -IPAddress "$ipaddr" -HostHeader "$domain"
|
||||
}
|
||||
# 获取绑定对象
|
||||
$binding = Get-WebBinding -Name "$siteName" -Protocol "https" -Port $port -IPAddress "$ipaddr" -HostHeader "$domain"
|
||||
# 绑定 SSL 证书
|
||||
$binding.AddSslCertificate($thumbprint, "My")
|
||||
# 删除目录下的证书文件
|
||||
Remove-Item -Path "$pfxPath" -Force
|
||||
`.trim()
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case "binding_netsh":
|
||||
{
|
||||
formInst.setFieldValue("shellEnv", "powershell");
|
||||
formInst.setFieldValue(
|
||||
"postCommand",
|
||||
`# 请将以下变量替换为实际值
|
||||
$pfxPath = "<your-pfx-path>" # PFX 文件路径
|
||||
$pfxPassword = "<your-pfx-password>" # PFX 密码
|
||||
$ipaddr = "<your-binding-ip>" # 绑定 IP,“0.0.0.0”表示所有 IP 绑定,可填入域名。
|
||||
$port = "<your-binding-port>" # 绑定端口
|
||||
|
||||
$addr = $ipaddr + ":" + $port
|
||||
|
||||
# 导入证书到本地计算机的个人存储区
|
||||
$cert = Import-PfxCertificate -FilePath "$pfxPath" -CertStoreLocation Cert:\\LocalMachine\\My -Password (ConvertTo-SecureString -String "$pfxPassword" -AsPlainText -Force) -Exportable
|
||||
# 获取 Thumbprint
|
||||
$thumbprint = $cert.Thumbprint
|
||||
# 检测端口是否绑定证书,如绑定则删除绑定
|
||||
$isExist = netsh http show sslcert ipport=$addr
|
||||
if ($isExist -like "*$addr*"){ netsh http delete sslcert ipport=$addr }
|
||||
# 绑定到端口
|
||||
netsh http add sslcert ipport=$addr certhash=$thumbprint
|
||||
# 删除目录下的证书文件
|
||||
Remove-Item -Path "$pfxPath" -Force
|
||||
`.trim()
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="format" label={t("workflow_node.deploy.form.local_format.label")} rules={[formRule]} initialValue={FORMAT_PEM}>
|
||||
<Select placeholder={t("workflow_node.deploy.form.local_format.placeholder")} onSelect={handleFormatSelect}>
|
||||
<Select.Option key={FORMAT_PEM} value={FORMAT_PEM}>
|
||||
{t("workflow_node.deploy.form.local_format.option.pem.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={FORMAT_PFX} value={FORMAT_PFX}>
|
||||
{t("workflow_node.deploy.form.local_format.option.pfx.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={FORMAT_JKS} value={FORMAT_JKS}>
|
||||
{t("workflow_node.deploy.form.local_format.option.jks.label")}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="certPath"
|
||||
label={t("workflow_node.deploy.form.local_cert_path.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.local_cert_path.tooltip") }}></span>}
|
||||
initialValue="/etc/ssl/certs/cert.crt"
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.local_cert_path.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldFormat === FORMAT_PEM}>
|
||||
<Form.Item
|
||||
name="keyPath"
|
||||
label={t("workflow_node.deploy.form.local_key_path.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.local_key_path.tooltip") }}></span>}
|
||||
initialValue="/etc/ssl/certs/cert.key"
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.local_key_path.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldFormat === FORMAT_PFX}>
|
||||
<Form.Item name="pfxPassword" label={t("workflow_node.deploy.form.local_pfx_password.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("workflow_node.deploy.form.local_pfx_password.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldFormat === FORMAT_JKS}>
|
||||
<Form.Item name="jksAlias" label={t("workflow_node.deploy.form.local_jks_alias.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("workflow_node.deploy.form.local_jks_alias.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="jksKeypass" label={t("workflow_node.deploy.form.local_jks_keypass.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("workflow_node.deploy.form.local_jks_keypass.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="jksStorepass" label={t("workflow_node.deploy.form.local_jks_storepass.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("workflow_node.deploy.form.local_jks_storepass.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Form.Item name="shellEnv" label={t("workflow_node.deploy.form.local_shell_env.label")} rules={[formRule]} initialValue={SHELLENV_SH}>
|
||||
<Select placeholder={t("workflow_node.deploy.form.local_shell_env.placeholder")}>
|
||||
<Select.Option key={SHELLENV_SH} value={SHELLENV_SH}>
|
||||
{t("workflow_node.deploy.form.local_shell_env.option.sh.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={SHELLENV_CMD} value={SHELLENV_CMD}>
|
||||
{t("workflow_node.deploy.form.local_shell_env.option.cmd.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={SHELLENV_POWERSHELL} value={SHELLENV_POWERSHELL}>
|
||||
{t("workflow_node.deploy.form.local_shell_env.option.powershell.label")}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="preCommand" label={t("workflow_node.deploy.form.local_pre_command.label")} rules={[formRule]}>
|
||||
<Input.TextArea autoSize={{ minRows: 1, maxRows: 5 }} placeholder={t("workflow_node.deploy.form.local_pre_command.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb-0">
|
||||
<label className="block mb-1">
|
||||
<div className="flex items-center justify-between gap-4 w-full">
|
||||
<div className="flex-grow max-w-full truncate">
|
||||
<span>{t("workflow_node.deploy.form.local_post_command.label")}</span>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: "reload_nginx",
|
||||
label: t("workflow_node.deploy.form.local_preset_scripts.option.reload_nginx.label"),
|
||||
onClick: () => handlePresetScriptClick("reload_nginx"),
|
||||
},
|
||||
{
|
||||
key: "binding_iis",
|
||||
label: t("workflow_node.deploy.form.local_preset_scripts.option.binding_iis.label"),
|
||||
onClick: () => handlePresetScriptClick("binding_iis"),
|
||||
},
|
||||
{
|
||||
key: "binding_netsh",
|
||||
label: t("workflow_node.deploy.form.local_preset_scripts.option.binding_netsh.label"),
|
||||
onClick: () => handlePresetScriptClick("binding_netsh"),
|
||||
},
|
||||
],
|
||||
}}
|
||||
trigger={["click"]}
|
||||
>
|
||||
<Button size="small" type="link">
|
||||
{t("workflow_node.deploy.form.local_preset_scripts.button")}
|
||||
<DownOutlinedIcon />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
<Form.Item name="postCommand" rules={[formRule]}>
|
||||
<Input.TextArea autoSize={{ minRows: 1, maxRows: 5 }} placeholder={t("workflow_node.deploy.form.local_post_command.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormLocalFields;
|
@ -0,0 +1,32 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormQiniuCDNFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.qiniu_cdn_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v, true), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.qiniu_cdn_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.qiniu_cdn_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.qiniu_cdn_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormQiniuCDNFields;
|
211
ui/src/components/workflow/node/DeployNodeFormSSHFields.tsx
Normal file
211
ui/src/components/workflow/node/DeployNodeFormSSHFields.tsx
Normal file
@ -0,0 +1,211 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button, Dropdown, Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { DownOutlined as DownOutlinedIcon } from "@ant-design/icons";
|
||||
import { z } from "zod";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
|
||||
const FORMAT_PEM = "pem" as const;
|
||||
const FORMAT_PFX = "pfx" as const;
|
||||
const FORMAT_JKS = "jks" as const;
|
||||
|
||||
const DeployNodeFormSSHFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
format: z.union([z.literal(FORMAT_PEM), z.literal(FORMAT_PFX), z.literal(FORMAT_JKS)], {
|
||||
message: t("domain.deployment.form.ssh_format.placeholder"),
|
||||
}),
|
||||
certPath: z
|
||||
.string()
|
||||
.min(1, t("workflow_node.deploy.form.ssh_cert_path.tooltip"))
|
||||
.max(256, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim(),
|
||||
keyPath: z
|
||||
.string()
|
||||
.max(256, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldFormat !== FORMAT_PEM || !!v?.trim(), { message: t("workflow_node.deploy.form.ssh_key_path.tooltip") }),
|
||||
pfxPassword: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldFormat !== FORMAT_PFX || !!v?.trim(), { message: t("workflow_node.deploy.form.ssh_pfx_password.tooltip") }),
|
||||
jksAlias: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldFormat !== FORMAT_JKS || !!v?.trim(), { message: t("workflow_node.deploy.form.ssh_jks_alias.tooltip") }),
|
||||
jksKeypass: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldFormat !== FORMAT_JKS || !!v?.trim(), { message: t("workflow_node.deploy.form.ssh_jks_keypass.tooltip") }),
|
||||
jksStorepass: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 256 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine((v) => fieldFormat !== FORMAT_JKS || !!v?.trim(), { message: t("workflow_node.deploy.form.ssh_jks_storepass.tooltip") }),
|
||||
preCommand: z
|
||||
.string()
|
||||
.max(20480, t("common.errmsg.string_max", { max: 20480 }))
|
||||
.nullish(),
|
||||
postCommand: z
|
||||
.string()
|
||||
.max(20480, t("common.errmsg.string_max", { max: 20480 }))
|
||||
.nullish(),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const formInst = Form.useFormInstance();
|
||||
|
||||
const fieldFormat = Form.useWatch("format", formInst);
|
||||
const fieldCertPath = Form.useWatch("certPath", formInst);
|
||||
|
||||
const handleFormatSelect = (value: string) => {
|
||||
if (fieldFormat === value) return;
|
||||
|
||||
switch (value) {
|
||||
case FORMAT_PEM:
|
||||
{
|
||||
if (/(.pfx|.jks)$/.test(fieldCertPath)) {
|
||||
formInst.setFieldValue("certPath", fieldCertPath.replace(/(.pfx|.jks)$/, ".crt"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FORMAT_PFX:
|
||||
{
|
||||
if (/(.crt|.jks)$/.test(fieldCertPath)) {
|
||||
formInst.setFieldValue("certPath", fieldCertPath.replace(/(.crt|.jks)$/, ".pfx"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case FORMAT_JKS:
|
||||
{
|
||||
if (/(.crt|.pfx)$/.test(fieldCertPath)) {
|
||||
formInst.setFieldValue("certPath", fieldCertPath.replace(/(.crt|.pfx)$/, ".jks"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const handlePresetScriptClick = (key: string) => {
|
||||
switch (key) {
|
||||
case "reload_nginx":
|
||||
{
|
||||
formInst.setFieldValue("postCommand", "sudo service nginx reload");
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="format" label={t("workflow_node.deploy.form.ssh_format.label")} rules={[formRule]} initialValue={FORMAT_PEM}>
|
||||
<Select placeholder={t("workflow_node.deploy.form.ssh_format.placeholder")} onSelect={handleFormatSelect}>
|
||||
<Select.Option key={FORMAT_PEM} value={FORMAT_PEM}>
|
||||
{t("workflow_node.deploy.form.ssh_format.option.pem.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={FORMAT_PFX} value={FORMAT_PFX}>
|
||||
{t("workflow_node.deploy.form.ssh_format.option.pfx.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={FORMAT_JKS} value={FORMAT_JKS}>
|
||||
{t("workflow_node.deploy.form.ssh_format.option.jks.label")}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="certPath"
|
||||
label={t("workflow_node.deploy.form.ssh_cert_path.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ssh_cert_path.tooltip") }}></span>}
|
||||
initialValue="/etc/ssl/certs/cert.crt"
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.ssh_cert_path.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Show when={fieldFormat === FORMAT_PEM}>
|
||||
<Form.Item
|
||||
name="keyPath"
|
||||
label={t("workflow_node.deploy.form.ssh_key_path.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.ssh_key_path.tooltip") }}></span>}
|
||||
initialValue="/etc/ssl/certs/cert.key"
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.ssh_key_path.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldFormat === FORMAT_PFX}>
|
||||
<Form.Item name="pfxPassword" label={t("workflow_node.deploy.form.ssh_pfx_password.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("workflow_node.deploy.form.ssh_pfx_password.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldFormat === FORMAT_JKS}>
|
||||
<Form.Item name="jksAlias" label={t("workflow_node.deploy.form.ssh_jks_alias.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("workflow_node.deploy.form.ssh_jks_alias.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="jksKeypass" label={t("workflow_node.deploy.form.ssh_jks_keypass.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("workflow_node.deploy.form.ssh_jks_keypass.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="jksStorepass" label={t("workflow_node.deploy.form.ssh_jks_storepass.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("workflow_node.deploy.form.ssh_jks_storepass.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Form.Item label={t("workflow_node.deploy.form.ssh_shell_env.label")}>
|
||||
<Select options={[{ value: t("workflow_node.deploy.form.ssh_shell_env.value") }]} value={t("workflow_node.deploy.form.ssh_shell_env.value")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="preCommand" label={t("workflow_node.deploy.form.ssh_pre_command.label")} rules={[formRule]}>
|
||||
<Input.TextArea autoSize={{ minRows: 1, maxRows: 5 }} placeholder={t("workflow_node.deploy.form.ssh_pre_command.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item className="mb-0">
|
||||
<label className="block mb-1">
|
||||
<div className="flex items-center justify-between gap-4 w-full">
|
||||
<div className="flex-grow max-w-full truncate">
|
||||
<span>{t("workflow_node.deploy.form.ssh_post_command.label")}</span>
|
||||
</div>
|
||||
<div className="text-right">
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: "reload_nginx",
|
||||
label: t("workflow_node.deploy.form.ssh_preset_scripts.option.reload_nginx.label"),
|
||||
onClick: () => handlePresetScriptClick("reload_nginx"),
|
||||
},
|
||||
],
|
||||
}}
|
||||
trigger={["click"]}
|
||||
>
|
||||
<Button size="small" type="link">
|
||||
{t("workflow_node.deploy.form.ssh_preset_scripts.button")}
|
||||
<DownOutlinedIcon />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
<Form.Item name="postCommand" rules={[formRule]}>
|
||||
<Input.TextArea autoSize={{ minRows: 1, maxRows: 5 }} placeholder={t("workflow_node.deploy.form.ssh_post_command.placeholder")} />
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormSSHFields;
|
@ -0,0 +1,32 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormTencentCloudCDNFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.tencentcloud_cdn_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v, true), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.tencentcloud_cdn_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_cdn_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_cdn_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormTencentCloudCDNFields;
|
@ -0,0 +1,125 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import Show from "@/components/Show";
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const RESOURCE_TYPE_SSLDEPLOY = "ssl-deploy" as const;
|
||||
const RESOURCE_TYPE_LOADBALANCER = "loadbalancer" as const;
|
||||
const RESOURCE_TYPE_LISTENER = "listener" as const;
|
||||
const RESOURCE_TYPE_RULEDOMAIN = "ruledomain" as const;
|
||||
|
||||
const DeployNodeFormTencentCloudCLBFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
resourceType: z.union(
|
||||
[z.literal(RESOURCE_TYPE_SSLDEPLOY), z.literal(RESOURCE_TYPE_LOADBALANCER), z.literal(RESOURCE_TYPE_LISTENER), z.literal(RESOURCE_TYPE_RULEDOMAIN)],
|
||||
{ message: t("workflow_node.deploy.form.tencentcloud_clb_resource_type.placeholder") }
|
||||
),
|
||||
region: z
|
||||
.string({ message: t("workflow_node.deploy.form.tencentcloud_clb_region.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.tencentcloud_clb_region.placeholder"))
|
||||
.trim(),
|
||||
loadbalancerId: z
|
||||
.string()
|
||||
.min(1, t("workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.placeholder"))
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim(),
|
||||
listenerId: z
|
||||
.string()
|
||||
.max(64, t("common.errmsg.string_max", { max: 64 }))
|
||||
.trim()
|
||||
.nullish()
|
||||
.refine(
|
||||
(v) => ![RESOURCE_TYPE_SSLDEPLOY, RESOURCE_TYPE_LISTENER, RESOURCE_TYPE_RULEDOMAIN].includes(fieldResourceType) || !!v?.trim(),
|
||||
t("workflow_node.deploy.form.tencentcloud_clb_listener_id.placeholder")
|
||||
),
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.tencentcloud_clb_domain.placeholder") })
|
||||
.nullish()
|
||||
.refine((v) => RESOURCE_TYPE_RULEDOMAIN !== fieldResourceType || validDomainName(v!, true), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const formInst = Form.useFormInstance();
|
||||
|
||||
const fieldResourceType = Form.useWatch("resourceType", formInst);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item name="resourceType" label={t("workflow_node.deploy.form.tencentcloud_clb_resource_type.label")} rules={[formRule]}>
|
||||
<Select placeholder={t("workflow_node.deploy.form.tencentcloud_clb_resource_type.placeholder")}>
|
||||
<Select.Option key={RESOURCE_TYPE_SSLDEPLOY} value={RESOURCE_TYPE_SSLDEPLOY}>
|
||||
{t("workflow_node.deploy.form.tencentcloud_clb_resource_type.option.ssl_deploy.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={RESOURCE_TYPE_LOADBALANCER} value={RESOURCE_TYPE_LOADBALANCER}>
|
||||
{t("workflow_node.deploy.form.tencentcloud_clb_resource_type.option.loadbalancer.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={RESOURCE_TYPE_LISTENER} value={RESOURCE_TYPE_LISTENER}>
|
||||
{t("workflow_node.deploy.form.tencentcloud_clb_resource_type.option.listener.label")}
|
||||
</Select.Option>
|
||||
<Select.Option key={RESOURCE_TYPE_RULEDOMAIN} value={RESOURCE_TYPE_RULEDOMAIN}>
|
||||
{t("workflow_node.deploy.form.tencentcloud_clb_resource_type.option.ruledomain.label")}
|
||||
</Select.Option>
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="region"
|
||||
label={t("workflow_node.deploy.form.tencentcloud_clb_region.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_clb_region.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_clb_region.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="loadbalancerId"
|
||||
label={t("workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Show
|
||||
when={fieldResourceType === RESOURCE_TYPE_SSLDEPLOY || fieldResourceType === RESOURCE_TYPE_LISTENER || fieldResourceType === RESOURCE_TYPE_RULEDOMAIN}
|
||||
>
|
||||
<Form.Item
|
||||
name="listenerId"
|
||||
label={t("workflow_node.deploy.form.tencentcloud_clb_listener_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_clb_listener_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_clb_listener_id.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_SSLDEPLOY}>
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.tencentcloud_clb_snidomain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_clb_snidomain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_clb_snidomain.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
|
||||
<Show when={fieldResourceType === RESOURCE_TYPE_RULEDOMAIN}>
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.tencentcloud_clb_ruledomain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_clb_ruledomain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_clb_ruledomain.placeholder")} />
|
||||
</Form.Item>
|
||||
</Show>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormTencentCloudCLBFields;
|
@ -0,0 +1,58 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormTencentCloudCOSFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
region: z
|
||||
.string({ message: t("workflow_node.deploy.form.tencentcloud_cos_region.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.tencentcloud_cos_region.placeholder"))
|
||||
.trim(),
|
||||
bucket: z
|
||||
.string({ message: t("workflow_node.deploy.form.tencentcloud_cos_bucket.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.tencentcloud_cos_bucket.placeholder"))
|
||||
.trim(),
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.tencentcloud_cos_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="region"
|
||||
label={t("workflow_node.deploy.form.tencentcloud_cos_region.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_cos_region.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_cos_region.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="bucket"
|
||||
label={t("workflow_node.deploy.form.tencentcloud_cos_bucket.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_cos_bucket.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_cos_bucket.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.tencentcloud_cos_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_cos_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_cos_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormTencentCloudCOSFields;
|
@ -0,0 +1,32 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormTencentCloudECDNFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.tencentcloud_ecdn_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v, true), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.tencentcloud_ecdn_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_ecdn_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_ecdn_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormTencentCloudECDNFields;
|
@ -0,0 +1,45 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormTencentCloudEOFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
zoneId: z
|
||||
.string({ message: t("workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder") })
|
||||
.nonempty(t("workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder"))
|
||||
.trim(),
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.tencentcloud_eo_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="zoneId"
|
||||
label={t("workflow_node.deploy.form.tencentcloud_eo_zone_id.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_eo_zone_id.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.tencentcloud_eo_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.tencentcloud_eo_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.tencentcloud_eo_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormTencentCloudEOFields;
|
@ -0,0 +1,32 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormVolcEngineCDNFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.volcengine_cdn_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v, true), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.volcengine_cdn_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.volcengine_cdn_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.volcengine_cdn_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormVolcEngineCDNFields;
|
@ -0,0 +1,32 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
import { validDomainName } from "@/utils/validators";
|
||||
|
||||
const DeployNodeFormVolcEngineLiveFields = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const formSchema = z.object({
|
||||
domain: z
|
||||
.string({ message: t("workflow_node.deploy.form.volcengine_live_domain.placeholder") })
|
||||
.refine((v) => validDomainName(v, true), t("common.errmsg.domain_invalid")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="domain"
|
||||
label={t("workflow_node.deploy.form.volcengine_live_domain.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.volcengine_live_domain.tooltip") }}></span>}
|
||||
>
|
||||
<Input placeholder={t("workflow_node.deploy.form.volcengine_live_domain.placeholder")} />
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormVolcEngineLiveFields;
|
@ -0,0 +1,50 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Form, Input } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { z } from "zod";
|
||||
|
||||
const DeployNodeFormWebhookFields = () => {
|
||||
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.placeholder")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const formInst = Form.useFormInstance();
|
||||
|
||||
const handleWebhookDataBlur = (e: React.FocusEvent<HTMLTextAreaElement>) => {
|
||||
const value = e.target.value;
|
||||
try {
|
||||
const json = JSON.stringify(JSON.parse(value), null, 2);
|
||||
formInst.setFieldValue("webhookData", json);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form.Item
|
||||
name="webhookData"
|
||||
label={t("workflow_node.deploy.form.webhook_data.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.deploy.form.webhook_data.tooltip") }}></span>}
|
||||
>
|
||||
<Input.TextArea
|
||||
autoSize={{ minRows: 3, maxRows: 10 }}
|
||||
placeholder={t("workflow_node.deploy.form.webhook_data.placeholder")}
|
||||
onBlur={handleWebhookDataBlur}
|
||||
/>
|
||||
</Form.Item>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployNodeFormWebhookFields;
|
@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { Button, Form, Input, Select } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import { RightOutlined as RightOutlinedIcon } from "@ant-design/icons";
|
||||
import { produce } from "immer";
|
||||
import { z } from "zod";
|
||||
|
||||
import { usePanel } from "../PanelProvider";
|
||||
@ -37,14 +38,14 @@ const NotifyNodeForm = ({ data }: NotifyNodeFormProps) => {
|
||||
|
||||
const formSchema = z.object({
|
||||
subject: z
|
||||
.string({ message: t("workflow.nodes.notify.form.subject.placeholder") })
|
||||
.min(1, t("workflow.nodes.notify.form.subject.placeholder"))
|
||||
.string({ message: t("workflow_node.notify.form.subject.placeholder") })
|
||||
.min(1, t("workflow_node.notify.form.subject.placeholder"))
|
||||
.max(1000, t("common.errmsg.string_max", { max: 1000 })),
|
||||
message: z
|
||||
.string({ message: t("workflow.nodes.notify.form.message.placeholder") })
|
||||
.min(1, t("workflow.nodes.notify.form.message.placeholder"))
|
||||
.string({ message: t("workflow_node.notify.form.message.placeholder") })
|
||||
.min(1, t("workflow_node.notify.form.message.placeholder"))
|
||||
.max(1000, t("common.errmsg.string_max", { max: 1000 })),
|
||||
channel: z.string({ message: t("workflow.nodes.notify.form.channel.placeholder") }).min(1, t("workflow.nodes.notify.form.channel.placeholder")),
|
||||
channel: z.string({ message: t("workflow_node.notify.form.channel.placeholder") }).min(1, t("workflow_node.notify.form.channel.placeholder")),
|
||||
});
|
||||
const formRule = createSchemaFieldRule(formSchema);
|
||||
const {
|
||||
@ -54,29 +55,35 @@ const NotifyNodeForm = ({ data }: NotifyNodeFormProps) => {
|
||||
} = useAntdForm<z.infer<typeof formSchema>>({
|
||||
initialValues: data?.config ?? initFormModel(),
|
||||
onSubmit: async (values) => {
|
||||
await updateNode({ ...data, config: { ...values }, validated: true });
|
||||
await formInst.validateFields();
|
||||
await updateNode(
|
||||
produce(data, (draft) => {
|
||||
draft.config = { ...values };
|
||||
draft.validated = true;
|
||||
})
|
||||
);
|
||||
hidePanel();
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Form {...formProps} form={formInst} disabled={formPending} layout="vertical">
|
||||
<Form.Item name="subject" label={t("workflow.nodes.notify.form.subject.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("workflow.nodes.notify.form.subject.placeholder")} />
|
||||
<Form.Item name="subject" label={t("workflow_node.notify.form.subject.label")} rules={[formRule]}>
|
||||
<Input placeholder={t("workflow_node.notify.form.subject.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item name="message" label={t("workflow.nodes.notify.form.message.label")} rules={[formRule]}>
|
||||
<Input.TextArea autoSize={{ minRows: 3, maxRows: 10 }} placeholder={t("workflow.nodes.notify.form.message.placeholder")} />
|
||||
<Form.Item name="message" label={t("workflow_node.notify.form.message.label")} rules={[formRule]}>
|
||||
<Input.TextArea autoSize={{ minRows: 3, maxRows: 10 }} placeholder={t("workflow_node.notify.form.message.placeholder")} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
<Form.Item className="mb-0">
|
||||
<label className="block mb-1">
|
||||
<div className="flex items-center justify-between gap-4 w-full">
|
||||
<div className="flex-grow max-w-full truncate">{t("workflow.nodes.notify.form.channel.label")}</div>
|
||||
<div className="flex-grow max-w-full truncate">{t("workflow_node.notify.form.channel.label")}</div>
|
||||
<div className="text-right">
|
||||
<Link className="ant-typography" to="/settings/notification" target="_blank">
|
||||
<Button size="small" type="link">
|
||||
{t("workflow.nodes.notify.form.channel.button")}
|
||||
{t("workflow_node.notify.form.channel.button")}
|
||||
<RightOutlinedIcon className="text-xs" />
|
||||
</Button>
|
||||
</Link>
|
||||
@ -92,7 +99,7 @@ const NotifyNodeForm = ({ data }: NotifyNodeFormProps) => {
|
||||
label: t(notifyChannelsMap.get(k)?.name ?? k),
|
||||
value: k,
|
||||
}))}
|
||||
placeholder={t("workflow.nodes.notify.form.channel.placeholder")}
|
||||
placeholder={t("workflow_node.notify.form.channel.placeholder")}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Form.Item>
|
||||
|
@ -3,6 +3,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { Alert, Button, Form, Input, Radio } from "antd";
|
||||
import { createSchemaFieldRule } from "antd-zod";
|
||||
import dayjs from "dayjs";
|
||||
import { produce } from "immer";
|
||||
import { z } from "zod";
|
||||
|
||||
import { usePanel } from "../PanelProvider";
|
||||
@ -30,7 +31,7 @@ const StartNodeForm = ({ data }: StartNodeFormProps) => {
|
||||
|
||||
const formSchema = z
|
||||
.object({
|
||||
executionMethod: z.string({ message: t("workflow.nodes.start.form.trigger.placeholder") }).min(1, t("workflow.nodes.start.form.trigger.placeholder")),
|
||||
executionMethod: z.string({ message: t("workflow_node.start.form.trigger.placeholder") }).min(1, t("workflow_node.start.form.trigger.placeholder")),
|
||||
crontab: z.string().nullish(),
|
||||
})
|
||||
.superRefine((data, ctx) => {
|
||||
@ -41,7 +42,7 @@ const StartNodeForm = ({ data }: StartNodeFormProps) => {
|
||||
if (!validCronExpression(data.crontab!)) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: t("workflow.nodes.start.form.trigger_cron.errmsg.invalid"),
|
||||
message: t("workflow_node.start.form.trigger_cron.errmsg.invalid"),
|
||||
path: ["crontab"],
|
||||
});
|
||||
}
|
||||
@ -54,7 +55,13 @@ const StartNodeForm = ({ data }: StartNodeFormProps) => {
|
||||
} = useAntdForm<z.infer<typeof formSchema>>({
|
||||
initialValues: data?.config ?? initFormModel(),
|
||||
onSubmit: async (values) => {
|
||||
await updateNode({ ...data, config: { ...values }, validated: true });
|
||||
await formInst.validateFields();
|
||||
await updateNode(
|
||||
produce(data, (draft) => {
|
||||
draft.config = { ...values };
|
||||
draft.validated = true;
|
||||
})
|
||||
);
|
||||
hidePanel();
|
||||
},
|
||||
});
|
||||
@ -82,26 +89,26 @@ const StartNodeForm = ({ data }: StartNodeFormProps) => {
|
||||
<Form {...formProps} form={formInst} disabled={formPending} layout="vertical">
|
||||
<Form.Item
|
||||
name="executionMethod"
|
||||
label={t("workflow.nodes.start.form.trigger.label")}
|
||||
label={t("workflow_node.start.form.trigger.label")}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow.nodes.start.form.trigger.tooltip") }}></span>}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.start.form.trigger.tooltip") }}></span>}
|
||||
>
|
||||
<Radio.Group value={triggerType} onChange={(e) => handleTriggerTypeChange(e.target.value)}>
|
||||
<Radio value="auto">{t("workflow.nodes.start.form.trigger.option.auto.label")}</Radio>
|
||||
<Radio value="manual">{t("workflow.nodes.start.form.trigger.option.manual.label")}</Radio>
|
||||
<Radio value="auto">{t("workflow_node.start.form.trigger.option.auto.label")}</Radio>
|
||||
<Radio value="manual">{t("workflow_node.start.form.trigger.option.manual.label")}</Radio>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name="crontab"
|
||||
label={t("workflow.nodes.start.form.trigger_cron.label")}
|
||||
label={t("workflow_node.start.form.trigger_cron.label")}
|
||||
hidden={triggerType !== "auto"}
|
||||
rules={[formRule]}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow.nodes.start.form.trigger_cron.tooltip") }}></span>}
|
||||
tooltip={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.start.form.trigger_cron.tooltip") }}></span>}
|
||||
extra={
|
||||
triggerCronLastExecutions.length > 0 ? (
|
||||
<div>
|
||||
{t("workflow.nodes.start.form.trigger_cron.extra")}
|
||||
{t("workflow_node.start.form.trigger_cron.extra")}
|
||||
<br />
|
||||
{triggerCronLastExecutions.map((date, index) => (
|
||||
<span key={index}>
|
||||
@ -115,11 +122,11 @@ const StartNodeForm = ({ data }: StartNodeFormProps) => {
|
||||
)
|
||||
}
|
||||
>
|
||||
<Input placeholder={t("workflow.nodes.start.form.trigger_cron.placeholder")} onChange={(e) => handleTriggerCronChange(e.target.value)} />
|
||||
<Input placeholder={t("workflow_node.start.form.trigger_cron.placeholder")} onChange={(e) => handleTriggerCronChange(e.target.value)} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item hidden={triggerType !== "auto"}>
|
||||
<Alert type="info" message={<span dangerouslySetInnerHTML={{ __html: t("workflow.nodes.start.form.trigger_cron_alert.content") }}></span>} />
|
||||
<Alert type="info" message={<span dangerouslySetInnerHTML={{ __html: t("workflow_node.start.form.trigger_cron_alert.content") }}></span>} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item>
|
||||
|
96
ui/src/domain/provider.ts
Normal file
96
ui/src/domain/provider.ts
Normal file
@ -0,0 +1,96 @@
|
||||
import {
|
||||
ACCESS_PROVIDER_ACMEHTTPREQ,
|
||||
ACCESS_PROVIDER_ALIYUN,
|
||||
ACCESS_PROVIDER_AWS,
|
||||
ACCESS_PROVIDER_BAIDUCLOUD,
|
||||
ACCESS_PROVIDER_BYTEPLUS,
|
||||
ACCESS_PROVIDER_CLOUDFLARE,
|
||||
ACCESS_PROVIDER_DOGECLOUD,
|
||||
ACCESS_PROVIDER_HUAWEICLOUD,
|
||||
ACCESS_PROVIDER_KUBERNETES,
|
||||
ACCESS_PROVIDER_LOCAL,
|
||||
ACCESS_PROVIDER_NAMEDOTCOM,
|
||||
ACCESS_PROVIDER_NAMESILO,
|
||||
ACCESS_PROVIDER_GODADDY,
|
||||
ACCESS_PROVIDER_POWERDNS,
|
||||
ACCESS_PROVIDER_QINIU,
|
||||
ACCESS_PROVIDER_SSH,
|
||||
ACCESS_PROVIDER_TENCENTCLOUD,
|
||||
ACCESS_PROVIDER_VOLCENGINE,
|
||||
ACCESS_PROVIDER_WEBHOOK,
|
||||
type AccessUsageType,
|
||||
} from "./access";
|
||||
|
||||
export type AccessProvider = {
|
||||
type: string;
|
||||
name: string;
|
||||
icon: string;
|
||||
usage: AccessUsageType;
|
||||
};
|
||||
|
||||
export const accessProvidersMap: Map<AccessProvider["type"], AccessProvider> = new Map(
|
||||
/*
|
||||
注意:此处的顺序决定显示在前端的顺序。
|
||||
NOTICE: The following order determines the order displayed at the frontend.
|
||||
*/
|
||||
[
|
||||
[ACCESS_PROVIDER_LOCAL, "common.provider.local", "/imgs/providers/local.svg", "deploy"],
|
||||
[ACCESS_PROVIDER_SSH, "common.provider.ssh", "/imgs/providers/ssh.svg", "deploy"],
|
||||
[ACCESS_PROVIDER_WEBHOOK, "common.provider.webhook", "/imgs/providers/webhook.svg", "deploy"],
|
||||
[ACCESS_PROVIDER_KUBERNETES, "common.provider.kubernetes", "/imgs/providers/kubernetes.svg", "deploy"],
|
||||
[ACCESS_PROVIDER_ALIYUN, "common.provider.aliyun", "/imgs/providers/aliyun.svg", "all"],
|
||||
[ACCESS_PROVIDER_TENCENTCLOUD, "common.provider.tencentcloud", "/imgs/providers/tencentcloud.svg", "all"],
|
||||
[ACCESS_PROVIDER_HUAWEICLOUD, "common.provider.huaweicloud", "/imgs/providers/huaweicloud.svg", "all"],
|
||||
[ACCESS_PROVIDER_BAIDUCLOUD, "common.provider.baiducloud", "/imgs/providers/baiducloud.svg", "all"],
|
||||
[ACCESS_PROVIDER_QINIU, "common.provider.qiniu", "/imgs/providers/qiniu.svg", "deploy"],
|
||||
[ACCESS_PROVIDER_DOGECLOUD, "common.provider.dogecloud", "/imgs/providers/dogecloud.svg", "deploy"],
|
||||
[ACCESS_PROVIDER_VOLCENGINE, "common.provider.volcengine", "/imgs/providers/volcengine.svg", "all"],
|
||||
[ACCESS_PROVIDER_BYTEPLUS, "common.provider.byteplus", "/imgs/providers/byteplus.svg", "all"],
|
||||
[ACCESS_PROVIDER_AWS, "common.provider.aws", "/imgs/providers/aws.svg", "apply"],
|
||||
[ACCESS_PROVIDER_CLOUDFLARE, "common.provider.cloudflare", "/imgs/providers/cloudflare.svg", "apply"],
|
||||
[ACCESS_PROVIDER_NAMEDOTCOM, "common.provider.namedotcom", "/imgs/providers/namedotcom.svg", "apply"],
|
||||
[ACCESS_PROVIDER_NAMESILO, "common.provider.namesilo", "/imgs/providers/namesilo.svg", "apply"],
|
||||
[ACCESS_PROVIDER_GODADDY, "common.provider.godaddy", "/imgs/providers/godaddy.svg", "apply"],
|
||||
[ACCESS_PROVIDER_POWERDNS, "common.provider.powerdns", "/imgs/providers/powerdns.svg", "apply"],
|
||||
[ACCESS_PROVIDER_ACMEHTTPREQ, "common.provider.acmehttpreq", "/imgs/providers/acmehttpreq.svg", "apply"],
|
||||
].map(([type, name, icon, usage]) => [type, { type, name, icon, usage: usage as AccessUsageType }])
|
||||
);
|
||||
|
||||
export type DeployProvider = {
|
||||
type: string;
|
||||
name: string;
|
||||
icon: string;
|
||||
provider: AccessProvider["type"];
|
||||
};
|
||||
|
||||
export const deployProvidersMap: Map<DeployProvider["type"], DeployProvider> = new Map(
|
||||
[
|
||||
/*
|
||||
注意:此处的顺序决定显示在前端的顺序。
|
||||
NOTICE: The following order determines the order displayed at the frontend.
|
||||
*/
|
||||
[`${ACCESS_PROVIDER_LOCAL}`, "common.provider.local"],
|
||||
[`${ACCESS_PROVIDER_SSH}`, "common.provider.ssh"],
|
||||
[`${ACCESS_PROVIDER_WEBHOOK}`, "common.provider.webhook"],
|
||||
[`${ACCESS_PROVIDER_KUBERNETES}-secret`, "common.provider.kubernetes.secret"],
|
||||
[`${ACCESS_PROVIDER_ALIYUN}-oss`, "common.provider.aliyun.oss"],
|
||||
[`${ACCESS_PROVIDER_ALIYUN}-cdn`, "common.provider.aliyun.cdn"],
|
||||
[`${ACCESS_PROVIDER_ALIYUN}-dcdn`, "common.provider.aliyun.dcdn"],
|
||||
[`${ACCESS_PROVIDER_ALIYUN}-clb`, "common.provider.aliyun.clb"],
|
||||
[`${ACCESS_PROVIDER_ALIYUN}-alb`, "common.provider.aliyun.alb"],
|
||||
[`${ACCESS_PROVIDER_ALIYUN}-nlb`, "common.provider.aliyun.nlb"],
|
||||
[`${ACCESS_PROVIDER_TENCENTCLOUD}-cdn`, "common.provider.tencentcloud.cdn"],
|
||||
[`${ACCESS_PROVIDER_TENCENTCLOUD}-ecdn`, "common.provider.tencentcloud.ecdn"],
|
||||
[`${ACCESS_PROVIDER_TENCENTCLOUD}-clb`, "common.provider.tencentcloud.clb"],
|
||||
[`${ACCESS_PROVIDER_TENCENTCLOUD}-cos`, "common.provider.tencentcloud.cos"],
|
||||
[`${ACCESS_PROVIDER_TENCENTCLOUD}-eo`, "common.provider.tencentcloud.eo"],
|
||||
[`${ACCESS_PROVIDER_HUAWEICLOUD}-cdn`, "common.provider.huaweicloud.cdn"],
|
||||
[`${ACCESS_PROVIDER_HUAWEICLOUD}-elb`, "common.provider.huaweicloud.elb"],
|
||||
[`${ACCESS_PROVIDER_BAIDUCLOUD}-cdn`, "common.provider.baiducloud.cdn"],
|
||||
[`${ACCESS_PROVIDER_VOLCENGINE}-cdn`, "common.provider.volcengine.cdn"],
|
||||
[`${ACCESS_PROVIDER_VOLCENGINE}-live`, "common.provider.volcengine.live"],
|
||||
[`${ACCESS_PROVIDER_QINIU}-cdn`, "common.provider.qiniu.cdn"],
|
||||
[`${ACCESS_PROVIDER_DOGECLOUD}-cdn`, "common.provider.dogecloud.cdn"],
|
||||
[`${ACCESS_PROVIDER_BYTEPLUS}-cdn`, "common.provider.byteplus.cdn"],
|
||||
].map(([type, name]) => [type, { type, name, icon: accessProvidersMap.get(type.split("-")[0])!.icon, provider: type.split("-")[0] }])
|
||||
);
|
@ -2,7 +2,7 @@ import { produce } from "immer";
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
import i18n from "@/i18n";
|
||||
import { deployTargets } from "./domain";
|
||||
import { deployProvidersMap } from "./provider";
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
@ -346,7 +346,6 @@ export const getWorkflowOutputBeforeId = (node: WorkflowNode | WorkflowBranchNod
|
||||
|
||||
if (isWorkflowBranchNode(current)) {
|
||||
const currentLength = output.length;
|
||||
console.log(currentLength);
|
||||
for (const branch of current.branches) {
|
||||
if (traverse(branch, output)) {
|
||||
return true;
|
||||
@ -424,7 +423,7 @@ export type WorkflowNodeDropdwonItemIcon = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
const workflowNodeDropdownDeployList: WorkflowNodeDropdwonItem[] = deployTargets.map((item) => {
|
||||
const workflowNodeDropdownDeployList: WorkflowNodeDropdwonItem[] = Array.from(deployProvidersMap.values()).map((item) => {
|
||||
return {
|
||||
type: WorkflowNodeType.Apply,
|
||||
providerType: item.type,
|
||||
|
@ -5,6 +5,8 @@ import nlsSettings from "./nls.settings.json";
|
||||
import nlsDomain from "./nls.domain.json";
|
||||
import nlsAccess from "./nls.access.json";
|
||||
import nlsWorkflow from "./nls.workflow.json";
|
||||
import nlsWorkflowNodes from "./nls.workflow.nodes.json";
|
||||
import nlsWorkflowRuns from "./nls.workflow.runs.json";
|
||||
import nlsCertificate from "./nls.certificate.json";
|
||||
|
||||
export default Object.freeze({
|
||||
@ -15,5 +17,7 @@ export default Object.freeze({
|
||||
...nlsDomain,
|
||||
...nlsAccess,
|
||||
...nlsWorkflow,
|
||||
...nlsWorkflowNodes,
|
||||
...nlsWorkflowRuns,
|
||||
...nlsCertificate,
|
||||
});
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
"access.action.add": "Create Authorization",
|
||||
"access.action.edit": "Edit Authorization",
|
||||
"access.action.copy": "Copy Authorization",
|
||||
"access.action.duplicate": "Duplicate Authorization",
|
||||
"access.action.delete": "Delete Authorization",
|
||||
"access.action.delete.confirm": "Are you sure to delete this authorization?",
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
"access.form.aws_secret_access_key.placeholder": "Please enter AWS Secret Access Key",
|
||||
"access.form.aws_secret_access_key.tooltip": "For more information, see <a href=\"https://docs.aws.amazon.com/en_us/IAM/latest/UserGuide/id_credentials_access-keys.html\" target=\"_blank\">https://docs.aws.amazon.com/en_us/IAM/latest/UserGuide/id_credentials_access-keys.html</a>",
|
||||
"access.form.aws_region.label": "AWS Region",
|
||||
"access.form.aws_region.placeholder": "Please enter AWS Region (example: us-east-1)",
|
||||
"access.form.aws_region.placeholder": "Please enter AWS Region (e.g. us-east-1)",
|
||||
"access.form.aws_region.tooltip": "For more information, see <a href=\"https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints\" target=\"_blank\">https://docs.aws.amazon.com/en_us/general/latest/gr/rande.html#regional-endpoints</a>",
|
||||
"access.form.aws_hosted_zone_id.label": "AWS Hosted Zone ID",
|
||||
"access.form.aws_hosted_zone_id.placeholder": "Please enter AWS Hosted Zone ID",
|
||||
@ -85,7 +85,7 @@
|
||||
"access.form.huaweicloud_secret_access_key.placeholder": "Please enter Huawei Cloud Secret Access Key",
|
||||
"access.form.huaweicloud_secret_access_key.tooltip": "For more information, see <a href=\"https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html\" target=\"_blank\">https://support.huaweicloud.com/intl/en-us/usermanual-ca/ca_01_0003.html</a>",
|
||||
"access.form.huaweicloud_region.label": "Huawei Cloud Region",
|
||||
"access.form.huaweicloud_region.placeholder": "Please enter Huawei Cloud Region (example: cn-north-1)",
|
||||
"access.form.huaweicloud_region.placeholder": "Please enter Huawei Cloud Region (e.g. cn-north-1)",
|
||||
"access.form.huaweicloud_region.tooltip": "For more information, see <a href=\"https://console-intl.huaweicloud.com/apiexplorer/#/endpoint?locale=en-us\" target=\"_blank\">https://console-intl.huaweicloud.com/apiexplorer/#/endpoint</a>",
|
||||
"access.form.k8s_kubeconfig.label": "KubeConfig",
|
||||
"access.form.k8s_kubeconfig.placeholder": "Please enter KubeConfig file",
|
||||
|
@ -29,10 +29,10 @@
|
||||
|
||||
"common.errmsg.string_max": "Please enter no more than {{max}} characters",
|
||||
"common.errmsg.email_invalid": "Please enter a valid email address",
|
||||
"common.errmsg.domain_invalid": "Please enter domain",
|
||||
"common.errmsg.host_invalid": "Please enter a valid domain name or IP",
|
||||
"common.errmsg.domain_invalid": "Please enter a valid domain name",
|
||||
"common.errmsg.host_invalid": "Please enter a valid domain name or IP address",
|
||||
"common.errmsg.port_invalid": "Please enter a valid port",
|
||||
"common.errmsg.ip_invalid": "Please enter a valid IP",
|
||||
"common.errmsg.ip_invalid": "Please enter a valid IP address",
|
||||
"common.errmsg.url_invalid": "Please enter a valid URL",
|
||||
|
||||
"common.provider.acmehttpreq": "Http Request (ACME Proxy)",
|
||||
|
@ -29,59 +29,6 @@
|
||||
"workflow.baseinfo.form.description.label": "Description",
|
||||
"workflow.baseinfo.form.description.placeholder": "Please enter description",
|
||||
|
||||
"workflow.nodes.start.form.trigger.label": "Trigger",
|
||||
"workflow.nodes.start.form.trigger.placeholder": "Please select trigger",
|
||||
"workflow.nodes.start.form.trigger.tooltip": "Auto: Time triggered based on cron expression.<br>Manual: Manually triggered.",
|
||||
"workflow.nodes.start.form.trigger.option.auto.label": "Auto",
|
||||
"workflow.nodes.start.form.trigger.option.manual.label": "Manual",
|
||||
"workflow.nodes.start.form.trigger_cron.label": "Cron Expression",
|
||||
"workflow.nodes.start.form.trigger_cron.placeholder": "Please enter cron expression",
|
||||
"workflow.nodes.start.form.trigger_cron.errmsg.invalid": "Please enter a valid cron expression",
|
||||
"workflow.nodes.start.form.trigger_cron.tooltip": "Time zone is based on the server.",
|
||||
"workflow.nodes.start.form.trigger_cron.extra": "Expected execution time for the last 5 times:",
|
||||
"workflow.nodes.start.form.trigger_cron_alert.content": "Tips: If you have multiple workflows, it is recommended to set them to run at multiple times of the day instead of always running at specific times.<br><br>Reference links:<br>1. <a href=\"https://letsencrypt.org/docs/rate-limits/\" target=\"_blank\">Let’s Encrypt rate limits</a><br>2. <a href=\"https://letsencrypt.org/docs/faq/#why-should-my-let-s-encrypt-acme-client-run-at-a-random-time\" target=\"_blank\">Why should my Let’s Encrypt (ACME) client run at a random time?</a>",
|
||||
"workflow.nodes.apply.form.domains.label": "Domains",
|
||||
"workflow.nodes.apply.form.domains.placeholder": "Please enter domains (separated by semicolons)",
|
||||
"workflow.nodes.apply.form.domains.tooltip": "Wildcard domain: *.example.com",
|
||||
"workflow.nodes.apply.form.domains.multiple_input_modal.title": "Change Domains",
|
||||
"workflow.nodes.apply.form.domains.multiple_input_modal.placeholder": "Please enter domain",
|
||||
"workflow.nodes.apply.form.email.label": "Contact Email",
|
||||
"workflow.nodes.apply.form.email.placeholder": "Please enter contact email",
|
||||
"workflow.nodes.apply.form.email.tooltip": "Contact information required for SSL certificate application. Please pay attention to the <a href=\"https://letsencrypt.org/docs/rate-limits/\" target=\"_blank\">rate limits</a>.",
|
||||
"workflow.nodes.apply.form.access.label": "DNS Provider Authorization",
|
||||
"workflow.nodes.apply.form.access.placeholder": "Please select an authorization of DNS provider",
|
||||
"workflow.nodes.apply.form.access.tooltip": "Used to manage DNS records during ACME DNS-01 authentication.",
|
||||
"workflow.nodes.apply.form.access.button": "Create",
|
||||
"workflow.nodes.apply.form.advanced_settings.label": "Advanced Settings",
|
||||
"workflow.nodes.apply.form.key_algorithm.label": "Certificate Key Algorithm",
|
||||
"workflow.nodes.apply.form.key_algorithm.placeholder": "Please select certificate key algorithm",
|
||||
"workflow.nodes.apply.form.nameservers.label": "DNS Recursive Nameservers",
|
||||
"workflow.nodes.apply.form.nameservers.placeholder": "Please enter DNS recursive nameservers (separated by semicolons)",
|
||||
"workflow.nodes.apply.form.nameservers.tooltip": "It determines whether to custom DNS recursive nameservers during ACME DNS-01 authentication. If you don't understand this option, just keep it by default.",
|
||||
"workflow.nodes.apply.form.nameservers.multiple_input_modal.title": "Change Nameservers",
|
||||
"workflow.nodes.apply.form.nameservers.multiple_input_modal.placeholder": "Please enter nameserver",
|
||||
"workflow.nodes.apply.form.propagation_timeout.label": "DNS Propagation Timeout",
|
||||
"workflow.nodes.apply.form.propagation_timeout.placeholder": "Please enter DNS propagation timeout",
|
||||
"workflow.nodes.apply.form.propagation_timeout.suffix": "Seconds",
|
||||
"workflow.nodes.apply.form.propagation_timeout.tooltip": "It determines the maximum waiting time for DNS propagation checks during ACME DNS-01 authentication. If you don't understand this option, just keep it by default.",
|
||||
"workflow.nodes.apply.form.disable_follow_cname.label": "Disable CNAME following",
|
||||
"workflow.nodes.apply.form.disable_follow_cname.tooltip": "It determines whether to disable CNAME following during ACME DNS-01 authentication. If you don't understand this option, just keep it by default.<br><a href=\"https://letsencrypt.org/2019/10/09/onboarding-your-customers-with-lets-encrypt-and-acme/#the-advantages-of-a-cname\" target=\"_blank\">Learn more</a>.",
|
||||
"workflow.nodes.notify.form.subject.label": "Subject",
|
||||
"workflow.nodes.notify.form.subject.placeholder": "Please enter subject",
|
||||
"workflow.nodes.notify.form.message.label": "Message",
|
||||
"workflow.nodes.notify.form.message.placeholder": "Please enter message",
|
||||
"workflow.nodes.notify.form.channel.label": "Channel",
|
||||
"workflow.nodes.notify.form.channel.placeholder": "Please select channel",
|
||||
"workflow.nodes.notify.form.channel.button": "Configure",
|
||||
|
||||
"workflow_run.props.id": "ID",
|
||||
"workflow_run.props.status": "Status",
|
||||
"workflow_run.props.status.succeeded": "Succeeded",
|
||||
"workflow_run.props.status.failed": "Failed",
|
||||
"workflow_run.props.trigger": "Trigger",
|
||||
"workflow_run.props.started_at": "Started At",
|
||||
"workflow_run.props.completed_at": "Completed At",
|
||||
|
||||
"workflow.detail.action.save": "Save updates",
|
||||
"workflow.detail.action.save.failed": "Save failed",
|
||||
"workflow.detail.action.save.failed.uncompleted": "Please complete the orchestration and publish the changes first",
|
||||
|
269
ui/src/i18n/locales/en/nls.workflow.nodes.json
Normal file
269
ui/src/i18n/locales/en/nls.workflow.nodes.json
Normal file
@ -0,0 +1,269 @@
|
||||
{
|
||||
"workflow_node.start.form.trigger.label": "Trigger",
|
||||
"workflow_node.start.form.trigger.placeholder": "Please select trigger",
|
||||
"workflow_node.start.form.trigger.tooltip": "Auto: Time triggered based on cron expression.<br>Manual: Manually triggered.",
|
||||
"workflow_node.start.form.trigger.option.auto.label": "Auto",
|
||||
"workflow_node.start.form.trigger.option.manual.label": "Manual",
|
||||
"workflow_node.start.form.trigger_cron.label": "Cron Expression",
|
||||
"workflow_node.start.form.trigger_cron.placeholder": "Please enter cron expression",
|
||||
"workflow_node.start.form.trigger_cron.errmsg.invalid": "Please enter a valid cron expression",
|
||||
"workflow_node.start.form.trigger_cron.tooltip": "Time zone is based on the server.",
|
||||
"workflow_node.start.form.trigger_cron.extra": "Expected execution time for the last 5 times:",
|
||||
"workflow_node.start.form.trigger_cron_alert.content": "Tips: If you have multiple workflows, it is recommended to set them to run at multiple times of the day instead of always running at specific times.<br><br>Reference links:<br>1. <a href=\"https://letsencrypt.org/docs/rate-limits/\" target=\"_blank\">Let’s Encrypt rate limits</a><br>2. <a href=\"https://letsencrypt.org/docs/faq/#why-should-my-let-s-encrypt-acme-client-run-at-a-random-time\" target=\"_blank\">Why should my Let’s Encrypt (ACME) client run at a random time?</a>",
|
||||
|
||||
"workflow_node.apply.form.domains.label": "Domains",
|
||||
"workflow_node.apply.form.domains.placeholder": "Please enter domains (separated by semicolons)",
|
||||
"workflow_node.apply.form.domains.tooltip": "Wildcard domain: *.example.com",
|
||||
"workflow_node.apply.form.domains.multiple_input_modal.title": "Change Domains",
|
||||
"workflow_node.apply.form.domains.multiple_input_modal.placeholder": "Please enter domain",
|
||||
"workflow_node.apply.form.email.label": "Contact Email",
|
||||
"workflow_node.apply.form.email.placeholder": "Please enter contact email",
|
||||
"workflow_node.apply.form.email.tooltip": "Contact information required for SSL certificate application. Please pay attention to the <a href=\"https://letsencrypt.org/docs/rate-limits/\" target=\"_blank\">rate limits</a>.",
|
||||
"workflow_node.apply.form.access.label": "DNS Provider Authorization",
|
||||
"workflow_node.apply.form.access.placeholder": "Please select an authorization of DNS provider",
|
||||
"workflow_node.apply.form.access.tooltip": "Used to manage DNS records during ACME DNS-01 authentication.",
|
||||
"workflow_node.apply.form.access.button": "Create",
|
||||
"workflow_node.apply.form.advanced_config.label": "Advanced Settings",
|
||||
"workflow_node.apply.form.key_algorithm.label": "Certificate Key Algorithm",
|
||||
"workflow_node.apply.form.key_algorithm.placeholder": "Please select certificate key algorithm",
|
||||
"workflow_node.apply.form.nameservers.label": "DNS Recursive Nameservers (Optional)",
|
||||
"workflow_node.apply.form.nameservers.placeholder": "Please enter DNS recursive nameservers (separated by semicolons)",
|
||||
"workflow_node.apply.form.nameservers.tooltip": "It determines whether to custom DNS recursive nameservers during ACME DNS-01 authentication. If you don't understand this option, just keep it by default.",
|
||||
"workflow_node.apply.form.nameservers.multiple_input_modal.title": "Change DNS Recursive Nameservers",
|
||||
"workflow_node.apply.form.nameservers.multiple_input_modal.placeholder": "Please enter DNS recursive nameserver",
|
||||
"workflow_node.apply.form.propagation_timeout.label": "DNS Propagation Timeout (Optional)",
|
||||
"workflow_node.apply.form.propagation_timeout.placeholder": "Please enter DNS propagation timeout",
|
||||
"workflow_node.apply.form.propagation_timeout.suffix": "Seconds",
|
||||
"workflow_node.apply.form.propagation_timeout.tooltip": "It determines the maximum waiting time for DNS propagation checks during ACME DNS-01 authentication. If you don't understand this option, just keep it by default.",
|
||||
"workflow_node.apply.form.disable_follow_cname.label": "Disable CNAME following",
|
||||
"workflow_node.apply.form.disable_follow_cname.tooltip": "It determines whether to disable CNAME following during ACME DNS-01 authentication. If you don't understand this option, just keep it by default.<br><a href=\"https://letsencrypt.org/2019/10/09/onboarding-your-customers-with-lets-encrypt-and-acme/#the-advantages-of-a-cname\" target=\"_blank\">Learn more</a>.",
|
||||
|
||||
"workflow_node.deploy.form.provider_type.label": "Deploy Target",
|
||||
"workflow_node.deploy.form.provider_type.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.tooltip": "Used to deploy certificates.",
|
||||
"workflow_node.deploy.form.provider_access.button": "Create",
|
||||
"workflow_node.deploy.form.certificate.label": "Certificate",
|
||||
"workflow_node.deploy.form.certificate.placeholder": "Please select certificate",
|
||||
"workflow_node.deploy.form.certificate.tooltip": "The certificate to be deployed comes from the previous application stage node.",
|
||||
"workflow_node.deploy.form.aliyun_alb_resource_type.label": "Resource Type",
|
||||
"workflow_node.deploy.form.aliyun_alb_resource_type.placeholder": "Please select resource type",
|
||||
"workflow_node.deploy.form.aliyun_alb_resource_type.option.loadbalancer.label": "ALB Load Balancer",
|
||||
"workflow_node.deploy.form.aliyun_alb_resource_type.option.listener.label": "ALB Listener",
|
||||
"workflow_node.deploy.form.aliyun_alb_region.label": "Aliyun Region",
|
||||
"workflow_node.deploy.form.aliyun_alb_region.placeholder": "Please enter Aliyun region (e.g. cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_alb_region.tooltip": "For more information, see <a href=\"https://www.alibabacloud.com/help/en/slb/application-load-balancer/product-overview/supported-regions-and-zones\" target=\"_blank\">https://www.alibabacloud.com/help/en/slb/application-load-balancer/product-overview/supported-regions-and-zones</a>",
|
||||
"workflow_node.deploy.form.aliyun_alb_loadbalancer_id.label": "Aliyun ALB Load Balancer ID",
|
||||
"workflow_node.deploy.form.aliyun_alb_loadbalancer_id.placeholder": "Please enter Aliyun ALB load balancer ID",
|
||||
"workflow_node.deploy.form.aliyun_alb_loadbalancer_id.tooltip": "For more information, see <a href=\"https://slb.console.aliyun.com/alb\" target=\"_blank\">https://slb.console.aliyun.com/alb</a>",
|
||||
"workflow_node.deploy.form.aliyun_alb_listener_id.label": "Aliyun ALB Listener ID",
|
||||
"workflow_node.deploy.form.aliyun_alb_listener_id.placeholder": "Please enter Aliyun ALB listener ID",
|
||||
"workflow_node.deploy.form.aliyun_alb_listener_id.tooltip": "For more information, see <a href=\"https://slb.console.aliyun.com/alb\" target=\"_blank\">https://slb.console.aliyun.com/alb</a>",
|
||||
"workflow_node.deploy.form.aliyun_clb_resource_type.label": "Resource Type",
|
||||
"workflow_node.deploy.form.aliyun_clb_resource_type.placeholder": "Please select resource type",
|
||||
"workflow_node.deploy.form.aliyun_clb_resource_type.option.loadbalancer.label": "CLB Load Balancer",
|
||||
"workflow_node.deploy.form.aliyun_clb_resource_type.option.listener.label": "CLB Listener",
|
||||
"workflow_node.deploy.form.aliyun_clb_region.label": "Aliyun Region",
|
||||
"workflow_node.deploy.form.aliyun_clb_region.placeholder": "Please enter Aliyun region (e.g. cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_clb_region.tooltip": "For more information, see <a href=\"https://www.alibabacloud.com/help/en/slb/classic-load-balancer/product-overview/regions-that-support-clb\" target=\"_blank\">https://www.alibabacloud.com/help/en/slb/classic-load-balancer/product-overview/regions-that-support-clb</a>",
|
||||
"workflow_node.deploy.form.aliyun_clb_loadbalancer_id.label": "Aliyun CLB Load Balancer ID",
|
||||
"workflow_node.deploy.form.aliyun_clb_loadbalancer_id.placeholder": "Please enter Aliyun CLB load balancer ID",
|
||||
"workflow_node.deploy.form.aliyun_clb_loadbalancer_id.tooltip": "For more information, see <a href=\"https://slb.console.aliyun.com/clb\" target=\"_blank\">https://slb.console.aliyun.com/clb</a>",
|
||||
"workflow_node.deploy.form.aliyun_clb_listener_port.label": "Aliyun CLB Listener Port",
|
||||
"workflow_node.deploy.form.aliyun_clb_listener_port.placeholder": "Please enter Aliyun CLB listener port",
|
||||
"workflow_node.deploy.form.aliyun_clb_listener_port.tooltip": "For more information, see <a href=\"https://slb.console.aliyun.com/clb\" target=\"_blank\">https://slb.console.aliyun.com/clb</a>",
|
||||
"workflow_node.deploy.form.aliyun_cdn_domain.label": "Aliyun CDN Domain",
|
||||
"workflow_node.deploy.form.aliyun_cdn_domain.placeholder": "Please enter Aliyun CDN domain name",
|
||||
"workflow_node.deploy.form.aliyun_cdn_domain.tooltip": "For more information, see <a href=\"https://cdn.console.aliyun.com\" target=\"_blank\">https://cdn.console.aliyun.com</a>",
|
||||
"workflow_node.deploy.form.aliyun_dcdn_domain.label": "Aliyun DCDN Domain",
|
||||
"workflow_node.deploy.form.aliyun_dcdn_domain.placeholder": "Please enter Aliyun DCDN domain name",
|
||||
"workflow_node.deploy.form.aliyun_dcdn_domain.tooltip": "For more information, see <a href=\"https://dcdn.console.aliyun.com\" target=\"_blank\">https://dcdn.console.aliyun.com</a>",
|
||||
"workflow_node.deploy.form.aliyun_nlb_resource_type.label": "Resource Type",
|
||||
"workflow_node.deploy.form.aliyun_nlb_resource_type.placeholder": "Please select resource type",
|
||||
"workflow_node.deploy.form.aliyun_nlb_resource_type.option.loadbalancer.label": "NLB Load Balancer",
|
||||
"workflow_node.deploy.form.aliyun_nlb_resource_type.option.listener.label": "NLB Listener",
|
||||
"workflow_node.deploy.form.aliyun_nlb_region.label": "Aliyun Region",
|
||||
"workflow_node.deploy.form.aliyun_nlb_region.placeholder": "Please enter Aliyun region (e.g. cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_nlb_region.tooltip": "For more information, see <a href=\"https://www.alibabacloud.com/help/en/slb/network-load-balancer/product-overview/regions-that-support-nlb\" target=\"_blank\">https://www.alibabacloud.com/help/en/slb/network-load-balancer/product-overview/regions-that-support-nlb</a>",
|
||||
"workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.label": "Aliyun NLB Load Balancer ID",
|
||||
"workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.placeholder": "Please enter Aliyun NLB load balancer ID",
|
||||
"workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.tooltip": "For more information, see <a href=\"https://slb.console.aliyun.com/nlb\" target=\"_blank\">https://slb.console.aliyun.com/nlb</a>",
|
||||
"workflow_node.deploy.form.aliyun_nlb_listener_id.label": "Aliyun NLB Listener ID",
|
||||
"workflow_node.deploy.form.aliyun_nlb_listener_id.placeholder": "Please enter Aliyun NLB listener ID",
|
||||
"workflow_node.deploy.form.aliyun_nlb_listener_id.tooltip": "For more information, see <a href=\"https://slb.console.aliyun.com/nlb\" target=\"_blank\">https://slb.console.aliyun.com/nlb</a>",
|
||||
"workflow_node.deploy.form.aliyun_oss_endpoint.label": "Aliyun OSS Endpoint",
|
||||
"workflow_node.deploy.form.aliyun_oss_endpoint.placeholder": "Please enter Aliyun OSS endpoint",
|
||||
"workflow_node.deploy.form.aliyun_oss_endpoint.tooltip": "For more information, see <a href=\"https://www.alibabacloud.com/help/en/oss/user-guide/regions-and-endpoints\" target=\"_blank\">https://www.alibabacloud.com/help/en/oss/user-guide/regions-and-endpoints</a>",
|
||||
"workflow_node.deploy.form.aliyun_oss_bucket.label": "Aliyun OSS Bucket",
|
||||
"workflow_node.deploy.form.aliyun_oss_bucket.placeholder": "Please enter Aliyun OSS bucket name",
|
||||
"workflow_node.deploy.form.aliyun_oss_bucket.tooltip": "For more information, see <a href=\"https://oss.console.aliyun.com\" target=\"_blank\">https://oss.console.aliyun.com</a>",
|
||||
"workflow_node.deploy.form.aliyun_oss_domain.label": "Aliyun OSS Domain",
|
||||
"workflow_node.deploy.form.aliyun_oss_domain.placeholder": "Please enter Aliyun OSS domain name",
|
||||
"workflow_node.deploy.form.aliyun_oss_domain.tooltip": "For more information, see <a href=\"https://oss.console.aliyun.com\" target=\"_blank\">https://oss.console.aliyun.com</a>",
|
||||
"workflow_node.deploy.form.baiducloud_cdn_domain.label": "Baidu Cloud CDN Domain",
|
||||
"workflow_node.deploy.form.baiducloud_cdn_domain.placeholder": "Please enter Baidu Cloud CDN domain name",
|
||||
"workflow_node.deploy.form.baiducloud_cdn_domain.tooltip": "For more information, see <a href=\"https://console.bce.baidu.com/cdn\" target=\"_blank\">https://console.bce.baidu.com/cdn</a>",
|
||||
"workflow_node.deploy.form.byteplus_cdn_domain.label": "BytePlus CDN Domain",
|
||||
"workflow_node.deploy.form.byteplus_cdn_domain.placeholder": "Please enter BytePlus CDN domain name",
|
||||
"workflow_node.deploy.form.byteplus_cdn_domain.tooltip": "For more information, see <a href=\"https://console.byteplus.com/cdn\" target=\"_blank\">https://console.byteplus.com/cdn</a>",
|
||||
"workflow_node.deploy.form.dogecloud_cdn_domain.label": "Doge Cloud CDN Domain",
|
||||
"workflow_node.deploy.form.dogecloud_cdn_domain.placeholder": "Please enter Doge Cloud CDN domain name",
|
||||
"workflow_node.deploy.form.dogecloud_cdn_domain.tooltip": "For more information, see <a href=\"https://console.dogecloud.com/\" target=\"_blank\">https://console.dogecloud.com/</a>",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_region.label": "Huawei Cloud Region",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_region.placeholder": "Please enter Huawei Cloud region (e.g. cn-north-1)",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_region.tooltip": "For more information, see <a href=\"https://console-intl.huaweicloud.com/apiexplorer/#/endpoint?locale=en-us\" target=\"_blank\">https://console-intl.huaweicloud.com/apiexplorer/#/endpoint</a>",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_domain.label": "Huawei Cloud CDN Domain",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_domain.placeholder": "Please enter Huawei Cloud CDN domain name",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_domain.tooltip": "For more information, see <a href=\"https://console-intl.huaweicloud.com/cdn\" target=\"_blank\">https://console-intl.huaweicloud.com/cdn</a>",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_resource_type.label": "Resource Type",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_resource_type.placeholder": "Please select resource type",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_resource_type.option.certificate.label": "ELB Certificate",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_resource_type.option.loadbalancer.label": "ELB Load Balancer",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_resource_type.option.listener.label": "ELB Listener",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_region.label": "Huawei Cloud Region",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_region.placeholder": "Please enter Huawei Cloud region (e.g. cn-north-1)",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_region.tooltip": "For more information, see <a href=\"https://console-intl.huaweicloud.com/apiexplorer/#/endpoint?locale=en-us\" target=\"_blank\">https://console-intl.huaweicloud.com/apiexplorer/#/endpoint</a>",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_certificate_id.label": "Huawei Cloud ELB Certificate ID",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_certificate_id.placeholder": "Please enter Huawei Cloud ELB certificate ID",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_certificate_id.tooltip": "For more information, see <a href=\"https://console-intl.huaweicloud.com/vpc/#/elb/elbCert\" target=\"_blank\">https://console-intl.huaweicloud.com/vpc/#/elb/elbCert</a>",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_loadbalancer_id.label": "Huawei Cloud ELB Load Balancer ID",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_loadbalancer_id.placeholder": "Please enter Huawei Cloud ELB load balancer ID",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_loadbalancer_id.tooltip": "For more information, see <a href=\"https://console-intl.huaweicloud.com/vpc/#/elb/list/grid\" target=\"_blank\">https://console-intl.huaweicloud.com/vpc/#/elb/list/grid</a>",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_listener_id.label": "Huawei Cloud ELB Listener ID",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_listener_id.placeholder": "Please enter Huawei Cloud ELB listener ID",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_listener_id.tooltip": "For more information, see <a href=\"https://console-intl.huaweicloud.com/vpc/#/elb/list/grid\" target=\"_blank\">https://console-intl.huaweicloud.com/vpc/#/elb/list/grid</a>",
|
||||
"workflow_node.deploy.form.k8s_namespace.label": "Kubernetes Namespace",
|
||||
"workflow_node.deploy.form.k8s_namespace.placeholder": "Please enter Kubernetes namespace",
|
||||
"workflow_node.deploy.form.k8s_namespace.tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/\" target=\"_blank\">https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/</a>",
|
||||
"workflow_node.deploy.form.k8s_secret_name.label": "Kubernetes Secret Name",
|
||||
"workflow_node.deploy.form.k8s_secret_name.placeholder": "Please enter Kubernetes secret name",
|
||||
"workflow_node.deploy.form.k8s_secret_name.tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/secret/</a>",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_crt.label": "Kubernetes Secret Data Key for Certificate",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_crt.placeholder": "Please enter secret data key for certificate",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_crt.tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/secret/</a>",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_key.label": "Kubernetes Secret Data Key for Private Key",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_key.placeholder": "Please enter secret data key for private key",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_key.tooltip": "For more information, see <a href=\"https://kubernetes.io/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/docs/concepts/configuration/secret/</a>",
|
||||
"workflow_node.deploy.form.local_format.label": "File Format",
|
||||
"workflow_node.deploy.form.local_format.placeholder": "Please select file format",
|
||||
"workflow_node.deploy.form.local_format.option.pem.label": "PEM (*.pem, *.crt, *.key)",
|
||||
"workflow_node.deploy.form.local_format.option.pfx.label": "PFX (*.pfx)",
|
||||
"workflow_node.deploy.form.local_format.option.jks.label": "JKS (*.jks)",
|
||||
"workflow_node.deploy.form.local_cert_path.label": "Certificate File Saving Path",
|
||||
"workflow_node.deploy.form.local_cert_path.placeholder": "Please enter saving path for certificate file",
|
||||
"workflow_node.deploy.form.local_cert_path.tooltip": "Note that the path should include the complete file name, not just the directory.",
|
||||
"workflow_node.deploy.form.local_key_path.label": "Private Key File Saving Path",
|
||||
"workflow_node.deploy.form.local_key_path.placeholder": "Please enter saving path for private key file",
|
||||
"workflow_node.deploy.form.local_key_path.tooltip": "Note that the path should include the complete file name, not just the directory.",
|
||||
"workflow_node.deploy.form.local_pfx_password.label": "PFX Output Password",
|
||||
"workflow_node.deploy.form.local_pfx_password.placeholder": "Please enter PFX output password",
|
||||
"workflow_node.deploy.form.local_jks_alias.label": "JKS Alias (KeyStore Alias)",
|
||||
"workflow_node.deploy.form.local_jks_alias.placeholder": "Please enter JKS alias",
|
||||
"workflow_node.deploy.form.local_jks_keypass.label": "JKS Key Password (KeyStore Keypass)",
|
||||
"workflow_node.deploy.form.local_jks_keypass.placeholder": "Please enter JKS key password",
|
||||
"workflow_node.deploy.form.local_jks_storepass.label": "JKS Store Password (KeyStore Storepass)",
|
||||
"workflow_node.deploy.form.local_jks_storepass.placeholder": "Please enter JKS store password",
|
||||
"workflow_node.deploy.form.local_shell_env.label": "Shell",
|
||||
"workflow_node.deploy.form.local_shell_env.placeholder": "Please select shell environment",
|
||||
"workflow_node.deploy.form.local_shell_env.option.sh.label": "POSIX Bash (on Linux / macOS)",
|
||||
"workflow_node.deploy.form.local_shell_env.option.cmd.label": "CMD (on Windows)",
|
||||
"workflow_node.deploy.form.local_shell_env.option.powershell.label": "PowerShell (on Windows)",
|
||||
"workflow_node.deploy.form.local_pre_command.label": "Pre-Command",
|
||||
"workflow_node.deploy.form.local_pre_command.placeholder": "Please enter command to be executed before saving files",
|
||||
"workflow_node.deploy.form.local_post_command.label": "Post-Command",
|
||||
"workflow_node.deploy.form.local_post_command.placeholder": "Please enter command to be executed after saving files",
|
||||
"workflow_node.deploy.form.local_preset_scripts.button": "Use Preset Scripts",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.reload_nginx.label": "POSIX Bash - Reload Nginx",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.binding_iis.label": "PowerShell - Binding IIS",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.binding_netsh.label": "PowerShell - Binding netsh",
|
||||
"workflow_node.deploy.form.qiniu_cdn_domain.label": "Qiniu CDN Domain",
|
||||
"workflow_node.deploy.form.qiniu_cdn_domain.placeholder": "Please enter Qiniu CDN domain name",
|
||||
"workflow_node.deploy.form.qiniu_cdn_domain.tooltip": "For more information, see <a href=\"https://portal.qiniu.com/\" target=\"_blank\">https://portal.qiniu.com/</a>",
|
||||
"workflow_node.deploy.form.ssh_format.label": "File Format",
|
||||
"workflow_node.deploy.form.ssh_format.placeholder": "Please select file format",
|
||||
"workflow_node.deploy.form.ssh_format.option.pem.label": "PEM (*.pem, *.crt, *.key)",
|
||||
"workflow_node.deploy.form.ssh_format.option.pfx.label": "PFX (*.pfx)",
|
||||
"workflow_node.deploy.form.ssh_format.option.jks.label": "JKS (*.jks)",
|
||||
"workflow_node.deploy.form.ssh_cert_path.label": "Certificate File Uploading Path",
|
||||
"workflow_node.deploy.form.ssh_cert_path.placeholder": "Please enter uploading path for certificate file",
|
||||
"workflow_node.deploy.form.ssh_cert_path.tooltip": "Note that the path should include the complete file name, not just the directory.",
|
||||
"workflow_node.deploy.form.ssh_key_path.label": "Private Key File Uploading Path",
|
||||
"workflow_node.deploy.form.ssh_key_path.placeholder": "Please enter uploading path for private key file",
|
||||
"workflow_node.deploy.form.ssh_key_path.tooltip": "Note that the path should include the complete file name, not just the directory.",
|
||||
"workflow_node.deploy.form.ssh_pfx_password.label": "PFX Output Password",
|
||||
"workflow_node.deploy.form.ssh_pfx_password.placeholder": "Please enter PFX output password",
|
||||
"workflow_node.deploy.form.ssh_jks_alias.label": "JKS Alias (KeyStore Alias)",
|
||||
"workflow_node.deploy.form.ssh_jks_alias.placeholder": "Please enter JKS alias",
|
||||
"workflow_node.deploy.form.ssh_jks_keypass.label": "JKS Key Password (KeyStore Keypass)",
|
||||
"workflow_node.deploy.form.ssh_jks_keypass.placeholder": "Please enter JKS key password",
|
||||
"workflow_node.deploy.form.ssh_jks_storepass.label": "JKS Store Password (KeyStore Storepass)",
|
||||
"workflow_node.deploy.form.ssh_jks_storepass.placeholder": "Please enter JKS store password",
|
||||
"workflow_node.deploy.form.ssh_shell_env.label": "Shell",
|
||||
"workflow_node.deploy.form.ssh_shell_env.value": "POSIX Bash (on Linux / macOS)",
|
||||
"workflow_node.deploy.form.ssh_pre_command.label": "Pre-Command",
|
||||
"workflow_node.deploy.form.ssh_pre_command.placeholder": "Please enter command to be executed before uploading files",
|
||||
"workflow_node.deploy.form.ssh_post_command.label": "Post-Command",
|
||||
"workflow_node.deploy.form.ssh_post_command.placeholder": "Please enter command to be executed after uploading files",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.button": "Use Preset Scripts",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.reload_nginx.label": "POSIX Bash - Reload Nginx",
|
||||
"workflow_node.deploy.form.tencentcloud_cdn_domain.label": "Tencent Cloud CDN Domain",
|
||||
"workflow_node.deploy.form.tencentcloud_cdn_domain.placeholder": "Please enter Tencent Cloud CDN domain name",
|
||||
"workflow_node.deploy.form.tencentcloud_cdn_domain.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/cdn\" target=\"_blank\">https://console.tencentcloud.com/cdn</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_resource_type.label": "Resource Type",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_resource_type.placeholder": "Please select resource type",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.ssl_deploy.label": "Through SSL Deploy",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.loadbalancer.label": "CLB Load Balancer",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.listener.label": "CLB Listener",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.ruledomain.label": "CLB Rule Domain",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_region.label": "Tencent Cloud Region",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_region.placeholder": "Please enter Tencent Cloud region (e.g. ap-guangzhou)",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_region.tooltip": "For more information, see <a href=\"https://www.tencentcloud.com/document/product/214/13629\" target=\"_blank\">https://www.tencentcloud.com/document/product/214/13629</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.label": "Tencent Cloud CLB Instance ID",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.placeholder": "Please enter Tencent Cloud CLB instance ID",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/clb\" target=\"_blank\">https://console.tencentcloud.com/clb</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_listener_id.label": "Tencent Cloud CLB Listener ID",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_listener_id.placeholder": "Please enter Tencent Cloud CLB listener ID",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_listener_id.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/clb\" target=\"_blank\">https://console.tencentcloud.com/clb</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_snidomain.label": "Tencent Cloud CLB Domain (Optional)",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_snidomain.placeholder": "Please enter Tencent Cloud CLB domain name",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_snidomain.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/clb\" target=\"_blank\">https://console.tencentcloud.com/clb</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_ruledomain.label": "Tencent Cloud CLB Domain",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_ruledomain.placeholder": "Please enter Tencent Cloud CLB domain name",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_ruledomain.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/clb\" target=\"_blank\">https://console.tencentcloud.com/clb</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_region.label": "Tencent Cloud Region",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_region.placeholder": "Please enter Tencent Cloud region (e.g. ap-guangzhou)",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_region.tooltip": "For more information, see <a href=\"https://www.tencentcloud.com/document/product/436/6224\" target=\"_blank\">https://www.tencentcloud.com/document/product/436/6224</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_bucket.label": "Tencent Cloud COS Bucket",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_bucket.placeholder": "Please enter Tencent Cloud COS bucket name",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_bucket.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/cos\" target=\"_blank\">https://console.tencentcloud.com/cos</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_domain.label": "Tencent Cloud COS Domain",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_domain.placeholder": "Please enter Tencent Cloud COS domain name",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_domain.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/cos\" target=\"_blank\">https://console.tencentcloud.com/cos</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_ecdn_domain.label": "Tencent Cloud ECDN Domain",
|
||||
"workflow_node.deploy.form.tencentcloud_ecdn_domain.placeholder": "Please enter Tencent Cloud ECDN domain name",
|
||||
"workflow_node.deploy.form.tencentcloud_ecdn_domain.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/cdn\" target=\"_blank\">https://console.tencentcloud.com/cdn</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_eo_zone_id.label": "Tencent Cloud EdgeOne Zone ID",
|
||||
"workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder": "Please enter Tencent Cloud EdgeOne zone ID",
|
||||
"workflow_node.deploy.form.tencentcloud_eo_zone_id.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/edgeone\" target=\"_blank\">https://console.tencentcloud.com/edgeone</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_eo_domain.label": "Tencent Cloud EdgeOne Domain",
|
||||
"workflow_node.deploy.form.tencentcloud_eo_domain.placeholder": "Please enter Tencent Cloud EdgeOne domain name",
|
||||
"workflow_node.deploy.form.tencentcloud_eo_domain.tooltip": "For more information, see <a href=\"https://console.tencentcloud.com/edgeone\" target=\"_blank\">https://console.tencentcloud.com/edgeone</a>",
|
||||
"workflow_node.deploy.form.volcengine_cdn_domain.label": "VolcEngine CDN Domain",
|
||||
"workflow_node.deploy.form.volcengine_cdn_domain.placeholder": "Please enter VolcEngine CDN domain name",
|
||||
"workflow_node.deploy.form.volcengine_cdn_domain.tooltip": "For more information, see <a href=\"https://console.volcengine.com/cdn/homepage\" target=\"_blank\">https://console.volcengine.com/cdn/homepage</a>",
|
||||
"workflow_node.deploy.form.volcengine_live_domain.label": "VolcEngine Live Streaming Domain",
|
||||
"workflow_node.deploy.form.volcengine_live_domain.placeholder": "Please enter VolcEngine live streaming domain name",
|
||||
"workflow_node.deploy.form.volcengine_live_domain.tooltip": "For more information, see <a href=\"https://console.volcengine.com/live\" target=\"_blank\">https://console.volcengine.com/live</a>",
|
||||
"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.params_config.label": "Parameter Settings",
|
||||
"workflow_node.notify.form.subject.label": "Subject",
|
||||
"workflow_node.notify.form.subject.placeholder": "Please enter subject",
|
||||
"workflow_node.notify.form.message.label": "Message",
|
||||
"workflow_node.notify.form.message.placeholder": "Please enter message",
|
||||
"workflow_node.notify.form.channel.label": "Channel",
|
||||
"workflow_node.notify.form.channel.placeholder": "Please select channel",
|
||||
"workflow_node.notify.form.channel.button": "Configure"
|
||||
}
|
9
ui/src/i18n/locales/en/nls.workflow.runs.json
Normal file
9
ui/src/i18n/locales/en/nls.workflow.runs.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"workflow_run.props.id": "ID",
|
||||
"workflow_run.props.status": "Status",
|
||||
"workflow_run.props.status.succeeded": "Succeeded",
|
||||
"workflow_run.props.status.failed": "Failed",
|
||||
"workflow_run.props.trigger": "Trigger",
|
||||
"workflow_run.props.started_at": "Started At",
|
||||
"workflow_run.props.completed_at": "Completed At"
|
||||
}
|
@ -5,6 +5,8 @@ import nlsSettings from "./nls.settings.json";
|
||||
import nlsDomain from "./nls.domain.json";
|
||||
import nlsAccess from "./nls.access.json";
|
||||
import nlsWorkflow from "./nls.workflow.json";
|
||||
import nlsWorkflowNodes from "./nls.workflow.nodes.json";
|
||||
import nlsWorkflowRuns from "./nls.workflow.runs.json";
|
||||
import nlsCertificate from "./nls.certificate.json";
|
||||
|
||||
export default Object.freeze({
|
||||
@ -15,5 +17,7 @@ export default Object.freeze({
|
||||
...nlsDomain,
|
||||
...nlsAccess,
|
||||
...nlsWorkflow,
|
||||
...nlsWorkflowNodes,
|
||||
...nlsWorkflowRuns,
|
||||
...nlsCertificate,
|
||||
});
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
"access.action.add": "新建授权",
|
||||
"access.action.edit": "编辑授权",
|
||||
"access.action.copy": "复制授权",
|
||||
"access.action.duplicate": "复制授权",
|
||||
"access.action.delete": "删除授权",
|
||||
"access.action.delete.confirm": "确定要删除此授权吗?",
|
||||
|
||||
@ -84,7 +84,7 @@
|
||||
"access.form.huaweicloud_secret_access_key.label": "华为云 Secret Access Key",
|
||||
"access.form.huaweicloud_secret_access_key.placeholder": "请输入华为云 Secret Access Key",
|
||||
"access.form.huaweicloud_secret_access_key.tooltip": "这是什么?请参阅 <a href=\"https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html\" target=\"_blank\">https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html</a>",
|
||||
"access.form.huaweicloud_region.label": "华为云 DNS 产品区域",
|
||||
"access.form.huaweicloud_region.label": "华为云区域",
|
||||
"access.form.huaweicloud_region.placeholder": "请输入华为云区域(例如:cn-north-1)",
|
||||
"access.form.huaweicloud_region.tooltip": "这是什么?请参阅 <a href=\"https://console.huaweicloud.com/apiexplorer/#/endpoint\" target=\"_blank\">https://console.huaweicloud.com/apiexplorer/#/endpoint</a>",
|
||||
"access.form.k8s_kubeconfig.label": "KubeConfig",
|
||||
|
@ -47,7 +47,7 @@
|
||||
"common.provider.baiducloud": "百度智能云",
|
||||
"common.provider.baiducloud.cdn": "百度智能云 - 内容分发网络 CDN",
|
||||
"common.provider.byteplus": "BytePlus",
|
||||
"common.provider.byteplus.cdn": "BytePlus - CDN",
|
||||
"common.provider.byteplus.cdn": "BytePlus - 内容分发网络 CDN",
|
||||
"common.provider.cloudflare": "Cloudflare",
|
||||
"common.provider.dogecloud": "多吉云",
|
||||
"common.provider.dogecloud.cdn": "多吉云 - 内容分发网络 CDN",
|
||||
@ -71,8 +71,8 @@
|
||||
"common.provider.tencentcloud.ecdn": "腾讯云 - 全站加速网络 ECDN",
|
||||
"common.provider.tencentcloud.eo": "腾讯云 - 边缘安全加速平台 EdgeOne",
|
||||
"common.provider.volcengine": "火山引擎",
|
||||
"common.provider.volcengine.cdn": "火山引擎 - CDN",
|
||||
"common.provider.volcengine.live": "火山引擎 - 视频直播",
|
||||
"common.provider.volcengine.cdn": "火山引擎 - 内容分发网络 CDN",
|
||||
"common.provider.volcengine.live": "火山引擎 - 视频直播 Live",
|
||||
"common.provider.webhook": "Webhook",
|
||||
|
||||
"common.notifier.bark": "Bark",
|
||||
|
@ -29,59 +29,6 @@
|
||||
"workflow.baseinfo.form.description.label": "描述",
|
||||
"workflow.baseinfo.form.description.placeholder": "请输入工作流描述",
|
||||
|
||||
"workflow.nodes.start.form.trigger.label": "触发方式",
|
||||
"workflow.nodes.start.form.trigger.placeholder": "请选择触发方式",
|
||||
"workflow.nodes.start.form.trigger.tooltip": "自动触发:基于 Cron 表达式定时触发。<br>手动触发:手动点击执行触发。",
|
||||
"workflow.nodes.start.form.trigger.option.auto.label": "自动触发",
|
||||
"workflow.nodes.start.form.trigger.option.manual.label": "手动触发",
|
||||
"workflow.nodes.start.form.trigger_cron.label": "Cron 表达式",
|
||||
"workflow.nodes.start.form.trigger_cron.placeholder": "请输入 Cron 表达式",
|
||||
"workflow.nodes.start.form.trigger_cron.errmsg.invalid": "请输入正确的 Cron 表达式",
|
||||
"workflow.nodes.start.form.trigger_cron.tooltip": "时区以服务器设置为准。",
|
||||
"workflow.nodes.start.form.trigger_cron.extra": "预计最近 5 次执行时间:",
|
||||
"workflow.nodes.start.form.trigger_cron_alert.content": "小贴士:如果你有多个工作流,建议将它们设置为在一天中的多个时间段运行,而非总是在相同的特定时间。<br><br>参考链接:<br>1. <a href=\"https://letsencrypt.org/zh-cn/docs/rate-limits/\" target=\"_blank\">Let’s Encrypt 速率限制</a><br>2. <a href=\"https://letsencrypt.org/zh-cn/docs/faq/#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E7%9A%84-let-s-encrypt-acme-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%AF%E5%8A%A8%E6%97%B6%E9%97%B4%E5%BA%94%E5%BD%93%E9%9A%8F%E6%9C%BA\" target=\"_blank\">为什么我的 Let’s Encrypt (ACME) 客户端启动时间应当随机?</a>",
|
||||
"workflow.nodes.apply.form.domains.label": "域名",
|
||||
"workflow.nodes.apply.form.domains.placeholder": "请输入域名(多个值请用半角分号隔开)",
|
||||
"workflow.nodes.apply.form.domains.tooltip": "泛域名表示形式为:*.example.com",
|
||||
"workflow.nodes.apply.form.domains.multiple_input_modal.title": "修改域名",
|
||||
"workflow.nodes.apply.form.domains.multiple_input_modal.placeholder": "请输入域名",
|
||||
"workflow.nodes.apply.form.email.label": "联系邮箱",
|
||||
"workflow.nodes.apply.form.email.placeholder": "请输入联系邮箱",
|
||||
"workflow.nodes.apply.form.email.tooltip": "申请签发 SSL 证书时所需的联系方式。请注意 Let's Encrypt 账户注册的<a href=\"https://letsencrypt.org/zh-cn/docs/rate-limits/\" target=\"_blank\">速率限制(点此了解更多)</a>。",
|
||||
"workflow.nodes.apply.form.access.label": "DNS 提供商授权",
|
||||
"workflow.nodes.apply.form.access.placeholder": "请选择 DNS 提供商授权",
|
||||
"workflow.nodes.apply.form.access.tooltip": "用于 ACME DNS-01 认证时操作域名解析记录,注意与部署阶段所需的主机提供商相区分。",
|
||||
"workflow.nodes.apply.form.access.button": "新建",
|
||||
"workflow.nodes.apply.form.advanced_settings.label": "高级设置",
|
||||
"workflow.nodes.apply.form.key_algorithm.label": "数字证书算法",
|
||||
"workflow.nodes.apply.form.key_algorithm.placeholder": "请选择数字证书算法",
|
||||
"workflow.nodes.apply.form.nameservers.label": "DNS 递归服务器",
|
||||
"workflow.nodes.apply.form.nameservers.placeholder": "请输入 DNS 递归服务器(多个值请用半角分号隔开)",
|
||||
"workflow.nodes.apply.form.nameservers.tooltip": "在 ACME DNS-01 认证时使用自定义的 DNS 递归服务器。如果你不了解该选项的用途,保持默认即可。",
|
||||
"workflow.nodes.apply.form.nameservers.multiple_input_modal.title": "修改 DNS 递归服务器",
|
||||
"workflow.nodes.apply.form.nameservers.multiple_input_modal.placeholder": "请输入 DNS 递归服务器",
|
||||
"workflow.nodes.apply.form.propagation_timeout.label": "DNS 传播检查超时时间",
|
||||
"workflow.nodes.apply.form.propagation_timeout.placeholder": "请输入 DNS 传播检查超时时间",
|
||||
"workflow.nodes.apply.form.propagation_timeout.suffix": "秒",
|
||||
"workflow.nodes.apply.form.propagation_timeout.tooltip": "在 ACME DNS-01 认证时等待 DNS 传播检查的最长时间。如果你不了解此选项的用途,保持默认即可。",
|
||||
"workflow.nodes.apply.form.disable_follow_cname.label": "禁止 CNAME 跟随",
|
||||
"workflow.nodes.apply.form.disable_follow_cname.tooltip": "在 ACME DNS-01 认证时是否禁止 CNAME 跟随。如果你不了解该选项的用途,保持默认即可。<br><a href=\"https://letsencrypt.org/2019/10/09/onboarding-your-customers-with-lets-encrypt-and-acme/#the-advantages-of-a-cname\" target=\"_blank\">点此了解更多</a>。",
|
||||
"workflow.nodes.notify.form.subject.label": "通知主题",
|
||||
"workflow.nodes.notify.form.subject.placeholder": "请输入通知主题",
|
||||
"workflow.nodes.notify.form.message.label": "通知内容",
|
||||
"workflow.nodes.notify.form.message.placeholder": "请输入通知内容",
|
||||
"workflow.nodes.notify.form.channel.label": "通知渠道",
|
||||
"workflow.nodes.notify.form.channel.placeholder": "请选择通知渠道",
|
||||
"workflow.nodes.notify.form.channel.button": "去配置",
|
||||
|
||||
"workflow_run.props.id": "ID",
|
||||
"workflow_run.props.status": "状态",
|
||||
"workflow_run.props.status.succeeded": "成功",
|
||||
"workflow_run.props.status.failed": "失败",
|
||||
"workflow_run.props.trigger": "触发方式",
|
||||
"workflow_run.props.started_at": "开始时间",
|
||||
"workflow_run.props.completed_at": "完成时间",
|
||||
|
||||
"workflow.detail.action.save": "保存变更",
|
||||
"workflow.detail.action.save.failed": "保存失败",
|
||||
"workflow.detail.action.save.failed.uncompleted": "请先完成流程编排并发布更改",
|
||||
|
269
ui/src/i18n/locales/zh/nls.workflow.nodes.json
Normal file
269
ui/src/i18n/locales/zh/nls.workflow.nodes.json
Normal file
@ -0,0 +1,269 @@
|
||||
{
|
||||
"workflow_node.start.form.trigger.label": "触发方式",
|
||||
"workflow_node.start.form.trigger.placeholder": "请选择触发方式",
|
||||
"workflow_node.start.form.trigger.tooltip": "自动触发:基于 Cron 表达式定时触发。<br>手动触发:手动点击执行触发。",
|
||||
"workflow_node.start.form.trigger.option.auto.label": "自动触发",
|
||||
"workflow_node.start.form.trigger.option.manual.label": "手动触发",
|
||||
"workflow_node.start.form.trigger_cron.label": "Cron 表达式",
|
||||
"workflow_node.start.form.trigger_cron.placeholder": "请输入 Cron 表达式",
|
||||
"workflow_node.start.form.trigger_cron.errmsg.invalid": "请输入正确的 Cron 表达式",
|
||||
"workflow_node.start.form.trigger_cron.tooltip": "时区以服务器设置为准。",
|
||||
"workflow_node.start.form.trigger_cron.extra": "预计最近 5 次执行时间:",
|
||||
"workflow_node.start.form.trigger_cron_alert.content": "小贴士:如果你有多个工作流,建议将它们设置为在一天中的多个时间段运行,而非总是在相同的特定时间。<br><br>参考链接:<br>1. <a href=\"https://letsencrypt.org/zh-cn/docs/rate-limits/\" target=\"_blank\">Let’s Encrypt 速率限制</a><br>2. <a href=\"https://letsencrypt.org/zh-cn/docs/faq/#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%88%91%E7%9A%84-let-s-encrypt-acme-%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%90%AF%E5%8A%A8%E6%97%B6%E9%97%B4%E5%BA%94%E5%BD%93%E9%9A%8F%E6%9C%BA\" target=\"_blank\">为什么我的 Let’s Encrypt (ACME) 客户端启动时间应当随机?</a>",
|
||||
|
||||
"workflow_node.apply.form.domains.label": "域名",
|
||||
"workflow_node.apply.form.domains.placeholder": "请输入域名(多个值请用半角分号隔开)",
|
||||
"workflow_node.apply.form.domains.tooltip": "泛域名表示形式为:*.example.com",
|
||||
"workflow_node.apply.form.domains.multiple_input_modal.title": "修改域名",
|
||||
"workflow_node.apply.form.domains.multiple_input_modal.placeholder": "请输入域名",
|
||||
"workflow_node.apply.form.email.label": "联系邮箱",
|
||||
"workflow_node.apply.form.email.placeholder": "请输入联系邮箱",
|
||||
"workflow_node.apply.form.email.tooltip": "申请签发 SSL 证书时所需的联系方式。请注意 Let's Encrypt 账户注册的<a href=\"https://letsencrypt.org/zh-cn/docs/rate-limits/\" target=\"_blank\">速率限制(点此了解更多)</a>。",
|
||||
"workflow_node.apply.form.access.label": "DNS 提供商授权",
|
||||
"workflow_node.apply.form.access.placeholder": "请选择 DNS 提供商授权",
|
||||
"workflow_node.apply.form.access.tooltip": "用于 ACME DNS-01 认证时操作域名解析记录,注意与部署阶段所需的主机提供商相区分。",
|
||||
"workflow_node.apply.form.access.button": "新建",
|
||||
"workflow_node.apply.form.advanced_config.label": "高级设置",
|
||||
"workflow_node.apply.form.key_algorithm.label": "数字证书算法",
|
||||
"workflow_node.apply.form.key_algorithm.placeholder": "请选择数字证书算法",
|
||||
"workflow_node.apply.form.nameservers.label": "DNS 递归服务器(可选)",
|
||||
"workflow_node.apply.form.nameservers.placeholder": "请输入 DNS 递归服务器(多个值请用半角分号隔开)",
|
||||
"workflow_node.apply.form.nameservers.tooltip": "在 ACME DNS-01 认证时使用自定义的 DNS 递归服务器。如果你不了解该选项的用途,保持默认即可。",
|
||||
"workflow_node.apply.form.nameservers.multiple_input_modal.title": "修改 DNS 递归服务器",
|
||||
"workflow_node.apply.form.nameservers.multiple_input_modal.placeholder": "请输入 DNS 递归服务器",
|
||||
"workflow_node.apply.form.propagation_timeout.label": "DNS 传播检查超时时间(可选)",
|
||||
"workflow_node.apply.form.propagation_timeout.placeholder": "请输入 DNS 传播检查超时时间",
|
||||
"workflow_node.apply.form.propagation_timeout.suffix": "秒",
|
||||
"workflow_node.apply.form.propagation_timeout.tooltip": "在 ACME DNS-01 认证时等待 DNS 传播检查的最长时间。如果你不了解此选项的用途,保持默认即可。",
|
||||
"workflow_node.apply.form.disable_follow_cname.label": "禁止 CNAME 跟随",
|
||||
"workflow_node.apply.form.disable_follow_cname.tooltip": "在 ACME DNS-01 认证时是否禁止 CNAME 跟随。如果你不了解该选项的用途,保持默认即可。<br><a href=\"https://letsencrypt.org/2019/10/09/onboarding-your-customers-with-lets-encrypt-and-acme/#the-advantages-of-a-cname\" target=\"_blank\">点此了解更多</a>。",
|
||||
|
||||
"workflow_node.deploy.form.provider_type.label": "部署目标",
|
||||
"workflow_node.deploy.form.provider_type.placeholder": "请选择部署目标",
|
||||
"workflow_node.deploy.form.provider_access.label": "主机提供商授权",
|
||||
"workflow_node.deploy.form.provider_access.placeholder": "请选择主机提供商授权",
|
||||
"workflow_node.deploy.form.provider_access.tooltip": "用于部署证书,注意与申请阶段所需的 DNS 提供商相区分。",
|
||||
"workflow_node.deploy.form.provider_access.button": "新建",
|
||||
"workflow_node.deploy.form.certificate.label": "待部署证书",
|
||||
"workflow_node.deploy.form.certificate.placeholder": "请选择待部署证书",
|
||||
"workflow_node.deploy.form.certificate.tooltip": "待部署证书来自之前的申请阶段。如果选项为空请先确保前序节点配置正确。",
|
||||
"workflow_node.deploy.form.params_config.label": "参数设置",
|
||||
"workflow_node.deploy.form.aliyun_alb_resource_type.label": "证书替换方式",
|
||||
"workflow_node.deploy.form.aliyun_alb_resource_type.placeholder": "请选择证书替换方式",
|
||||
"workflow_node.deploy.form.aliyun_alb_resource_type.option.loadbalancer.label": "替换指定负载均衡器下的全部 HTTPS/QUIC 监听的证书",
|
||||
"workflow_node.deploy.form.aliyun_alb_resource_type.option.listener.label": "替换指定负载均衡监听器的证书",
|
||||
"workflow_node.deploy.form.aliyun_alb_region.label": "阿里云地域",
|
||||
"workflow_node.deploy.form.aliyun_alb_region.placeholder": "请输入阿里云地域(例如:cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_alb_region.tooltip": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/slb/application-load-balancer/product-overview/supported-regions-and-zones\" target=\"_blank\">https://help.aliyun.com/zh/slb/application-load-balancer/product-overview/supported-regions-and-zones</a>",
|
||||
"workflow_node.deploy.form.aliyun_alb_loadbalancer_id.label": "阿里云 ALB 负载均衡器 ID",
|
||||
"workflow_node.deploy.form.aliyun_alb_loadbalancer_id.placeholder": "请输入阿里云 ALB 负载均衡器 ID",
|
||||
"workflow_node.deploy.form.aliyun_alb_loadbalancer_id.tooltip": "这是什么?请参阅 <a href=\"https://slb.console.aliyun.com/alb\" target=\"_blank\">https://slb.console.aliyun.com/alb</a>",
|
||||
"workflow_node.deploy.form.aliyun_alb_listener_id.label": "阿里云 ALB 监听器 ID",
|
||||
"workflow_node.deploy.form.aliyun_alb_listener_id.placeholder": "请输入阿里云 ALB 监听器 ID",
|
||||
"workflow_node.deploy.form.aliyun_alb_listener_id.tooltip": "这是什么?请参阅 <a href=\"https://slb.console.aliyun.com/alb\" target=\"_blank\">https://slb.console.aliyun.com/alb</a>",
|
||||
"workflow_node.deploy.form.aliyun_clb_resource_type.label": "证书替换方式",
|
||||
"workflow_node.deploy.form.aliyun_clb_resource_type.placeholder": "请选择证书替换方式",
|
||||
"workflow_node.deploy.form.aliyun_clb_resource_type.option.loadbalancer.label": "替换指定负载均衡器下的全部 HTTPS 监听的证书",
|
||||
"workflow_node.deploy.form.aliyun_clb_resource_type.option.listener.label": "替换指定负载均衡监听的证书",
|
||||
"workflow_node.deploy.form.aliyun_clb_region.label": "阿里云地域",
|
||||
"workflow_node.deploy.form.aliyun_clb_region.placeholder": "请输入阿里云地域(例如:cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_clb_region.tooltip": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/slb/classic-load-balancer/product-overview/regions-that-support-clb\" target=\"_blank\">https://help.aliyun.com/zh/slb/classic-load-balancer/product-overview/regions-that-support-clb</a>",
|
||||
"workflow_node.deploy.form.aliyun_clb_loadbalancer_id.label": "阿里云 CLB 负载均衡器 ID",
|
||||
"workflow_node.deploy.form.aliyun_clb_loadbalancer_id.placeholder": "请输入阿里云 CLB 负载均衡器 ID",
|
||||
"workflow_node.deploy.form.aliyun_clb_loadbalancer_id.tooltip": "这是什么?请参阅 <a href=\"https://slb.console.aliyun.com/clb\" target=\"_blank\">https://slb.console.aliyun.com/clb</a>",
|
||||
"workflow_node.deploy.form.aliyun_clb_listener_id.label": "阿里云 CLB 监听端口",
|
||||
"workflow_node.deploy.form.aliyun_clb_listener_id.placeholder": "请输入阿里云 CLB 监听端口",
|
||||
"workflow_node.deploy.form.aliyun_clb_listener_id.tooltip": "这是什么?请参阅 <a href=\"https://slb.console.aliyun.com/clb\" target=\"_blank\">https://slb.console.aliyun.com/clb</a>",
|
||||
"workflow_node.deploy.form.aliyun_cdn_domain.label": "阿里云 CDN 加速域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.aliyun_cdn_domain.placeholder": "请输入阿里云 CDN 加速域名",
|
||||
"workflow_node.deploy.form.aliyun_cdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://cdn.console.aliyun.com\" target=\"_blank\">https://cdn.console.aliyun.com</a>",
|
||||
"workflow_node.deploy.form.aliyun_dcdn_domain.label": "阿里云 DCDN 加速域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.aliyun_dcdn_domain.placeholder": "请输入阿里云 DCDN 加速域名",
|
||||
"workflow_node.deploy.form.aliyun_dcdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://dcdn.console.aliyun.com\" target=\"_blank\">https://dcdn.console.aliyun.com</a>",
|
||||
"workflow_node.deploy.form.aliyun_nlb_resource_type.label": "证书替换方式",
|
||||
"workflow_node.deploy.form.aliyun_nlb_resource_type.placeholder": "请选择证书替换方式",
|
||||
"workflow_node.deploy.form.aliyun_nlb_resource_type.option.loadbalancer.label": "替换指定负载均衡器下的全部 HTTPS/QUIC 监听的证书",
|
||||
"workflow_node.deploy.form.aliyun_nlb_resource_type.option.listener.label": "替换指定负载均衡监听器的证书",
|
||||
"workflow_node.deploy.form.aliyun_nlb_region.label": "阿里云地域",
|
||||
"workflow_node.deploy.form.aliyun_nlb_region.placeholder": "请输入阿里云地域(例如:cn-hangzhou)",
|
||||
"workflow_node.deploy.form.aliyun_nlb_region.tooltip": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/slb/network-load-balancer/product-overview/regions-that-support-nlb\" target=\"_blank\">https://help.aliyun.com/zh/slb/network-load-balancer/product-overview/regions-that-support-nlb</a>",
|
||||
"workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.label": "阿里云 NLB 负载均衡器 ID",
|
||||
"workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.placeholder": "请输入阿里云 NLB 负载均衡器 ID",
|
||||
"workflow_node.deploy.form.aliyun_nlb_loadbalancer_id.tooltip": "这是什么?请参阅 <a href=\"https://slb.console.aliyun.com/nlb\" target=\"_blank\">https://slb.console.aliyun.com/nlb</a>",
|
||||
"workflow_node.deploy.form.aliyun_nlb_listener_id.label": "阿里云 NLB 监听器 ID",
|
||||
"workflow_node.deploy.form.aliyun_nlb_listener_id.placeholder": "请输入阿里云 NLB 监听器 ID",
|
||||
"workflow_node.deploy.form.aliyun_nlb_listener_id.tooltip": "这是什么?请参阅 <a href=\"https://slb.console.aliyun.com/nlb\" target=\"_blank\">https://slb.console.aliyun.com/nlb</a>",
|
||||
"workflow_node.deploy.form.aliyun_oss_endpoint.label": "阿里云 OSS Endpoint",
|
||||
"workflow_node.deploy.form.aliyun_oss_endpoint.placeholder": "请输入阿里云 OSS Endpoint",
|
||||
"workflow_node.deploy.form.aliyun_oss_endpoint.tooltip": "这是什么?请参阅 <a href=\"https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints\" target=\"_blank\">https://help.aliyun.com/zh/oss/user-guide/regions-and-endpoints</a>",
|
||||
"workflow_node.deploy.form.aliyun_oss_bucket.label": "阿里云 OSS 存储桶名",
|
||||
"workflow_node.deploy.form.aliyun_oss_bucket.placeholder": "请输入阿里云 OSS 存储桶名",
|
||||
"workflow_node.deploy.form.aliyun_oss_bucket.tooltip": "这是什么?请参阅 <a href=\"https://oss.console.aliyun.com\" target=\"_blank\">https://oss.console.aliyun.com</a>",
|
||||
"workflow_node.deploy.form.aliyun_oss_domain.label": "阿里云 OSS 自定义域名",
|
||||
"workflow_node.deploy.form.aliyun_oss_domain.placeholder": "请输入阿里云 OSS 自定义域名",
|
||||
"workflow_node.deploy.form.aliyun_oss_domain.tooltip": "这是什么?请参阅 see <a href=\"https://oss.console.aliyun.com\" target=\"_blank\">https://oss.console.aliyun.com</a>",
|
||||
"workflow_node.deploy.form.baiducloud_cdn_domain.label": "百度智能云 CDN 加速域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.baiducloud_cdn_domain.placeholder": "请输入百度智能云 CDN 加速域名",
|
||||
"workflow_node.deploy.form.baiducloud_cdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://console.bce.baidu.com/cdn\" target=\"_blank\">https://console.bce.baidu.com/cdn</a>",
|
||||
"workflow_node.deploy.form.byteplus_cdn_domain.label": "BytePlus CDN 域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.byteplus_cdn_domain.placeholder": "请输入 BytePlus CDN 域名",
|
||||
"workflow_node.deploy.form.byteplus_cdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://console.byteplus.com/cdn\" target=\"_blank\">https://console.byteplus.com/cdn</a>",
|
||||
"workflow_node.deploy.form.dogecloud_cdn_domain.label": "多吉云 CDN 加速域名",
|
||||
"workflow_node.deploy.form.dogecloud_cdn_domain.placeholder": "请输入多吉云 CDN 加速域名",
|
||||
"workflow_node.deploy.form.dogecloud_cdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://console.dogecloud.com\" target=\"_blank\">https://console.dogecloud.com</a>",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_region.label": "华为云区域",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_region.placeholder": "请输入华为云区域(例如:cn-north-1)",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_region.tooltip": "这是什么?请参阅 <a href=\"https://console.huaweicloud.com/apiexplorer/#/endpoint\" target=\"_blank\">https://console.huaweicloud.com/apiexplorer/#/endpoint</a>",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_domain.label": "华为云 CDN 加速域名",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_domain.placeholder": "请输入华为云 CDN 加速域名",
|
||||
"workflow_node.deploy.form.huaweicloud_cdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://console.huaweicloud.com/cdn\" target=\"_blank\">https://console.huaweicloud.com/cdn</a>",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_resource_type.label": "证书替换方式",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_resource_type.placeholder": "请选择证书替换方式",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_resource_type.option.certificate.label": "替换指定证书",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_resource_type.option.loadbalancer.label": "替换指定负载均衡器下的全部 HTTPS 监听器的证书",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_resource_type.option.listener.label": "替换指定监听器的证书",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_region.label": "华为云区域",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_region.placeholder": "请输入华为云区域(例如:cn-north-1)",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_region.tooltip": "这是什么?请参阅 <a href=\"https://console.huaweicloud.com/apiexplorer/#/endpoint\" target=\"_blank\">https://console.huaweicloud.com/apiexplorer/#/endpoint</a>",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_certificate_id.label": "华为云 ELB 证书 ID",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_certificate_id.placeholder": "请输入华为云 ELB 证书 ID",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_certificate_id.tooltip": "这是什么?请参阅 <a href=\"https://console.huaweicloud.com/vpc/#/elb/elbCert\" target=\"_blank\">https://console.huaweicloud.com/vpc/#/elb/elbCert</a>",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_loadbalancer_id.label": "华为云 ELB 负载均衡器 ID",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_loadbalancer_id.placeholder": "请输入华为云 ELB 负载均衡器 ID",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_loadbalancer_id.tooltip": "这是什么?请参阅 <a href=\"https://console.huaweicloud.com/vpc/#/elb/list/grid\" target=\"_blank\">https://console.huaweicloud.com/vpc/#/elb/list/grid</a>",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_listener_id.label": "华为云 ELB 监听器 ID",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_listener_id.placeholder": "请输入华为云 ELB 监听器 ID",
|
||||
"workflow_node.deploy.form.huaweicloud_elb_listener_id.tooltip": "这是什么?请参阅 <a href=\"https://console.huaweicloud.com/vpc/#/elb/list/grid\" target=\"_blank\">https://console.huaweicloud.com/vpc/#/elb/list/grid</a>",
|
||||
"workflow_node.deploy.form.k8s_namespace.label": "Kubernetes 命名空间",
|
||||
"workflow_node.deploy.form.k8s_namespace.placeholder": "请输入 Kubernetes 命名空间",
|
||||
"workflow_node.deploy.form.k8s_namespace.tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/namespaces/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/overview/working-with-objects/namespaces/</a>",
|
||||
"workflow_node.deploy.form.k8s_secret_name.label": "Kubernetes Secret 名称",
|
||||
"workflow_node.deploy.form.k8s_secret_name.placeholder": "请输入 Kubernetes Secret 名称",
|
||||
"workflow_node.deploy.form.k8s_secret_name.tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/</a>",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_crt.label": "Kubernetes Secret 数据键(用于存放证书的字段)",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_crt.placeholder": "请输入 Kubernetes Secret 中用于存放证书的数据键",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_crt.tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/</a>",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_key.label": "Kubernetes Secret 数据键(用于存放私钥的字段)",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_key.placeholder": "请输入 Kubernetes Secret 中用于存放私钥的数据键",
|
||||
"workflow_node.deploy.form.k8s_secret_data_key_for_key.tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/</a>",
|
||||
"workflow_node.deploy.form.local_format.label": "文件格式",
|
||||
"workflow_node.deploy.form.local_format.placeholder": "请选择文件格式",
|
||||
"workflow_node.deploy.form.local_format.option.pem.label": "PEM 格式(*.pem, *.crt, *.key)",
|
||||
"workflow_node.deploy.form.local_format.option.pfx.label": "PFX 格式(*.pfx)",
|
||||
"workflow_node.deploy.form.local_format.option.jks.label": "JKS 格式(*.jks)",
|
||||
"workflow_node.deploy.form.local_cert_path.label": "证书文件保存路径",
|
||||
"workflow_node.deploy.form.local_cert_path.placeholder": "请输入证书文件保存路径",
|
||||
"workflow_node.deploy.form.local_cert_path.tooltip": "注意,路径需包含完整的文件名,而不是仅目录。",
|
||||
"workflow_node.deploy.form.local_key_path.label": "私钥文件保存路径",
|
||||
"workflow_node.deploy.form.local_key_path.placeholder": "请输入私钥文件保存路径",
|
||||
"workflow_node.deploy.form.local_key_path.tooltip": "注意,路径需包含完整的文件名,而不是仅目录。",
|
||||
"workflow_node.deploy.form.local_pfx_password.label": "PFX 导出密码",
|
||||
"workflow_node.deploy.form.local_pfx_password.placeholder": "请输入 PFX 导出密码",
|
||||
"workflow_node.deploy.form.local_jks_alias.label": "JKS 别名(KeyStore Alias)",
|
||||
"workflow_node.deploy.form.local_jks_alias.placeholder": "请输入 JKS 别名",
|
||||
"workflow_node.deploy.form.local_jks_keypass.label": "JKS 私钥访问口令(KeyStore Keypass)",
|
||||
"workflow_node.deploy.form.local_jks_keypass.placeholder": "请输入 JKS 私钥访问口令",
|
||||
"workflow_node.deploy.form.local_jks_storepass.label": "JKS 密钥库存储口令(KeyStore Storepass)",
|
||||
"workflow_node.deploy.form.local_jks_storepass.placeholder": "请输入 JKS 密钥库存储口令",
|
||||
"workflow_node.deploy.form.local_shell_env.label": "命令执行环境",
|
||||
"workflow_node.deploy.form.local_shell_env.placeholder": "请选择命令执行环境",
|
||||
"workflow_node.deploy.form.local_shell_env.option.sh.label": "POSIX Bash(Linux / macOS)",
|
||||
"workflow_node.deploy.form.local_shell_env.option.cmd.label": "CMD(Windows)",
|
||||
"workflow_node.deploy.form.local_shell_env.option.powershell.label": "PowerShell(Windows)",
|
||||
"workflow_node.deploy.form.local_pre_command.label": "前置命令",
|
||||
"workflow_node.deploy.form.local_pre_command.placeholder": "请输入保存文件前执行的命令",
|
||||
"workflow_node.deploy.form.local_post_command.label": "后置命令",
|
||||
"workflow_node.deploy.form.local_post_command.placeholder": "请输入保存文件后执行的命令",
|
||||
"workflow_node.deploy.form.local_preset_scripts.button": "使用预设脚本",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.reload_nginx.label": "POSIX Bash - 重启 nginx 进程",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.binding_iis.label": "PowerShell - 导入并绑定到 IIS(需管理员权限)",
|
||||
"workflow_node.deploy.form.local_preset_scripts.option.binding_netsh.label": "PowerShell - 导入并绑定到 netsh(需管理员权限)",
|
||||
"workflow_node.deploy.form.qiniu_cdn_domain.label": "七牛云 CDN 加速域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.qiniu_cdn_domain.placeholder": "请输入七牛云 CDN 加速域名",
|
||||
"workflow_node.deploy.form.qiniu_cdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/\" target=\"_blank\">https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/</a>",
|
||||
"workflow_node.deploy.form.ssh_format.label": "文件格式",
|
||||
"workflow_node.deploy.form.ssh_format.placeholder": "请选择文件格式",
|
||||
"workflow_node.deploy.form.ssh_format.option.pem.label": "PEM 格式(*.pem, *.crt, *.key)",
|
||||
"workflow_node.deploy.form.ssh_format.option.pfx.label": "PFX 格式(*.pfx)",
|
||||
"workflow_node.deploy.form.ssh_format.option.jks.label": "JKS 格式(*.jks)",
|
||||
"workflow_node.deploy.form.ssh_cert_path.label": "证书文件上传路径",
|
||||
"workflow_node.deploy.form.ssh_cert_path.placeholder": "请输入证书文件上传路径",
|
||||
"workflow_node.deploy.form.ssh_cert_path.tooltip": "注意,路径需包含完整的文件名,而不是仅目录。",
|
||||
"workflow_node.deploy.form.ssh_key_path.label": "私钥文件上传路径",
|
||||
"workflow_node.deploy.form.ssh_key_path.placeholder": "请输入私钥文件上传路径",
|
||||
"workflow_node.deploy.form.ssh_key_path.tooltip": "注意,路径需包含完整的文件名,而不是仅目录。",
|
||||
"workflow_node.deploy.form.ssh_pfx_password.label": "PFX 导出密码",
|
||||
"workflow_node.deploy.form.ssh_pfx_password.placeholder": "请输入 PFX 导出密码",
|
||||
"workflow_node.deploy.form.ssh_jks_alias.label": "JKS 别名(KeyStore Alias)",
|
||||
"workflow_node.deploy.form.ssh_jks_alias.placeholder": "请输入 JKS 别名",
|
||||
"workflow_node.deploy.form.ssh_jks_keypass.label": "JKS 私钥访问口令(KeyStore Keypass)",
|
||||
"workflow_node.deploy.form.ssh_jks_keypass.placeholder": "请输入 JKS 私钥访问口令",
|
||||
"workflow_node.deploy.form.ssh_jks_storepass.label": "JKS 密钥库存储口令(KeyStore Storepass)",
|
||||
"workflow_node.deploy.form.ssh_jks_storepass.placeholder": "请输入 JKS 密钥库存储口令",
|
||||
"workflow_node.deploy.form.ssh_shell_env.label": "命令执行环境",
|
||||
"workflow_node.deploy.form.ssh_shell_env.value": "POSIX Bash(Linux / macOS)",
|
||||
"workflow_node.deploy.form.ssh_pre_command.label": "前置命令",
|
||||
"workflow_node.deploy.form.ssh_pre_command.placeholder": "请输入保存文件前执行的命令",
|
||||
"workflow_node.deploy.form.ssh_post_command.label": "后置命令",
|
||||
"workflow_node.deploy.form.ssh_post_command.placeholder": "请输入保存文件后执行的命令",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.button": "使用预设脚本",
|
||||
"workflow_node.deploy.form.ssh_preset_scripts.option.reload_nginx.label": "POSIX Bash - 重启 nginx 进程",
|
||||
"workflow_node.deploy.form.tencentcloud_cdn_domain.label": "腾讯云 CDN 加速域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.tencentcloud_cdn_domain.placeholder": "请输入腾讯云 CDN 加速域名",
|
||||
"workflow_node.deploy.form.tencentcloud_cdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/cdn\" target=\"_blank\">https://console.cloud.tencent.com/cdn</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_resource_type.label": "证书替换方式",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_resource_type.placeholder": "请选择证书替换方式",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.ssl_deploy.label": "通过 SSL 服务部署到云资源实例",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.loadbalancer.label": "替换指定实例下的全部 HTTPS/TCPSSL/QUIC 监听器的证书",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.listener.label": "替换指定监听器的证书",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_resource_type.option.ruledomain.label": "替换指定七层监听转发规则域名的证书",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_region.label": "腾讯云地域",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_region.placeholder": "请输入腾讯云地域(例如:ap-guangzhou)",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_region.tooltip": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/214/33415\" target=\"_blank\">https://cloud.tencent.com/document/product/214/33415</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.label": "腾讯云 CLB 实例 ID",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.placeholder": "请输入腾讯云 CLB 实例 ID",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_loadbalancer_id.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/clb\" target=\"_blank\">https://console.cloud.tencent.com/clb</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_listener_id.label": "腾讯云 CLB 监听器 ID",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_listener_id.placeholder": "请输入腾讯云 CLB 监听器 ID",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_listener_id.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/clb\" target=\"_blank\">https://console.cloud.tencent.com/clb</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_snidomain.label": "腾讯云 CLB SNI 域名(可选)",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_snidomain.placeholder": "请输入腾讯云 CLB SNI 域名",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_snidomain.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/clb\" target=\"_blank\">https://console.cloud.tencent.com/clb</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_ruledomain.label": "腾讯云 CLB 七层转发规则域名",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_ruledomain.placeholder": "请输入腾讯云 CLB 七层转发规则域名",
|
||||
"workflow_node.deploy.form.tencentcloud_clb_ruledomain.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/clb\" target=\"_blank\">https://console.cloud.tencent.com/clb</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_region.label": "腾讯云地域",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_region.placeholder": "请输入腾讯云地域(例如:ap-guangzhou)",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_region.tooltip": "这是什么?请参阅 <a href=\"https://cloud.tencent.com/document/product/436/6224\" target=\"_blank\">https://cloud.tencent.com/document/product/436/6224</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_bucket.label": "腾讯云 COS 存储桶名",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_bucket.placeholder": "请输入腾讯云 COS 存储桶名",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_bucket.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/cos\" target=\"_blank\">https://console.cloud.tencent.com/cos</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_domain.label": "腾讯云 COS 自定义域名",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_domain.placeholder": "请输入腾讯云 COS 自定义域名",
|
||||
"workflow_node.deploy.form.tencentcloud_cos_domain.tooltip": "这是什么?请参阅 see <a href=\"https://console.cloud.tencent.com/cos\" target=\"_blank\">https://console.cloud.tencent.com/cos</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_ecdn_domain.label": "腾讯云 ECDN 加速域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.tencentcloud_ecdn_domain.placeholder": "请输入腾讯云 ECDN 加速域名",
|
||||
"workflow_node.deploy.form.tencentcloud_ecdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/cdn\" target=\"_blank\">https://console.cloud.tencent.com/cdn</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_eo_zone_id.label": "腾讯云 EdgeOne 站点 ID",
|
||||
"workflow_node.deploy.form.tencentcloud_eo_zone_id.placeholder": "请输入腾讯云 EdgeOne 站点 ID",
|
||||
"workflow_node.deploy.form.tencentcloud_eo_zone_id.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/edgeone\" target=\"_blank\">https://console.cloud.tencent.com/edgeone</a>",
|
||||
"workflow_node.deploy.form.tencentcloud_eo_domain.label": "腾讯云 EdgeOne 加速域名",
|
||||
"workflow_node.deploy.form.tencentcloud_eo_domain.placeholder": "请输入腾讯云 EdgeOne 加速域名",
|
||||
"workflow_node.deploy.form.tencentcloud_eo_domain.tooltip": "这是什么?请参阅 <a href=\"https://console.cloud.tencent.com/edgeone\" target=\"_blank\">https://console.cloud.tencent.com/edgeone</a>",
|
||||
"workflow_node.deploy.form.volcengine_cdn_domain.label": "火山引擎 CDN 加速域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.volcengine_cdn_domain.placeholder": "请输入火山引擎 CDN 加速域名",
|
||||
"workflow_node.deploy.form.volcengine_cdn_domain.tooltip": "这是什么?请参阅 <a href=\"https://console.volcengine.com/cdn/homepage\" target=\"_blank\">https://console.volcengine.com/cdn/homepage</a>",
|
||||
"workflow_node.deploy.form.volcengine_live_domain.label": "火山引擎视频直播流域名(支持泛域名)",
|
||||
"workflow_node.deploy.form.volcengine_live_domain.placeholder": "请输入火山引擎视频直播流域名",
|
||||
"workflow_node.deploy.form.volcengine_live_domain.tooltip": "这是什么?请参阅 <a href=\"https://console.volcengine.com/live\" target=\"_blank\">https://console.volcengine.com/live</a>",
|
||||
"workflow_node.deploy.form.webhook_data.label": "Webhook 回调数据(JSON 格式)",
|
||||
"workflow_node.deploy.form.webhook_data.placeholder": "请输入 Webhook 回调数据",
|
||||
|
||||
"workflow_node.notify.form.subject.label": "通知主题",
|
||||
"workflow_node.notify.form.subject.placeholder": "请输入通知主题",
|
||||
"workflow_node.notify.form.message.label": "通知内容",
|
||||
"workflow_node.notify.form.message.placeholder": "请输入通知内容",
|
||||
"workflow_node.notify.form.channel.label": "通知渠道",
|
||||
"workflow_node.notify.form.channel.placeholder": "请选择通知渠道",
|
||||
"workflow_node.notify.form.channel.button": "去配置"
|
||||
}
|
9
ui/src/i18n/locales/zh/nls.workflow.runs.json
Normal file
9
ui/src/i18n/locales/zh/nls.workflow.runs.json
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"workflow_run.props.id": "ID",
|
||||
"workflow_run.props.status": "状态",
|
||||
"workflow_run.props.status.succeeded": "成功",
|
||||
"workflow_run.props.status.failed": "失败",
|
||||
"workflow_run.props.trigger": "触发方式",
|
||||
"workflow_run.props.started_at": "开始时间",
|
||||
"workflow_run.props.completed_at": "完成时间"
|
||||
}
|
@ -13,7 +13,8 @@ import dayjs from "dayjs";
|
||||
import { ClientResponseError } from "pocketbase";
|
||||
|
||||
import AccessEditModal from "@/components/access/AccessEditModal";
|
||||
import { accessProvidersMap, type AccessModel } from "@/domain/access";
|
||||
import { type AccessModel } from "@/domain/access";
|
||||
import { accessProvidersMap } from "@/domain/provider";
|
||||
import { useAccessStore } from "@/stores/access";
|
||||
import { getErrMsg } from "@/utils/error";
|
||||
|
||||
@ -89,7 +90,7 @@ const AccessList = () => {
|
||||
data={{ ...record, id: undefined, name: `${record.name}-copy` }}
|
||||
preset="add"
|
||||
trigger={
|
||||
<Tooltip title={t("access.action.copy")}>
|
||||
<Tooltip title={t("access.action.duplicate")}>
|
||||
<Button color="primary" icon={<SnippetsOutlinedIcon />} variant="text" />
|
||||
</Tooltip>
|
||||
}
|
||||
|
@ -34,3 +34,7 @@ export const validHttpOrHttpsUrl = (value: string) => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
export const validPortNumber = (value: string | number) => {
|
||||
return parseInt(value + "") === +value && +value >= 1 && +value <= 65535;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user