mirror of
https://github.com/woodchen-ink/certimate.git
synced 2025-07-19 09:51:55 +08:00
impprove frontend
This commit is contained in:
parent
07b5760986
commit
be84f3314f
@ -36,7 +36,7 @@ const AddNode = ({ data }: NodeProps | BrandNodeProps) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="before:content-[''] before:w-[2px] before:bg-stone-300 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 pt-6 pb-9 relative flex flex-col items-center">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger className="">
|
||||
<div className="bg-stone-400 hover:bg-stone-500 rounded-full z-10 relative outline-none">
|
||||
|
@ -25,7 +25,7 @@ const BranchNode = memo(({ data }: BrandNodeProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="border-t-[2px] border-b-[2px] relative flex gap-x-16 border-stone-300 bg-slate-50">
|
||||
<div className="border-t-[2px] border-b-[2px] relative flex gap-x-16 border-stone-200 bg-background">
|
||||
<Button
|
||||
onClick={() => {
|
||||
addBranch(data.id);
|
||||
@ -40,18 +40,18 @@ const BranchNode = memo(({ data }: BrandNodeProps) => {
|
||||
{data.branches.map((branch, index) => (
|
||||
<div
|
||||
key={branch.id}
|
||||
className="relative flex flex-col items-center before:content-[''] before:w-[2px] before:bg-stone-300 before:absolute before:h-full before:left-[50%] before:-translate-x-[50%] before:top-0"
|
||||
className="relative flex flex-col items-center before:content-[''] before:w-[2px] before:bg-stone-200 before:absolute before:h-full before:left-[50%] before:-translate-x-[50%] before:top-0"
|
||||
>
|
||||
{index == 0 && (
|
||||
<>
|
||||
<div className="w-[50%] h-2 absolute -top-1 bg-stone-50 -left-[1px]"></div>
|
||||
<div className="w-[50%] h-2 absolute -bottom-1 bg-stone-50 -left-[1px]"></div>
|
||||
<div className="w-[50%] h-2 absolute -top-1 bg-background -left-[1px]"></div>
|
||||
<div className="w-[50%] h-2 absolute -bottom-1 bg-background -left-[1px]"></div>
|
||||
</>
|
||||
)}
|
||||
{index == data.branches.length - 1 && (
|
||||
<>
|
||||
<div className="w-[50%] h-2 absolute -top-1 bg-stone-50 -right-[1px]"></div>
|
||||
<div className="w-[50%] h-2 absolute -bottom-1 bg-stone-50 -right-[1px]"></div>
|
||||
<div className="w-[50%] h-2 absolute -top-1 bg-background -right-[1px]"></div>
|
||||
<div className="w-[50%] h-2 absolute -bottom-1 bg-background -right-[1px]"></div>
|
||||
</>
|
||||
)}
|
||||
{/* 条件 1 */}
|
||||
|
@ -1,6 +1,23 @@
|
||||
import { WorkflowNode } from "@/domain/workflow";
|
||||
import { memo } from "react";
|
||||
import DeployToAliyunOSS from "./DeployToAliyunOss";
|
||||
import DeployToAliyunALB from "./DeployToAliyunALB";
|
||||
import DeployToAliyunCDN from "./DeployToAliyunCDN";
|
||||
import DeployToAliyunCLB from "./DeployToAliyunCLB";
|
||||
import DeployToAliyunNLB from "./DeployToAliyunNLB";
|
||||
import DeployToBaiduCloudCDN from "./DeployToBaiduCloudCDN";
|
||||
import DeployToDogeCloudCDN from "./DeployToDogeCloudCDN";
|
||||
import DeployToHuaweiCloudCDN from "./DeployToHuaweiCloudCDN";
|
||||
import DeployToHuaweiCloudELB from "./DeployToHuaweiCloudELB";
|
||||
import DeployToKubernetesSecret from "./DeployToKubernetesSecret";
|
||||
import DeployToQiniuCDN from "./DeployToQiniuCDN";
|
||||
import DeployToWebhook from "./DeployToWebhook";
|
||||
import DeployToTencentCDN from "./DeployToTencentCDN";
|
||||
import DeployToTencentCLB from "./DeployToTencentCLB";
|
||||
import DeployToTencentCOS from "./DeployToTencentCOS";
|
||||
import DeployToTencentTEO from "./DeployToTencentTEO";
|
||||
import DeployToSSH from "./DeployToSSH";
|
||||
import DeployToLocal from "./DeployToLocal";
|
||||
|
||||
export type DeployFormProps = {
|
||||
data: WorkflowNode;
|
||||
@ -17,12 +34,43 @@ const getForm = (data: WorkflowNode, defaultProivder?: string) => {
|
||||
switch (provider) {
|
||||
case "aliyun-oss":
|
||||
return <DeployToAliyunOSS data={data} />;
|
||||
case "tencent":
|
||||
return <TencentForm data={data} />;
|
||||
case "aws":
|
||||
return <AwsForm data={data} />;
|
||||
case "aliyun-alb":
|
||||
return <DeployToAliyunALB data={data} />;
|
||||
case "aliyun-cdn":
|
||||
case "aliyun-dcdn":
|
||||
return <DeployToAliyunCDN data={data} />;
|
||||
case "aliyun-clb":
|
||||
return <DeployToAliyunCLB data={data} />;
|
||||
case "aliyun-nlb":
|
||||
return <DeployToAliyunNLB data={data} />;
|
||||
case "baiducloud-cdn":
|
||||
return <DeployToBaiduCloudCDN data={data} />;
|
||||
case "dogecloud-cdn":
|
||||
return <DeployToDogeCloudCDN data={data} />;
|
||||
case "huaweicloud-cdn":
|
||||
return <DeployToHuaweiCloudCDN data={data} />;
|
||||
case "huaweicloud-elb":
|
||||
return <DeployToHuaweiCloudELB data={data} />;
|
||||
case "k8s-secret":
|
||||
return <DeployToKubernetesSecret data={data} />;
|
||||
case "qiniu-cdn":
|
||||
return <DeployToQiniuCDN data={data} />;
|
||||
case "webhook":
|
||||
return <DeployToWebhook data={data} />;
|
||||
case "tencent-cdn":
|
||||
case "tencent-ecdn":
|
||||
return <DeployToTencentCDN data={data} />;
|
||||
case "tencent-clb":
|
||||
return <DeployToTencentCLB data={data} />;
|
||||
case "tencent-cos":
|
||||
return <DeployToTencentCOS data={data} />;
|
||||
case "tencent-teo":
|
||||
return <DeployToTencentTEO data={data} />;
|
||||
case "ssh":
|
||||
return <DeployToSSH data={data} />;
|
||||
case "local":
|
||||
return <DeployToLocal data={data} />;
|
||||
default:
|
||||
return <></>;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { accessProviders } from "@/domain/access";
|
||||
import { WorkflowNode } from "@/domain/workflow";
|
||||
import { memo, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@ -55,4 +54,3 @@ const DeployPanelBody = ({ data }: DeployPanelBodyProps) => {
|
||||
};
|
||||
|
||||
export default memo(DeployPanelBody);
|
||||
|
||||
|
217
ui/src/components/workflow/DeployToAliyunALB.tsx
Normal file
217
ui/src/components/workflow/DeployToAliyunALB.tsx
Normal file
@ -0,0 +1,217 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
|
||||
const DeployToAliyunALB = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z
|
||||
.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
region: z.string().min(1, t("domain.deployment.form.aliyun_alb_region.placeholder")),
|
||||
resourceType: z.union([z.literal("loadbalancer"), z.literal("listener")], {
|
||||
message: t("domain.deployment.form.aliyun_alb_resource_type.placeholder"),
|
||||
}),
|
||||
loadbalancerId: z.string().optional(),
|
||||
listenerId: z.string().optional(),
|
||||
})
|
||||
.refine((data) => (data.resourceType === "loadbalancer" ? !!data.loadbalancerId?.trim() : true), {
|
||||
message: t("domain.deployment.form.aliyun_alb_loadbalancer_id.placeholder"),
|
||||
path: ["loadbalancerId"],
|
||||
})
|
||||
.refine((data) => (data.resourceType === "listener" ? !!data.listenerId?.trim() : true), {
|
||||
message: t("domain.deployment.form.aliyun_alb_listener_id.placeholder"),
|
||||
path: ["listenerId"],
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "aliyun-alb",
|
||||
region: "",
|
||||
resourceType: "",
|
||||
loadbalancerId: "",
|
||||
listenerId: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
region: config.region as string,
|
||||
resourceType: config.resourceType as "loadbalancer" | "listener",
|
||||
loadbalancerId: config.loadbalancerId as string,
|
||||
listenerId: config.listenerId as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="region"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.aliyun_alb_region.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.aliyun_alb_region.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="resourceType"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.aliyun_alb_resource_type.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("resourceType", value as "loadbalancer" | "listener");
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t("domain.deployment.form.aliyun_alb_resource_type.placeholder")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="loadbalancer">{t("domain.deployment.form.aliyun_alb_resource_type.option.loadbalancer.label")}</SelectItem>
|
||||
<SelectItem value="listener">{t("domain.deployment.form.aliyun_alb_resource_type.option.listener.label")}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="loadbalancerId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.aliyun_alb_loadbalancer_id.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.aliyun_alb_loadbalancer_id.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="listenerId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.aliyun_alb_listener_id.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.aliyun_alb_listener_id.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToAliyunALB;
|
141
ui/src/components/workflow/DeployToAliyunCDN.tsx
Normal file
141
ui/src/components/workflow/DeployToAliyunCDN.tsx
Normal file
@ -0,0 +1,141 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { SelectLabel } from "@radix-ui/react-select";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
const DeployToAliyunCDN = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
domain: z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||
message: t("common.errmsg.domain_invalid"),
|
||||
}),
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "aliyun-cdn",
|
||||
|
||||
domain: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
domain: config.domain as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="domain"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.domain.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.domain.label")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToAliyunCDN;
|
217
ui/src/components/workflow/DeployToAliyunCLB.tsx
Normal file
217
ui/src/components/workflow/DeployToAliyunCLB.tsx
Normal file
@ -0,0 +1,217 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
|
||||
const DeployToAliyunCLB = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z
|
||||
.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
region: z.string().min(1, t("domain.deployment.form.aliyun_clb_region.placeholder")),
|
||||
resourceType: z.union([z.literal("certificate"), z.literal("loadbalancer"), z.literal("listener")], {
|
||||
message: t("domain.deployment.form.aliyun_clb_resource_type.placeholder"),
|
||||
}),
|
||||
loadbalancerId: z.string().optional(),
|
||||
listenerPort: z.string().optional(),
|
||||
})
|
||||
.refine((data) => (data.resourceType === "loadbalancer" || data.resourceType === "listener" ? !!data.loadbalancerId?.trim() : true), {
|
||||
message: t("domain.deployment.form.aliyun_clb_loadbalancer_id.placeholder"),
|
||||
path: ["loadbalancerId"],
|
||||
})
|
||||
.refine((data) => (data.resourceType === "listener" ? +data.listenerPort! > 0 && +data.listenerPort! < 65535 : true), {
|
||||
message: t("domain.deployment.form.aliyun_clb_listener_port.placeholder"),
|
||||
path: ["listenerPort"],
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "aliyun-clb",
|
||||
region: "",
|
||||
resourceType: "",
|
||||
loadbalancerId: "",
|
||||
listenerPort: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
region: config.region as string,
|
||||
resourceType: config.resourceType as "loadbalancer" | "listener",
|
||||
loadbalancerId: config.loadbalancerId as string,
|
||||
listenerPort: config.listenerPort as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="region"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.aliyun_clb_region.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.aliyun_clb_region.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="resourceType"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.aliyun_clb_resource_type.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("resourceType", value as "loadbalancer" | "listener");
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t("domain.deployment.form.aliyun_clb_resource_type.placeholder")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="loadbalancer">{t("domain.deployment.form.aliyun_clb_resource_type.option.loadbalancer.label")}</SelectItem>
|
||||
<SelectItem value="listener">{t("domain.deployment.form.aliyun_clb_resource_type.option.listener.label")}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="loadbalancerId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.aliyun_clb_loadbalancer_id.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.aliyun_clb_loadbalancer_id.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="listenerPort"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.aliyun_clb_listener_port.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.aliyun_clb_listener_port.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToAliyunCLB;
|
217
ui/src/components/workflow/DeployToAliyunNLB.tsx
Normal file
217
ui/src/components/workflow/DeployToAliyunNLB.tsx
Normal file
@ -0,0 +1,217 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
|
||||
const DeployToAliyunNLB = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z
|
||||
.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
region: z.string().min(1, t("domain.deployment.form.aliyun_nlb_region.placeholder")),
|
||||
resourceType: z.union([z.literal("loadbalancer"), z.literal("listener")], {
|
||||
message: t("domain.deployment.form.aliyun_nlb_resource_type.placeholder"),
|
||||
}),
|
||||
loadbalancerId: z.string().optional(),
|
||||
listenerId: z.string().optional(),
|
||||
})
|
||||
.refine((data) => (data.resourceType === "loadbalancer" ? !!data.loadbalancerId?.trim() : true), {
|
||||
message: t("domain.deployment.form.aliyun_nlb_loadbalancer_id.placeholder"),
|
||||
path: ["loadbalancerId"],
|
||||
})
|
||||
.refine((data) => (data.resourceType === "listener" ? !!data.listenerId?.trim() : true), {
|
||||
message: t("domain.deployment.form.aliyun_nlb_listener_id.placeholder"),
|
||||
path: ["listenerId"],
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "aliyun-nlb",
|
||||
region: "",
|
||||
resourceType: "",
|
||||
loadbalancerId: "",
|
||||
listenerId: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
region: config.region as string,
|
||||
resourceType: config.resourceType as "loadbalancer" | "listener",
|
||||
loadbalancerId: config.loadbalancerId as string,
|
||||
listenerId: config.listenerId as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="region"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.aliyun_nlb_region.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.aliyun_nlb_region.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="resourceType"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.aliyun_nlb_resource_type.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("resourceType", value as "loadbalancer" | "listener");
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t("domain.deployment.form.aliyun_nlb_resource_type.placeholder")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="loadbalancer">{t("domain.deployment.form.aliyun_nlb_resource_type.option.loadbalancer.label")}</SelectItem>
|
||||
<SelectItem value="listener">{t("domain.deployment.form.aliyun_nlb_resource_type.option.listener.label")}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="loadbalancerId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.aliyun_nlb_loadbalancer_id.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.aliyun_nlb_loadbalancer_id.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="listenerId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.aliyun_nlb_listener_id.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.aliyun_nlb_listener_id.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToAliyunNLB;
|
@ -177,4 +177,3 @@ const DeployToAliyunOSS = ({ data }: DeployFormProps) => {
|
||||
};
|
||||
|
||||
export default DeployToAliyunOSS;
|
||||
|
||||
|
141
ui/src/components/workflow/DeployToBaiduCloudCDN.tsx
Normal file
141
ui/src/components/workflow/DeployToBaiduCloudCDN.tsx
Normal file
@ -0,0 +1,141 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { SelectLabel } from "@radix-ui/react-select";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
const DeployToBaiduCloudCDN = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
domain: z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||
message: t("common.errmsg.domain_invalid"),
|
||||
}),
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "baiducloud-cdn",
|
||||
|
||||
domain: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
domain: config.domain as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="domain"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.domain.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.domain.label")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToBaiduCloudCDN;
|
141
ui/src/components/workflow/DeployToDogeCloudCDN.tsx
Normal file
141
ui/src/components/workflow/DeployToDogeCloudCDN.tsx
Normal file
@ -0,0 +1,141 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { SelectLabel } from "@radix-ui/react-select";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
const DeployToDogeCloudCDN = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
domain: z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||
message: t("common.errmsg.domain_invalid"),
|
||||
}),
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "dogecloud-cdn",
|
||||
|
||||
domain: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
domain: config.domain as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="domain"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.domain.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.domain.label")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToDogeCloudCDN;
|
160
ui/src/components/workflow/DeployToHuaweiCloudCDN.tsx
Normal file
160
ui/src/components/workflow/DeployToHuaweiCloudCDN.tsx
Normal file
@ -0,0 +1,160 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { SelectLabel } from "@radix-ui/react-select";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
const DeployToHuaweiCloudCDN = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
region: z.string().min(1, {
|
||||
message: t("domain.deployment.form.huaweicloud_cdn_region.placeholder"),
|
||||
}),
|
||||
domain: z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||
message: t("common.errmsg.domain_invalid"),
|
||||
}),
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "huaweicloud-cdn",
|
||||
region: "",
|
||||
domain: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
region: config.region as string,
|
||||
domain: config.domain as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="region"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.huaweicloud_cdn_region.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.huaweicloud_cdn_region.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="domain"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.domain.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.domain.label")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToHuaweiCloudCDN;
|
252
ui/src/components/workflow/DeployToHuaweiCloudELB.tsx
Normal file
252
ui/src/components/workflow/DeployToHuaweiCloudELB.tsx
Normal file
@ -0,0 +1,252 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { SelectLabel } from "@radix-ui/react-select";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
const DeployToHuaweiCloudELB = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [resourceType, setResourceType] = useState<"certificate" | "loadbalancer" | "listener">();
|
||||
|
||||
useEffect(() => {
|
||||
setResourceType(data.config?.resourceType as "certificate" | "loadbalancer" | "listener");
|
||||
}, [data]);
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z
|
||||
.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
region: z.string().min(1, t("domain.deployment.form.huaweicloud_elb_region.placeholder")),
|
||||
resourceType: z.union([z.literal("certificate"), z.literal("loadbalancer"), z.literal("listener")], {
|
||||
message: t("domain.deployment.form.huaweicloud_elb_resource_type.placeholder"),
|
||||
}),
|
||||
certificateId: z.string().optional(),
|
||||
loadbalancerId: z.string().optional(),
|
||||
listenerId: z.string().optional(),
|
||||
})
|
||||
.refine((data) => (data.resourceType === "certificate" ? !!data.certificateId?.trim() : true), {
|
||||
message: t("domain.deployment.form.huaweicloud_elb_certificate_id.placeholder"),
|
||||
path: ["certificateId"],
|
||||
})
|
||||
.refine((data) => (data.resourceType === "loadbalancer" ? !!data.loadbalancerId?.trim() : true), {
|
||||
message: t("domain.deployment.form.huaweicloud_elb_loadbalancer_id.placeholder"),
|
||||
path: ["loadbalancerId"],
|
||||
})
|
||||
.refine((data) => (data.resourceType === "listener" ? !!data.listenerId?.trim() : true), {
|
||||
message: t("domain.deployment.form.huaweicloud_elb_listener_id.placeholder"),
|
||||
path: ["listenerId"],
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "huaweicloud-elb",
|
||||
resouceType: "",
|
||||
certificateId: "",
|
||||
loadbalancerId: "",
|
||||
listenerId: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
region: config.region as string,
|
||||
resourceType: config.resourceType as "certificate" | "loadbalancer" | "listener",
|
||||
certificateId: config.certificateId as string,
|
||||
loadbalancerId: config.loadbalancerId as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="region"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.huaweicloud_cdn_region.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.huaweicloud_cdn_region.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="resourceType"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.huaweicloud_elb_resource_type.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
setResourceType(value as "certificate" | "loadbalancer" | "listener");
|
||||
form.setValue("resourceType", value as "loadbalancer" | "certificate" | "listener");
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t("domain.deployment.form.huaweicloud_elb_resource_type.placeholder")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="certificate">{t("domain.deployment.form.huaweicloud_elb_resource_type.option.certificate.label")}</SelectItem>
|
||||
<SelectItem value="loadbalancer">{t("domain.deployment.form.huaweicloud_elb_resource_type.option.loadbalancer.label")}</SelectItem>
|
||||
<SelectItem value="listener">{t("domain.deployment.form.huaweicloud_elb_resource_type.option.listener.label")}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
{resourceType === "certificate" && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificateId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.huaweicloud_elb_certificate_id.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.huaweicloud_elb_certificate_id.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{resourceType === "loadbalancer" && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="loadbalancerId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.huaweicloud_elb_loadbalancer_id.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.huaweicloud_elb_loadbalancer_id.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{resourceType === "listener" && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="listenerId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.huaweicloud_elb_listener_id.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.huaweicloud_elb_listener_id.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToHuaweiCloudELB;
|
196
ui/src/components/workflow/DeployToKubernetesSecret.tsx
Normal file
196
ui/src/components/workflow/DeployToKubernetesSecret.tsx
Normal file
@ -0,0 +1,196 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { SelectLabel } from "@radix-ui/react-select";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
const DeployToKubernetesSecret = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
namespace: z.string().min(1, {
|
||||
message: t("domain.deployment.form.k8s_namespace.placeholder"),
|
||||
}),
|
||||
secretName: z.string().min(1, {
|
||||
message: t("domain.deployment.form.k8s_secret_name.placeholder"),
|
||||
}),
|
||||
secretDataKeyForCrt: z.string().min(1, {
|
||||
message: t("domain.deployment.form.k8s_secret_data_key_for_crt.placeholder"),
|
||||
}),
|
||||
secretDataKeyForKey: z.string().min(1, {
|
||||
message: t("domain.deployment.form.k8s_secret_data_key_for_key.placeholder"),
|
||||
}),
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "k8s-secret",
|
||||
namespace: "",
|
||||
secretName: "",
|
||||
secretDataKeyForCrt: "",
|
||||
secretDataKeyForKey: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
namespace: config.namespace as string,
|
||||
secretName: config.secretName as string,
|
||||
secretDataKeyForCrt: config.secretDataKeyForCrt as string,
|
||||
secretDataKeyForKey: config.secretDataKeyForKey as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="namespace"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.k8s_namespace.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} placeholder={t("domain.deployment.form.k8s_namespace.label")} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="secretName"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.k8s_secret_name.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} placeholder={t("domain.deployment.form.k8s_secret_name.label")} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="secretDataKeyForCrt"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.k8s_secret_data_key_for_crt.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} placeholder={t("domain.deployment.form.k8s_secret_data_key_for_crt.label")} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="secretDataKeyForKey"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.k8s_secret_data_key_for_key.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} placeholder={t("domain.deployment.form.k8s_secret_data_key_for_key.label")} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToKubernetesSecret;
|
432
ui/src/components/workflow/DeployToLocal.tsx
Normal file
432
ui/src/components/workflow/DeployToLocal.tsx
Normal file
@ -0,0 +1,432 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { Button } from "../ui/button";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { useEffect, useState } from "react";
|
||||
import i18n from "@/i18n";
|
||||
import { WorkflowNode } from "@/domain/workflow";
|
||||
import { Textarea } from "../ui/textarea";
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../ui/dropdown-menu";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
|
||||
const t = i18n.t;
|
||||
|
||||
const formSchema = z
|
||||
.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
format: z.union([z.literal("pem"), z.literal("pfx"), z.literal("jks")], {
|
||||
message: t("domain.deployment.form.file_format.placeholder"),
|
||||
}),
|
||||
certPath: z
|
||||
.string()
|
||||
.min(1, t("domain.deployment.form.file_cert_path.placeholder"))
|
||||
.max(255, t("common.errmsg.string_max", { max: 255 })),
|
||||
keyPath: z
|
||||
.string()
|
||||
.min(0, t("domain.deployment.form.file_key_path.placeholder"))
|
||||
.max(255, t("common.errmsg.string_max", { max: 255 })),
|
||||
pfxPassword: z.string().optional(),
|
||||
jksAlias: z.string().optional(),
|
||||
jksKeypass: z.string().optional(),
|
||||
jksStorepass: z.string().optional(),
|
||||
preCommand: z.string().optional(),
|
||||
command: z.string().optional(),
|
||||
shell: z.union([z.literal("sh"), z.literal("cmd"), z.literal("powershell")], {
|
||||
message: t("domain.deployment.form.shell.placeholder"),
|
||||
}),
|
||||
})
|
||||
.refine((data) => (data.format === "pem" ? !!data.keyPath?.trim() : true), {
|
||||
message: t("domain.deployment.form.file_key_path.placeholder"),
|
||||
path: ["keyPath"],
|
||||
})
|
||||
.refine((data) => (data.format === "pfx" ? !!data.pfxPassword?.trim() : true), {
|
||||
message: t("domain.deployment.form.file_pfx_password.placeholder"),
|
||||
path: ["pfxPassword"],
|
||||
})
|
||||
.refine((data) => (data.format === "jks" ? !!data.jksAlias?.trim() : true), {
|
||||
message: t("domain.deployment.form.file_jks_alias.placeholder"),
|
||||
path: ["jksAlias"],
|
||||
})
|
||||
.refine((data) => (data.format === "jks" ? !!data.jksKeypass?.trim() : true), {
|
||||
message: t("domain.deployment.form.file_jks_keypass.placeholder"),
|
||||
path: ["jksKeypass"],
|
||||
})
|
||||
.refine((data) => (data.format === "jks" ? !!data.jksStorepass?.trim() : true), {
|
||||
message: t("domain.deployment.form.file_jks_storepass.placeholder"),
|
||||
path: ["jksStorepass"],
|
||||
});
|
||||
|
||||
const DeployToLocal = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: "local",
|
||||
certificate: data.config?.certificate as string,
|
||||
format: (data.config?.format as "pem" | "pfx" | "jks") || "pem",
|
||||
certPath: (data.config?.certPath as string) || "/etc/ssl/certs/cert.crt",
|
||||
keyPath: (data.config?.keyPath as string) || "/etc/ssl/private/cert.key",
|
||||
pfxPassword: (data.config?.pfxPassword as string) || "",
|
||||
jksAlias: (data.config?.jksAlias as string) || "",
|
||||
jksKeypass: (data.config?.jksKeypass as string) || "",
|
||||
jksStorepass: (data.config?.jksStorepass as string) || "",
|
||||
preCommand: (data.config?.preCommand as string) || "",
|
||||
command: (data.config?.command as string) || "service nginx reload",
|
||||
shell: (data.config?.shell as "sh" | "cmd" | "powershell") || "sh",
|
||||
},
|
||||
});
|
||||
|
||||
const format = form.watch("format");
|
||||
const certPath = form.watch("certPath");
|
||||
|
||||
useEffect(() => {
|
||||
if (format === "pem" && /(.pfx|.jks)$/.test(certPath)) {
|
||||
form.setValue("certPath", certPath.replace(/(.pfx|.jks)$/, ".crt"));
|
||||
} else if (format === "pfx" && /(.crt|.jks)$/.test(certPath)) {
|
||||
form.setValue("certPath", certPath.replace(/(.crt|.jks)$/, ".pfx"));
|
||||
} else if (format === "jks" && /(.crt|.pfx)$/.test(certPath)) {
|
||||
form.setValue("certPath", certPath.replace(/(.crt|.pfx)$/, ".jks"));
|
||||
}
|
||||
}, [format]);
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
const handleUsePresetScript = (key: string) => {
|
||||
switch (key) {
|
||||
case "reload_nginx":
|
||||
{
|
||||
form.setValue("shell", "sh");
|
||||
form.setValue("command", "sudo service nginx reload");
|
||||
}
|
||||
break;
|
||||
|
||||
case "binding_iis":
|
||||
{
|
||||
form.setValue("shell", "powershell");
|
||||
form.setValue(
|
||||
"command",
|
||||
`# 请将以下变量替换为实际值
|
||||
$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":
|
||||
{
|
||||
form.setValue("shell", "powershell");
|
||||
form.setValue(
|
||||
"command",
|
||||
`# 请将以下变量替换为实际值
|
||||
$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 {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="format"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.file_format.label")}</FormLabel>
|
||||
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t("domain.deployment.form.file_format.placeholder")} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="pem">PEM</SelectItem>
|
||||
<SelectItem value="pfx">PFX</SelectItem>
|
||||
<SelectItem value="jks">JKS</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certPath"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.file_cert_path.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.file_cert_path.label")} {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="keyPath"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>密钥路径</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="输入密钥路径" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
{format === "pfx" && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="pfxPassword"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>PFX 密码</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="password" placeholder="输入 PFX 密码" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{format === "jks" && (
|
||||
<>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="jksAlias"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>JKS 别名</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="输入 JKS 别名" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="jksKeypass"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>JKS Keypass</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="password" placeholder="输入 JKS Keypass" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="jksStorepass"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>JKS Storepass</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="password" placeholder="输入 JKS Storepass" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="shell"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.shell.label")}</FormLabel>
|
||||
<Select onValueChange={field.onChange} value={field.value}>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t("domain.deployment.form.shell.placeholder")} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="sh">POSIX Bash (Linux)</SelectItem>
|
||||
<SelectItem value="cmd">CMD (Windows)</SelectItem>
|
||||
<SelectItem value="powershell">PowerShell (Windows)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="preCommand"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.shell_pre_command.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea placeholder={t("domain.deployment.form.shell_pre_command.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="command"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel className="flex justify-between items-center">
|
||||
<div>{t("domain.deployment.form.shell_command.label")}</div>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<a className="text-xs text-blue-500 cursor-pointer">{t("domain.deployment.form.shell_preset_scripts.trigger")}</a>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem onClick={() => handleUsePresetScript("reload_nginx")}>
|
||||
{t("domain.deployment.form.shell_preset_scripts.option.reload_nginx.label")}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleUsePresetScript("binding_iis")}>
|
||||
{t("domain.deployment.form.shell_preset_scripts.option.binding_iis.label")}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => handleUsePresetScript("binding_netsh")}>
|
||||
{t("domain.deployment.form.shell_preset_scripts.option.binding_netsh.label")}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea placeholder={t("domain.deployment.form.shell_command.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToLocal;
|
141
ui/src/components/workflow/DeployToQiniuCDN.tsx
Normal file
141
ui/src/components/workflow/DeployToQiniuCDN.tsx
Normal file
@ -0,0 +1,141 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { SelectLabel } from "@radix-ui/react-select";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
const DeployToQiniuCDN = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
domain: z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||
message: t("common.errmsg.domain_invalid"),
|
||||
}),
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "qiniu-cdn",
|
||||
|
||||
domain: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
domain: config.domain as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="domain"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.domain.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.domain.label")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToQiniuCDN;
|
309
ui/src/components/workflow/DeployToSSH.tsx
Normal file
309
ui/src/components/workflow/DeployToSSH.tsx
Normal file
@ -0,0 +1,309 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { Button } from "../ui/button";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { useEffect, useState } from "react";
|
||||
import i18n from "@/i18n";
|
||||
import { WorkflowNode } from "@/domain/workflow";
|
||||
import { Textarea } from "../ui/textarea";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
|
||||
const t = i18n.t;
|
||||
|
||||
const formSchema = z
|
||||
.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
format: z.union([z.literal("pem"), z.literal("pfx"), z.literal("jks")], {
|
||||
message: t("domain.deployment.form.file_format.placeholder"),
|
||||
}),
|
||||
certPath: z
|
||||
.string()
|
||||
.min(1, t("domain.deployment.form.file_cert_path.placeholder"))
|
||||
.max(255, t("common.errmsg.string_max", { max: 255 })),
|
||||
keyPath: z
|
||||
.string()
|
||||
.min(0, t("domain.deployment.form.file_key_path.placeholder"))
|
||||
.max(255, t("common.errmsg.string_max", { max: 255 })),
|
||||
pfxPassword: z.string().optional(),
|
||||
jksAlias: z.string().optional(),
|
||||
jksKeypass: z.string().optional(),
|
||||
jksStorepass: z.string().optional(),
|
||||
preCommand: z.string().optional(),
|
||||
command: z.string().optional(),
|
||||
})
|
||||
.refine((data) => (data.format === "pem" ? !!data.keyPath?.trim() : true), {
|
||||
message: t("domain.deployment.form.file_key_path.placeholder"),
|
||||
path: ["keyPath"],
|
||||
})
|
||||
.refine((data) => (data.format === "pfx" ? !!data.pfxPassword?.trim() : true), {
|
||||
message: t("domain.deployment.form.file_pfx_password.placeholder"),
|
||||
path: ["pfxPassword"],
|
||||
})
|
||||
.refine((data) => (data.format === "jks" ? !!data.jksAlias?.trim() : true), {
|
||||
message: t("domain.deployment.form.file_jks_alias.placeholder"),
|
||||
path: ["jksAlias"],
|
||||
})
|
||||
.refine((data) => (data.format === "jks" ? !!data.jksKeypass?.trim() : true), {
|
||||
message: t("domain.deployment.form.file_jks_keypass.placeholder"),
|
||||
path: ["jksKeypass"],
|
||||
})
|
||||
.refine((data) => (data.format === "jks" ? !!data.jksStorepass?.trim() : true), {
|
||||
message: t("domain.deployment.form.file_jks_storepass.placeholder"),
|
||||
path: ["jksStorepass"],
|
||||
});
|
||||
|
||||
const DeployToSSH = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: "ssh",
|
||||
certificate: data.config?.certificate as string,
|
||||
format: (data.config?.format as "pem" | "pfx" | "jks") || "pem",
|
||||
certPath: (data.config?.certPath as string) || "/etc/ssl/certs/cert.crt",
|
||||
keyPath: (data.config?.keyPath as string) || "/etc/ssl/private/cert.key",
|
||||
pfxPassword: (data.config?.pfxPassword as string) || "",
|
||||
jksAlias: (data.config?.jksAlias as string) || "",
|
||||
jksKeypass: (data.config?.jksKeypass as string) || "",
|
||||
jksStorepass: (data.config?.jksStorepass as string) || "",
|
||||
preCommand: (data.config?.preCommand as string) || "",
|
||||
command: (data.config?.command as string) || "service nginx reload",
|
||||
},
|
||||
});
|
||||
|
||||
const format = form.watch("format");
|
||||
const certPath = form.watch("certPath");
|
||||
|
||||
useEffect(() => {
|
||||
if (format === "pem" && /(.pfx|.jks)$/.test(certPath)) {
|
||||
form.setValue("certPath", certPath.replace(/(.pfx|.jks)$/, ".crt"));
|
||||
} else if (format === "pfx" && /(.crt|.jks)$/.test(certPath)) {
|
||||
form.setValue("certPath", certPath.replace(/(.crt|.jks)$/, ".pfx"));
|
||||
} else if (format === "jks" && /(.crt|.pfx)$/.test(certPath)) {
|
||||
form.setValue("certPath", certPath.replace(/(.crt|.pfx)$/, ".jks"));
|
||||
}
|
||||
}, [format]);
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="format"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.file_format.label")}</FormLabel>
|
||||
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t("domain.deployment.form.file_format.placeholder")} />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="pem">PEM</SelectItem>
|
||||
<SelectItem value="pfx">PFX</SelectItem>
|
||||
<SelectItem value="jks">JKS</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certPath"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.file_cert_path.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.file_cert_path.label")} {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="keyPath"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>密钥路径</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="输入密钥路径" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
{format === "pfx" && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="pfxPassword"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>PFX 密码</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="password" placeholder="输入 PFX 密码" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{format === "jks" && (
|
||||
<>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="jksAlias"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>JKS 别名</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="输入 JKS 别名" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="jksKeypass"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>JKS Keypass</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="password" placeholder="输入 JKS Keypass" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="jksStorepass"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>JKS Storepass</FormLabel>
|
||||
<FormControl>
|
||||
<Input type="password" placeholder="输入 JKS Storepass" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="preCommand"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.shell_pre_command.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea placeholder={t("domain.deployment.form.shell_pre_command.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="command"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.shell_command.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea placeholder={t("domain.deployment.form.shell_command.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToSSH;
|
141
ui/src/components/workflow/DeployToTencentCDN.tsx
Normal file
141
ui/src/components/workflow/DeployToTencentCDN.tsx
Normal file
@ -0,0 +1,141 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { SelectLabel } from "@radix-ui/react-select";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
const DeployToTencentCDN = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
domain: z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||
message: t("common.errmsg.domain_invalid"),
|
||||
}),
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "tencent-cdn",
|
||||
|
||||
domain: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
domain: config.domain as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="domain"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.domain.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.domain.label")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToTencentCDN;
|
280
ui/src/components/workflow/DeployToTencentCLB.tsx
Normal file
280
ui/src/components/workflow/DeployToTencentCLB.tsx
Normal file
@ -0,0 +1,280 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { SelectLabel } from "@radix-ui/react-select";
|
||||
|
||||
type TencentResourceType = "ssl-deploy" | "loadbalancer" | "listener" | "ruledomain";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
const DeployToTencentCLB = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [resourceType, setResourceType] = useState<TencentResourceType>();
|
||||
|
||||
useEffect(() => {
|
||||
setResourceType(data.config?.resourceType as TencentResourceType);
|
||||
}, [data]);
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z
|
||||
.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
region: z.string().min(1, t("domain.deployment.form.tencent_clb_region.placeholder")),
|
||||
resourceType: z.union([z.literal("ssl-deploy"), z.literal("loadbalancer"), z.literal("listener"), z.literal("ruledomain")], {
|
||||
message: t("domain.deployment.form.tencent_clb_resource_type.placeholder"),
|
||||
}),
|
||||
loadbalancerId: z.string().min(1, t("domain.deployment.form.tencent_clb_loadbalancer_id.placeholder")),
|
||||
listenerId: z.string().optional(),
|
||||
domain: z.string().regex(/^$|^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||
message: t("common.errmsg.domain_invalid"),
|
||||
}),
|
||||
})
|
||||
.refine(
|
||||
(data) => {
|
||||
switch (data.resourceType) {
|
||||
case "ssl-deploy":
|
||||
case "listener":
|
||||
case "ruledomain":
|
||||
return !!data.listenerId?.trim();
|
||||
}
|
||||
return true;
|
||||
},
|
||||
{
|
||||
message: t("domain.deployment.form.tencent_clb_listener_id.placeholder"),
|
||||
path: ["listenerId"],
|
||||
}
|
||||
)
|
||||
.refine((data) => (data.resourceType === "ruledomain" ? !!data.domain?.trim() : true), {
|
||||
message: t("domain.deployment.form.tencent_clb_ruledomain.placeholder"),
|
||||
path: ["domain"],
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "tencent-clb",
|
||||
resouceType: "",
|
||||
domain: "",
|
||||
loadbalancerId: "",
|
||||
listenerId: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
region: config.region as string,
|
||||
resourceType: config.resourceType as TencentResourceType,
|
||||
domain: config.certificateId as string,
|
||||
loadbalancerId: config.loadbalancerId as string,
|
||||
listenerId: config.listenerId as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="region"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.huaweicloud_cdn_region.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.huaweicloud_cdn_region.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="resourceType"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.tencent_clb_resource_type.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
setResourceType(value as TencentResourceType);
|
||||
form.setValue("resourceType", value as TencentResourceType);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder={t("domain.deployment.form.tencent_clb_resource_type.placeholder")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value="ssl-deploy">{t("domain.deployment.form.tencent_clb_resource_type.option.ssl_deploy.label")}</SelectItem>
|
||||
<SelectItem value="loadbalancer">{t("domain.deployment.form.tencent_clb_resource_type.option.loadbalancer.label")}</SelectItem>
|
||||
<SelectItem value="listener">{t("domain.deployment.form.tencent_clb_resource_type.option.listener.label")}</SelectItem>
|
||||
<SelectItem value="ruledomain">{t("domain.deployment.form.tencent_clb_resource_type.option.ruledomain.label")}</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="loadbalancerId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.tencent_clb_loadbalancer_id.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.tencent_clb_loadbalancer_id.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
{(resourceType === "ssl-deploy" || resourceType === "listener" || resourceType === "ruledomain") && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="listenerId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.tencent_clb_listener_id.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.tencent_clb_listener_id.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{resourceType === "ssl-deploy" && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="domain"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.tencent_clb_domain.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.tencent_clb_domain.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
{resourceType === "ruledomain" && (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="domain"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.tencent_clb_ruledomain.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.tencent_clb_ruledomain.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToTencentCLB;
|
176
ui/src/components/workflow/DeployToTencentCOS.tsx
Normal file
176
ui/src/components/workflow/DeployToTencentCOS.tsx
Normal file
@ -0,0 +1,176 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { SelectLabel } from "@radix-ui/react-select";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
const DeployToTencentCOS = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
region: z.string().min(1, t("domain.deployment.form.tencent_cos_region.placeholder")),
|
||||
bucket: z.string().min(1, t("domain.deployment.form.tencent_cos_bucket.placeholder")),
|
||||
domain: z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||
message: t("common.errmsg.domain_invalid"),
|
||||
}),
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "tencent-cos",
|
||||
region: "",
|
||||
bucket: "",
|
||||
domain: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
region: config.region as string,
|
||||
bucket: config.bucket as string,
|
||||
domain: config.domain as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="region"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.tencent_cos_region.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.tencent_cos_region.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="bucket"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.tencent_cos_bucket.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.tencent_cos_bucket.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="domain"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.domain.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.domain.label")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToTencentCOS;
|
158
ui/src/components/workflow/DeployToTencentTEO.tsx
Normal file
158
ui/src/components/workflow/DeployToTencentTEO.tsx
Normal file
@ -0,0 +1,158 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { SelectLabel } from "@radix-ui/react-select";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
const DeployToTencentTEO = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
console.log(rs);
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
zoneId: z.string().min(1, t("domain.deployment.form.tencent_teo_zone_id.placeholder")),
|
||||
domain: z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||
message: t("common.errmsg.domain_invalid"),
|
||||
}),
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "tencent-teo",
|
||||
zoneId: "",
|
||||
domain: "",
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
zoneId: config.zoneId as string,
|
||||
domain: config.domain as string,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="zoneId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.tencent_teo_zone_id.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.tencent_teo_zone_id.placeholder")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="domain"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t("domain.deployment.form.domain.label")}</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder={t("domain.deployment.form.domain.label")} {...field} />
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToTencentTEO;
|
145
ui/src/components/workflow/DeployToWebhook.tsx
Normal file
145
ui/src/components/workflow/DeployToWebhook.tsx
Normal file
@ -0,0 +1,145 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
|
||||
import { DeployFormProps } from "./DeployForm";
|
||||
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "../ui/form";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
|
||||
import { useWorkflowStore, WorkflowState } from "@/providers/workflow";
|
||||
import { useShallow } from "zustand/shallow";
|
||||
import { usePanel } from "./PanelProvider";
|
||||
import { Button } from "../ui/button";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "../ui/select";
|
||||
import { SelectLabel } from "@radix-ui/react-select";
|
||||
import KVList from "../certimate/KVList";
|
||||
|
||||
const selectState = (state: WorkflowState) => ({
|
||||
updateNode: state.updateNode,
|
||||
getWorkflowOuptutBeforeId: state.getWorkflowOuptutBeforeId,
|
||||
});
|
||||
|
||||
const KVTypeSchema = z.object({
|
||||
key: z.string(),
|
||||
value: z.string(),
|
||||
});
|
||||
const DeployToWebhook = ({ data }: DeployFormProps) => {
|
||||
const { updateNode, getWorkflowOuptutBeforeId } = useWorkflowStore(useShallow(selectState));
|
||||
const { hidePanel } = usePanel();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [beforeOutput, setBeforeOutput] = useState<WorkflowNode[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const rs = getWorkflowOuptutBeforeId(data.id, "certificate");
|
||||
setBeforeOutput(rs);
|
||||
}, [data]);
|
||||
|
||||
const formSchema = z.object({
|
||||
providerType: z.string(),
|
||||
certificate: z.string().min(1),
|
||||
variables: z.array(KVTypeSchema).optional(),
|
||||
});
|
||||
|
||||
let config: WorkflowNodeConfig = {
|
||||
certificate: "",
|
||||
providerType: "webhook",
|
||||
|
||||
variables: [],
|
||||
};
|
||||
if (data) config = data.config ?? config;
|
||||
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
providerType: config.providerType as string,
|
||||
certificate: config.certificate as string,
|
||||
variables: config.variables as { key: string; value: string }[],
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (config: z.infer<typeof formSchema>) => {
|
||||
console.log(config);
|
||||
updateNode({ ...data, config: { ...config } });
|
||||
hidePanel();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.stopPropagation();
|
||||
form.handleSubmit(onSubmit)(e);
|
||||
}}
|
||||
className="space-y-8"
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="certificate"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>证书</FormLabel>
|
||||
<FormControl>
|
||||
<Select
|
||||
{...field}
|
||||
value={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("certificate", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="选择证书来源" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
{beforeOutput.map((item) => (
|
||||
<>
|
||||
<SelectGroup key={item.id}>
|
||||
<SelectLabel>{item.name}</SelectLabel>
|
||||
{item.output?.map((output) => (
|
||||
<SelectItem key={output.name} value={`${item.id}#${output.name}`}>
|
||||
<div>
|
||||
{item.name}-{output.label}
|
||||
</div>
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectGroup>
|
||||
</>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="variables"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<KVList
|
||||
{...field}
|
||||
variables={field.value}
|
||||
onValueChange={(value) => {
|
||||
form.setValue("variables", value);
|
||||
}}
|
||||
/>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end">
|
||||
<Button type="submit">{t("common.save")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToWebhook;
|
@ -178,4 +178,3 @@ const NotifyForm = ({ data }: NotifyFormProps) => {
|
||||
};
|
||||
|
||||
export default NotifyForm;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
// components/AddNodePanel.tsx
|
||||
import { ScrollArea } from "../ui/scroll-area";
|
||||
import { Sheet, SheetContent, SheetTitle } from "../ui/sheet";
|
||||
|
||||
type AddNodePanelProps = {
|
||||
@ -14,7 +15,7 @@ const Panel = ({ open, onOpenChange, children, name }: AddNodePanelProps) => {
|
||||
<SheetContent className="sm:max-w-[640px] p-0">
|
||||
<SheetTitle className="bg-primary p-4 text-white">{name}</SheetTitle>
|
||||
|
||||
<div className="p-10 flex-col space-y-5">{children}</div>
|
||||
<ScrollArea className="p-10 flex-col space-y-5 h-[90vh]">{children}</ScrollArea>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
);
|
||||
|
@ -31,4 +31,3 @@ const PanelBody = ({ data }: PanelBodyProps) => {
|
||||
};
|
||||
|
||||
export default PanelBody;
|
||||
|
||||
|
@ -119,4 +119,3 @@ export type SSLProviderSetting = {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { produce } from "immer";
|
||||
import { nanoid } from "nanoid";
|
||||
import { accessProviders } from "./access";
|
||||
import i18n from "@/i18n";
|
||||
import { deployTargets } from "./domain";
|
||||
import { deployTargets, KVType } from "./domain";
|
||||
|
||||
export enum WorkflowNodeType {
|
||||
Start = "start",
|
||||
@ -72,7 +71,7 @@ export const workflowNodeTypeDefaultOutput: Map<WorkflowNodeType, WorkflowNodeIo
|
||||
[WorkflowNodeType.Notify, []],
|
||||
]);
|
||||
|
||||
export type WorkflowNodeConfig = Record<string, string | boolean | number | string[] | undefined>;
|
||||
export type WorkflowNodeConfig = Record<string, string | boolean | number | KVType[] | string[] | undefined>;
|
||||
|
||||
export type WorkflowNode = {
|
||||
id: string;
|
||||
@ -369,4 +368,3 @@ export const workflowNodeDropdownList: WorkflowwNodeDropdwonItem[] = [
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
|
@ -36,8 +36,8 @@ const Workflow = () => {
|
||||
return (
|
||||
<>
|
||||
<WorkflowProvider>
|
||||
<ScrollArea className="h-[100vh] w-full bg-slate-50 relative">
|
||||
<div className="h-16 sticky top-0 left-0 z-20 shadow-md bg-white"></div>
|
||||
<ScrollArea className="h-[100vh] w-full relative bg-background">
|
||||
<div className="h-16 sticky top-0 left-0 z-20 shadow-md bg-muted/40"></div>
|
||||
|
||||
<div className=" flex flex-col items-center mt-8">{elements}</div>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user