mirror of
https://github.com/usual2970/certimate.git
synced 2025-10-04 21:44:54 +00:00
Merge branch 'main' into feat/multiple-certificate-formats
This commit is contained in:
@@ -37,7 +37,7 @@ const AccessKubernetesForm = ({ data, op, onAfterReq }: AccessKubernetesFormProp
|
||||
configType: accessTypeFormSchema,
|
||||
kubeConfig: z
|
||||
.string()
|
||||
.min(1, "access.authorization.form.k8s_kubeconfig.placeholder")
|
||||
.min(0, "access.authorization.form.k8s_kubeconfig.placeholder")
|
||||
.max(20480, t("common.errmsg.string_max", { max: 20480 })),
|
||||
kubeConfigFile: z.any().optional(),
|
||||
});
|
||||
@@ -191,3 +191,4 @@ const AccessKubernetesForm = ({ data, op, onAfterReq }: AccessKubernetesFormProp
|
||||
};
|
||||
|
||||
export default AccessKubernetesForm;
|
||||
|
||||
|
@@ -11,9 +11,13 @@ import AccessEditDialog from "./AccessEditDialog";
|
||||
import { Context as DeployEditContext } from "./DeployEdit";
|
||||
import DeployToAliyunOSS from "./DeployToAliyunOSS";
|
||||
import DeployToAliyunCDN from "./DeployToAliyunCDN";
|
||||
import DeployToAliyunCLB from "./DeployToAliyunCLB";
|
||||
import DeployToAliyunALB from "./DeployToAliyunALB";
|
||||
import DeployToAliyunNLB from "./DeployToAliyunNLB";
|
||||
import DeployToTencentCDN from "./DeployToTencentCDN";
|
||||
import DeployToTencentCLB from "./DeployToTencentCLB";
|
||||
import DeployToTencentCOS from "./DeployToTencentCOS";
|
||||
import DeployToTencentTEO from "./DeployToTencentTEO";
|
||||
import DeployToHuaweiCloudCDN from "./DeployToHuaweiCloudCDN";
|
||||
import DeployToHuaweiCloudELB from "./DeployToHuaweiCloudELB";
|
||||
import DeployToQiniuCDN from "./DeployToQiniuCDN";
|
||||
@@ -119,7 +123,17 @@ const DeployEditDialog = ({ trigger, deployConfig, onSave }: DeployEditDialogPro
|
||||
case "aliyun-dcdn":
|
||||
childComponent = <DeployToAliyunCDN />;
|
||||
break;
|
||||
case "aliyun-clb":
|
||||
childComponent = <DeployToAliyunCLB />;
|
||||
break;
|
||||
case "aliyun-alb":
|
||||
childComponent = <DeployToAliyunALB />;
|
||||
break;
|
||||
case "aliyun-nlb":
|
||||
childComponent = <DeployToAliyunNLB />;
|
||||
break;
|
||||
case "tencent-cdn":
|
||||
case "tencent-ecdn":
|
||||
childComponent = <DeployToTencentCDN />;
|
||||
break;
|
||||
case "tencent-clb":
|
||||
@@ -128,6 +142,9 @@ const DeployEditDialog = ({ trigger, deployConfig, onSave }: DeployEditDialogPro
|
||||
case "tencent-cos":
|
||||
childComponent = <DeployToTencentCOS />;
|
||||
break;
|
||||
case "tencent-teo":
|
||||
childComponent = <DeployToTencentTEO />;
|
||||
break;
|
||||
case "huaweicloud-cdn":
|
||||
childComponent = <DeployToHuaweiCloudCDN />;
|
||||
break;
|
||||
|
162
ui/src/components/certimate/DeployToAliyunALB.tsx
Normal file
162
ui/src/components/certimate/DeployToAliyunALB.tsx
Normal file
@@ -0,0 +1,162 @@
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
import { produce } from "immer";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { useDeployEditContext } from "./DeployEdit";
|
||||
|
||||
const DeployToAliyunALB = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { deploy: data, setDeploy, error, setError } = useDeployEditContext();
|
||||
|
||||
useEffect(() => {
|
||||
if (!data.id) {
|
||||
setDeploy({
|
||||
...data,
|
||||
config: {
|
||||
region: "cn-hangzhou",
|
||||
resourceType: "",
|
||||
loadbalancerId: "",
|
||||
listenerId: "",
|
||||
},
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setError({});
|
||||
}, []);
|
||||
|
||||
const formSchema = z
|
||||
.object({
|
||||
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"],
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const res = formSchema.safeParse(data.config);
|
||||
if (!res.success) {
|
||||
setError({
|
||||
...error,
|
||||
region: res.error.errors.find((e) => e.path[0] === "region")?.message,
|
||||
resourceType: res.error.errors.find((e) => e.path[0] === "resourceType")?.message,
|
||||
loadbalancerId: res.error.errors.find((e) => e.path[0] === "loadbalancerId")?.message,
|
||||
listenerId: res.error.errors.find((e) => e.path[0] === "listenerId")?.message,
|
||||
});
|
||||
} else {
|
||||
setError({
|
||||
...error,
|
||||
region: undefined,
|
||||
resourceType: undefined,
|
||||
loadbalancerId: undefined,
|
||||
listenerId: undefined,
|
||||
});
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col space-y-8">
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.aliyun_alb_region.label")}</Label>
|
||||
<Input
|
||||
placeholder={t("domain.deployment.form.aliyun_alb_region.placeholder")}
|
||||
className="w-full mt-1"
|
||||
value={data?.config?.region}
|
||||
onChange={(e) => {
|
||||
const newData = produce(data, (draft) => {
|
||||
draft.config ??= {};
|
||||
draft.config.region = e.target.value?.trim();
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.region}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.aliyun_alb_resource_type.label")}</Label>
|
||||
<Select
|
||||
value={data?.config?.resourceType}
|
||||
onValueChange={(value) => {
|
||||
const newData = produce(data, (draft) => {
|
||||
draft.config ??= {};
|
||||
draft.config.resourceType = value?.trim();
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
>
|
||||
<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>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.resourceType}</div>
|
||||
</div>
|
||||
|
||||
{data?.config?.resourceType === "loadbalancer" ? (
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.aliyun_alb_loadbalancer_id.label")}</Label>
|
||||
<Input
|
||||
placeholder={t("domain.deployment.form.aliyun_alb_loadbalancer_id.placeholder")}
|
||||
className="w-full mt-1"
|
||||
value={data?.config?.loadbalancerId}
|
||||
onChange={(e) => {
|
||||
const newData = produce(data, (draft) => {
|
||||
draft.config ??= {};
|
||||
draft.config.loadbalancerId = e.target.value?.trim();
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.loadbalancerId}</div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
|
||||
{data?.config?.resourceType === "listener" ? (
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.aliyun_alb_listener_id.label")}</Label>
|
||||
<Input
|
||||
placeholder={t("domain.deployment.form.aliyun_alb_listener_id.placeholder")}
|
||||
className="w-full mt-1"
|
||||
value={data?.config?.listenerId}
|
||||
onChange={(e) => {
|
||||
const newData = produce(data, (draft) => {
|
||||
draft.config ??= {};
|
||||
draft.config.listenerId = e.target.value?.trim();
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.listenerId}</div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToAliyunALB;
|
158
ui/src/components/certimate/DeployToAliyunCLB.tsx
Normal file
158
ui/src/components/certimate/DeployToAliyunCLB.tsx
Normal file
@@ -0,0 +1,158 @@
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
import { produce } from "immer";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { useDeployEditContext } from "./DeployEdit";
|
||||
|
||||
const DeployToAliyunCLB = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { deploy: data, setDeploy, error, setError } = useDeployEditContext();
|
||||
|
||||
useEffect(() => {
|
||||
if (!data.id) {
|
||||
setDeploy({
|
||||
...data,
|
||||
config: {
|
||||
region: "cn-hangzhou",
|
||||
resourceType: "",
|
||||
loadbalancerId: "",
|
||||
listenerPort: "443",
|
||||
},
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setError({});
|
||||
}, []);
|
||||
|
||||
const formSchema = z
|
||||
.object({
|
||||
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"],
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const res = formSchema.safeParse(data.config);
|
||||
if (!res.success) {
|
||||
setError({
|
||||
...error,
|
||||
region: res.error.errors.find((e) => e.path[0] === "region")?.message,
|
||||
resourceType: res.error.errors.find((e) => e.path[0] === "resourceType")?.message,
|
||||
loadbalancerId: res.error.errors.find((e) => e.path[0] === "loadbalancerId")?.message,
|
||||
listenerPort: res.error.errors.find((e) => e.path[0] === "listenerPort")?.message,
|
||||
});
|
||||
} else {
|
||||
setError({
|
||||
...error,
|
||||
region: undefined,
|
||||
resourceType: undefined,
|
||||
loadbalancerId: undefined,
|
||||
listenerPort: undefined,
|
||||
});
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col space-y-8">
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.aliyun_clb_region.label")}</Label>
|
||||
<Input
|
||||
placeholder={t("domain.deployment.form.aliyun_clb_region.placeholder")}
|
||||
className="w-full mt-1"
|
||||
value={data?.config?.region}
|
||||
onChange={(e) => {
|
||||
const newData = produce(data, (draft) => {
|
||||
draft.config ??= {};
|
||||
draft.config.region = e.target.value?.trim();
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.region}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.aliyun_clb_resource_type.label")}</Label>
|
||||
<Select
|
||||
value={data?.config?.resourceType}
|
||||
onValueChange={(value) => {
|
||||
const newData = produce(data, (draft) => {
|
||||
draft.config ??= {};
|
||||
draft.config.resourceType = value?.trim();
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
>
|
||||
<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>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.resourceType}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.aliyun_clb_loadbalancer_id.label")}</Label>
|
||||
<Input
|
||||
placeholder={t("domain.deployment.form.aliyun_clb_loadbalancer_id.placeholder")}
|
||||
className="w-full mt-1"
|
||||
value={data?.config?.loadbalancerId}
|
||||
onChange={(e) => {
|
||||
const newData = produce(data, (draft) => {
|
||||
draft.config ??= {};
|
||||
draft.config.loadbalancerId = e.target.value?.trim();
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.loadbalancerId}</div>
|
||||
</div>
|
||||
|
||||
{data?.config?.resourceType === "listener" ? (
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.aliyun_clb_listener_port.label")}</Label>
|
||||
<Input
|
||||
placeholder={t("domain.deployment.form.aliyun_clb_listener_port.placeholder")}
|
||||
className="w-full mt-1"
|
||||
value={data?.config?.listenerPort}
|
||||
onChange={(e) => {
|
||||
const newData = produce(data, (draft) => {
|
||||
draft.config ??= {};
|
||||
draft.config.listenerPort = e.target.value?.trim();
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.listenerPort}</div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToAliyunCLB;
|
162
ui/src/components/certimate/DeployToAliyunNLB.tsx
Normal file
162
ui/src/components/certimate/DeployToAliyunNLB.tsx
Normal file
@@ -0,0 +1,162 @@
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
import { produce } from "immer";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { useDeployEditContext } from "./DeployEdit";
|
||||
|
||||
const DeployToAliyunNLB = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { deploy: data, setDeploy, error, setError } = useDeployEditContext();
|
||||
|
||||
useEffect(() => {
|
||||
if (!data.id) {
|
||||
setDeploy({
|
||||
...data,
|
||||
config: {
|
||||
region: "cn-hangzhou",
|
||||
resourceType: "",
|
||||
loadbalancerId: "",
|
||||
listenerId: "",
|
||||
},
|
||||
});
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setError({});
|
||||
}, []);
|
||||
|
||||
const formSchema = z
|
||||
.object({
|
||||
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"],
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const res = formSchema.safeParse(data.config);
|
||||
if (!res.success) {
|
||||
setError({
|
||||
...error,
|
||||
region: res.error.errors.find((e) => e.path[0] === "region")?.message,
|
||||
resourceType: res.error.errors.find((e) => e.path[0] === "resourceType")?.message,
|
||||
loadbalancerId: res.error.errors.find((e) => e.path[0] === "loadbalancerId")?.message,
|
||||
listenerId: res.error.errors.find((e) => e.path[0] === "listenerId")?.message,
|
||||
});
|
||||
} else {
|
||||
setError({
|
||||
...error,
|
||||
region: undefined,
|
||||
resourceType: undefined,
|
||||
loadbalancerId: undefined,
|
||||
listenerId: undefined,
|
||||
});
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col space-y-8">
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.aliyun_nlb_region.label")}</Label>
|
||||
<Input
|
||||
placeholder={t("domain.deployment.form.aliyun_nlb_region.placeholder")}
|
||||
className="w-full mt-1"
|
||||
value={data?.config?.region}
|
||||
onChange={(e) => {
|
||||
const newData = produce(data, (draft) => {
|
||||
draft.config ??= {};
|
||||
draft.config.region = e.target.value?.trim();
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.region}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.aliyun_nlb_resource_type.label")}</Label>
|
||||
<Select
|
||||
value={data?.config?.resourceType}
|
||||
onValueChange={(value) => {
|
||||
const newData = produce(data, (draft) => {
|
||||
draft.config ??= {};
|
||||
draft.config.resourceType = value?.trim();
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
>
|
||||
<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>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.resourceType}</div>
|
||||
</div>
|
||||
|
||||
{data?.config?.resourceType === "loadbalancer" ? (
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.aliyun_nlb_loadbalancer_id.label")}</Label>
|
||||
<Input
|
||||
placeholder={t("domain.deployment.form.aliyun_nlb_loadbalancer_id.placeholder")}
|
||||
className="w-full mt-1"
|
||||
value={data?.config?.loadbalancerId}
|
||||
onChange={(e) => {
|
||||
const newData = produce(data, (draft) => {
|
||||
draft.config ??= {};
|
||||
draft.config.loadbalancerId = e.target.value?.trim();
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.loadbalancerId}</div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
|
||||
{data?.config?.resourceType === "listener" ? (
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.aliyun_nlb_listener_id.label")}</Label>
|
||||
<Input
|
||||
placeholder={t("domain.deployment.form.aliyun_nlb_listener_id.placeholder")}
|
||||
className="w-full mt-1"
|
||||
value={data?.config?.listenerId}
|
||||
onChange={(e) => {
|
||||
const newData = produce(data, (draft) => {
|
||||
draft.config ??= {};
|
||||
draft.config.listenerId = e.target.value?.trim();
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.listenerId}</div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToAliyunNLB;
|
@@ -44,7 +44,7 @@ const DeployToHuaweiCloudCDN = () => {
|
||||
message: t("domain.deployment.form.huaweicloud_elb_certificate_id.placeholder"),
|
||||
path: ["certificateId"],
|
||||
})
|
||||
.refine((data) => (data.resourceType === "loadbalancer" ? !!data.certificateId?.trim() : true), {
|
||||
.refine((data) => (data.resourceType === "loadbalancer" ? !!data.loadbalancerId?.trim() : true), {
|
||||
message: t("domain.deployment.form.huaweicloud_elb_loadbalancer_id.placeholder"),
|
||||
path: ["loadbalancerId"],
|
||||
})
|
||||
|
131
ui/src/components/certimate/DeployToTencentTEO.tsx
Normal file
131
ui/src/components/certimate/DeployToTencentTEO.tsx
Normal file
@@ -0,0 +1,131 @@
|
||||
import { useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { z } from "zod";
|
||||
import { produce } from "immer";
|
||||
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { useDeployEditContext } from "./DeployEdit";
|
||||
|
||||
const DeployToTencentTEO = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const { deploy: data, setDeploy, error, setError } = useDeployEditContext();
|
||||
|
||||
useEffect(() => {
|
||||
setError({});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const resp = domainSchema.safeParse(data.config?.domain);
|
||||
if (!resp.success) {
|
||||
setError({
|
||||
...error,
|
||||
domain: JSON.parse(resp.error.message)[0].message,
|
||||
});
|
||||
} else {
|
||||
setError({
|
||||
...error,
|
||||
domain: "",
|
||||
});
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
useEffect(() => {
|
||||
const resp = zoneIdSchema.safeParse(data.config?.zoneId);
|
||||
if (!resp.success) {
|
||||
setError({
|
||||
...error,
|
||||
zoneId: JSON.parse(resp.error.message)[0].message,
|
||||
});
|
||||
} else {
|
||||
setError({
|
||||
...error,
|
||||
zoneId: "",
|
||||
});
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
const domainSchema = z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||
message: t("common.errmsg.domain_invalid"),
|
||||
});
|
||||
|
||||
const zoneIdSchema = z.string().regex(/^zone-[0-9a-zA-Z]{9}$/, {
|
||||
message: t("common.errmsg.zoneid_invalid"),
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="flex flex-col space-y-8">
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.tencent_teo_zone_id.label")}</Label>
|
||||
<Input
|
||||
placeholder={t("domain.deployment.form.tencent_teo_zone_id.placeholder")}
|
||||
className="w-full mt-1"
|
||||
value={data?.config?.zoneId}
|
||||
onChange={(e) => {
|
||||
const temp = e.target.value;
|
||||
|
||||
const resp = zoneIdSchema.safeParse(temp);
|
||||
if (!resp.success) {
|
||||
setError({
|
||||
...error,
|
||||
zoneId: JSON.parse(resp.error.message)[0].message,
|
||||
});
|
||||
} else {
|
||||
setError({
|
||||
...error,
|
||||
zoneId: "",
|
||||
});
|
||||
}
|
||||
|
||||
const newData = produce(data, (draft) => {
|
||||
if (!draft.config) {
|
||||
draft.config = {};
|
||||
}
|
||||
draft.config.zoneId = temp;
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.zoneId}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Label>{t("domain.deployment.form.tencent_teo_domain.label")}</Label>
|
||||
<Textarea
|
||||
placeholder={t("domain.deployment.form.tencent_teo_domain.placeholder")}
|
||||
className="w-full mt-1"
|
||||
value={data?.config?.domain}
|
||||
onChange={(e) => {
|
||||
const temp = e.target.value;
|
||||
|
||||
const resp = domainSchema.safeParse(temp);
|
||||
if (!resp.success) {
|
||||
setError({
|
||||
...error,
|
||||
domain: JSON.parse(resp.error.message)[0].message,
|
||||
});
|
||||
} else {
|
||||
setError({
|
||||
...error,
|
||||
domain: "",
|
||||
});
|
||||
}
|
||||
|
||||
const newData = produce(data, (draft) => {
|
||||
if (!draft.config) {
|
||||
draft.config = {};
|
||||
}
|
||||
draft.config.domain = temp;
|
||||
});
|
||||
setDeploy(newData);
|
||||
}}
|
||||
/>
|
||||
<div className="text-red-600 text-sm mt-1">{error?.domain}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default DeployToTencentTEO;
|
236
ui/src/components/notify/ServerChan.tsx
Normal file
236
ui/src/components/notify/ServerChan.tsx
Normal file
@@ -0,0 +1,236 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Switch } from "@/components/ui/switch";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { getErrMessage } from "@/lib/error";
|
||||
import { isValidURL } from "@/lib/url";
|
||||
import { NotifyChannels, NotifyChannelServerChan } from "@/domain/settings";
|
||||
import { update } from "@/repository/settings";
|
||||
import { useNotifyContext } from "@/providers/notify";
|
||||
import { notifyTest } from "@/api/notify";
|
||||
import Show from "@/components/Show";
|
||||
|
||||
type ServerChanSetting = {
|
||||
id: string;
|
||||
name: string;
|
||||
data: NotifyChannelServerChan;
|
||||
};
|
||||
|
||||
const ServerChan = () => {
|
||||
const { config, setChannels } = useNotifyContext();
|
||||
const { t } = useTranslation();
|
||||
const [changed, setChanged] = useState<boolean>(false);
|
||||
|
||||
const [serverchan, setServerChan] = useState<ServerChanSetting>({
|
||||
id: config.id ?? "",
|
||||
name: "notifyChannels",
|
||||
data: {
|
||||
url: "",
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
const [originServerChan, setOriginServerChan] = useState<ServerChanSetting>({
|
||||
id: config.id ?? "",
|
||||
name: "notifyChannels",
|
||||
data: {
|
||||
url: "",
|
||||
enabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setChanged(false);
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailServerChan();
|
||||
setOriginServerChan({
|
||||
id: config.id ?? "",
|
||||
name: "serverchan",
|
||||
data,
|
||||
});
|
||||
}, [config]);
|
||||
|
||||
useEffect(() => {
|
||||
const data = getDetailServerChan();
|
||||
setServerChan({
|
||||
id: config.id ?? "",
|
||||
name: "serverchan",
|
||||
data,
|
||||
});
|
||||
}, [config]);
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
const checkChanged = (data: NotifyChannelServerChan) => {
|
||||
if (data.url !== originServerChan.data.url) {
|
||||
setChanged(true);
|
||||
} else {
|
||||
setChanged(false);
|
||||
}
|
||||
};
|
||||
|
||||
const getDetailServerChan = () => {
|
||||
const df: NotifyChannelServerChan = {
|
||||
url: "",
|
||||
enabled: false,
|
||||
};
|
||||
if (!config.content) {
|
||||
return df;
|
||||
}
|
||||
const chanels = config.content as NotifyChannels;
|
||||
if (!chanels.serverchan) {
|
||||
return df;
|
||||
}
|
||||
|
||||
return chanels.serverchan as NotifyChannelServerChan;
|
||||
};
|
||||
|
||||
const handleSaveClick = async () => {
|
||||
try {
|
||||
serverchan.data.url = serverchan.data.url.trim();
|
||||
if (!isValidURL(serverchan.data.url)) {
|
||||
toast({
|
||||
title: t("common.save.failed.message"),
|
||||
description: t("settings.notification.url.errmsg.invalid"),
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const resp = await update({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
...config.content,
|
||||
serverchan: {
|
||||
...serverchan.data,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
setChannels(resp);
|
||||
toast({
|
||||
title: t("common.save.succeeded.message"),
|
||||
description: t("settings.notification.config.saved.message"),
|
||||
});
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("common.save.failed.message"),
|
||||
description: `${t("settings.notification.config.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handlePushTestClick = async () => {
|
||||
try {
|
||||
await notifyTest("serverchan");
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.success.message"),
|
||||
description: t("settings.notification.config.push.test.message.success.message"),
|
||||
});
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("settings.notification.config.push.test.message.failed.message"),
|
||||
description: `${t("settings.notification.config.push.test.message.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleSwitchChange = async () => {
|
||||
const newData = {
|
||||
...serverchan,
|
||||
data: {
|
||||
...serverchan.data,
|
||||
enabled: !serverchan.data.enabled,
|
||||
},
|
||||
};
|
||||
setServerChan(newData);
|
||||
|
||||
try {
|
||||
const resp = await update({
|
||||
...config,
|
||||
name: "notifyChannels",
|
||||
content: {
|
||||
...config.content,
|
||||
serverchan: {
|
||||
...newData.data,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
setChannels(resp);
|
||||
} catch (e) {
|
||||
const msg = getErrMessage(e);
|
||||
|
||||
toast({
|
||||
title: t("common.save.failed.message"),
|
||||
description: `${t("settings.notification.config.failed.message")}: ${msg}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Input
|
||||
placeholder={t("settings.notification.serverchan.url.placeholder")}
|
||||
value={serverchan.data.url}
|
||||
onChange={(e) => {
|
||||
const newData = {
|
||||
...serverchan,
|
||||
data: {
|
||||
...serverchan.data,
|
||||
url: e.target.value,
|
||||
},
|
||||
};
|
||||
|
||||
checkChanged(newData.data);
|
||||
setServerChan(newData);
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="flex items-center space-x-1 mt-2">
|
||||
<Switch id="airplane-mode" checked={serverchan.data.enabled} onCheckedChange={handleSwitchChange} />
|
||||
<Label htmlFor="airplane-mode">{t("settings.notification.config.enable")}</Label>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end mt-2">
|
||||
<Show when={changed}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
handleSaveClick();
|
||||
}}
|
||||
>
|
||||
{t("common.save")}
|
||||
</Button>
|
||||
</Show>
|
||||
|
||||
<Show when={!changed && serverchan.id != ""}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={() => {
|
||||
handlePushTestClick();
|
||||
}}
|
||||
>
|
||||
{t("settings.notification.config.push.test.message")}
|
||||
</Button>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ServerChan;
|
@@ -75,9 +75,14 @@ export const deployTargetsMap: Map<DeployTarget["type"], DeployTarget> = new Map
|
||||
["aliyun-oss", "common.provider.aliyun.oss", "/imgs/providers/aliyun.svg"],
|
||||
["aliyun-cdn", "common.provider.aliyun.cdn", "/imgs/providers/aliyun.svg"],
|
||||
["aliyun-dcdn", "common.provider.aliyun.dcdn", "/imgs/providers/aliyun.svg"],
|
||||
["aliyun-clb", "common.provider.aliyun.clb", "/imgs/providers/aliyun.svg"],
|
||||
["aliyun-alb", "common.provider.aliyun.alb", "/imgs/providers/aliyun.svg"],
|
||||
["aliyun-nlb", "common.provider.aliyun.nlb", "/imgs/providers/aliyun.svg"],
|
||||
["tencent-cdn", "common.provider.tencent.cdn", "/imgs/providers/tencent.svg"],
|
||||
["tencent-ecdn", "common.provider.tencent.ecdn", "/imgs/providers/tencent.svg"],
|
||||
["tencent-clb", "common.provider.tencent.clb", "/imgs/providers/tencent.svg"],
|
||||
["tencent-cos", "common.provider.tencent.cos", "/imgs/providers/tencent.svg"],
|
||||
["tencent-teo", "common.provider.tencent.teo", "/imgs/providers/tencent.svg"],
|
||||
["huaweicloud-cdn", "common.provider.huaweicloud.cdn", "/imgs/providers/huaweicloud.svg"],
|
||||
["huaweicloud-elb", "common.provider.huaweicloud.elb", "/imgs/providers/huaweicloud.svg"],
|
||||
["qiniu-cdn", "common.provider.qiniu.cdn", "/imgs/providers/qiniu.svg"],
|
||||
|
@@ -22,9 +22,10 @@ export type NotifyChannels = {
|
||||
lark?: NotifyChannel;
|
||||
telegram?: NotifyChannel;
|
||||
webhook?: NotifyChannel;
|
||||
serverchan?: NotifyChannel;
|
||||
};
|
||||
|
||||
export type NotifyChannel = NotifyChannelDingTalk | NotifyChannelLark | NotifyChannelTelegram | NotifyChannelWebhook;
|
||||
export type NotifyChannel = NotifyChannelDingTalk | NotifyChannelLark | NotifyChannelTelegram | NotifyChannelWebhook | NotifyChannelServerChan;
|
||||
|
||||
export type NotifyChannelDingTalk = {
|
||||
accessToken: string;
|
||||
@@ -48,6 +49,11 @@ export type NotifyChannelWebhook = {
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
export type NotifyChannelServerChan = {
|
||||
url: string;
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
export const defaultNotifyTemplate: NotifyTemplate = {
|
||||
title: "您有 {COUNT} 张证书即将过期",
|
||||
content: "有 {COUNT} 张证书即将过期,域名分别为 {DOMAINS},请保持关注!",
|
||||
|
@@ -69,9 +69,9 @@
|
||||
"access.authorization.form.ssh_key_passphrase.placeholder": "Please enter Key Passphrase",
|
||||
"access.authorization.form.webhook_url.label": "Webhook URL",
|
||||
"access.authorization.form.webhook_url.placeholder": "Please enter Webhook URL",
|
||||
"access.authorization.form.k8s_kubeconfig.label": "KubeConfig",
|
||||
"access.authorization.form.k8s_kubeconfig.label": "KubeConfig (Null will use pod's ServiceAccount)",
|
||||
"access.authorization.form.k8s_kubeconfig.placeholder": "Please enter KubeConfig",
|
||||
"access.authorization.form.k8s_kubeconfig_file.placeholder": "Please select file",
|
||||
"access.authorization.form.k8s_kubeconfig_file.placeholder": "Please select file (Null will use pod's ServiceAccount)",
|
||||
|
||||
"access.group.tab": "Authorization Group",
|
||||
|
||||
|
@@ -51,15 +51,21 @@
|
||||
"common.errmsg.host_invalid": "Please enter the correct domain name or IP",
|
||||
"common.errmsg.ip_invalid": "Please enter IP",
|
||||
"common.errmsg.url_invalid": "Please enter a valid URL",
|
||||
"common.errmsg.zoneid_invalid": "Please enter Zone ID",
|
||||
|
||||
"common.provider.aliyun": "Alibaba Cloud",
|
||||
"common.provider.aliyun.oss": "Alibaba Cloud - OSS",
|
||||
"common.provider.aliyun.cdn": "Alibaba Cloud - CDN",
|
||||
"common.provider.aliyun.dcdn": "Alibaba Cloud - DCDN",
|
||||
"common.provider.aliyun.clb": "Alibaba Cloud - CLB",
|
||||
"common.provider.aliyun.alb": "Alibaba Cloud - ALB",
|
||||
"common.provider.aliyun.nlb": "Alibaba Cloud - NLB",
|
||||
"common.provider.tencent": "Tencent Cloud",
|
||||
"common.provider.tencent.cdn": "Tencent Cloud - CDN",
|
||||
"common.provider.tencent.ecdn": "Tencent Cloud - ECDN",
|
||||
"common.provider.tencent.clb": "Tencent Cloud - CLB",
|
||||
"common.provider.tencent.cos": "Tencent Cloud - COS",
|
||||
"common.provider.tencent.teo": "Tencent Cloud - TEO",
|
||||
"common.provider.huaweicloud": "Huawei Cloud",
|
||||
"common.provider.huaweicloud.cdn": "Huawei Cloud - CDN",
|
||||
"common.provider.huaweicloud.elb": "Huawei Cloud - ELB",
|
||||
@@ -74,6 +80,7 @@
|
||||
"common.provider.local": "Local Deployment",
|
||||
"common.provider.ssh": "SSH Deployment",
|
||||
"common.provider.webhook": "Webhook",
|
||||
"common.provider.serverchan": "ServerChan",
|
||||
"common.provider.kubernetes": "Kubernetes",
|
||||
"common.provider.kubernetes.secret": "Kubernetes - Secret",
|
||||
"common.provider.dingtalk": "DingTalk",
|
||||
|
@@ -61,6 +61,36 @@
|
||||
"domain.deployment.form.aliyun_oss_endpoint.placeholder": "Please enter endpoint",
|
||||
"domain.deployment.form.aliyun_oss_bucket.label": "Bucket",
|
||||
"domain.deployment.form.aliyun_oss_bucket.placeholder": "Please enter bucket",
|
||||
"domain.deployment.form.aliyun_clb_region.label": "Region",
|
||||
"domain.deployment.form.aliyun_clb_region.placeholder": "Please enter region (e.g. cn-hangzhou)",
|
||||
"domain.deployment.form.aliyun_clb_resource_type.label": "Resource Type",
|
||||
"domain.deployment.form.aliyun_clb_resource_type.placeholder": "Please select CLB resource type",
|
||||
"domain.deployment.form.aliyun_clb_resource_type.option.loadbalancer.label": "CLB LoadBalancer",
|
||||
"domain.deployment.form.aliyun_clb_resource_type.option.listener.label": "CLB Listener",
|
||||
"domain.deployment.form.aliyun_clb_loadbalancer_id.label": "LoadBalancer ID",
|
||||
"domain.deployment.form.aliyun_clb_loadbalancer_id.placeholder": "Please enter CLB loadbalancer ID",
|
||||
"domain.deployment.form.aliyun_clb_listener_port.label": "Listener Port",
|
||||
"domain.deployment.form.aliyun_clb_listener_port.placeholder": "Please enter CLB listener port",
|
||||
"domain.deployment.form.aliyun_alb_region.label": "Region",
|
||||
"domain.deployment.form.aliyun_alb_region.placeholder": "Please enter region (e.g. cn-hangzhou)",
|
||||
"domain.deployment.form.aliyun_alb_resource_type.label": "Resource Type",
|
||||
"domain.deployment.form.aliyun_alb_resource_type.placeholder": "Please select ALB resource type",
|
||||
"domain.deployment.form.aliyun_alb_resource_type.option.loadbalancer.label": "ALB LoadBalancer",
|
||||
"domain.deployment.form.aliyun_alb_resource_type.option.listener.label": "ALB Listener",
|
||||
"domain.deployment.form.aliyun_alb_loadbalancer_id.label": "LoadBalancer ID",
|
||||
"domain.deployment.form.aliyun_alb_loadbalancer_id.placeholder": "Please enter ALB loadbalancer ID",
|
||||
"domain.deployment.form.aliyun_alb_listener_id.label": "Listener ID",
|
||||
"domain.deployment.form.aliyun_alb_listener_id.placeholder": "Please enter ALB listener ID",
|
||||
"domain.deployment.form.aliyun_nlb_region.label": "Region",
|
||||
"domain.deployment.form.aliyun_nlb_region.placeholder": "Please enter region (e.g. cn-hangzhou)",
|
||||
"domain.deployment.form.aliyun_nlb_resource_type.label": "Resource Type",
|
||||
"domain.deployment.form.aliyun_nlb_resource_type.placeholder": "Please select NLB resource type",
|
||||
"domain.deployment.form.aliyun_nlb_resource_type.option.loadbalancer.label": "NLB LoadBalancer",
|
||||
"domain.deployment.form.aliyun_nlb_resource_type.option.listener.label": "NLB Listener",
|
||||
"domain.deployment.form.aliyun_nlb_loadbalancer_id.label": "LoadBalancer ID",
|
||||
"domain.deployment.form.aliyun_nlb_loadbalancer_id.placeholder": "Please enter NLB loadbalancer ID",
|
||||
"domain.deployment.form.aliyun_nlb_listener_id.label": "Listener ID",
|
||||
"domain.deployment.form.aliyun_nlb_listener_id.placeholder": "Please enter NLB listener ID",
|
||||
"domain.deployment.form.tencent_cos_region.label": "Region",
|
||||
"domain.deployment.form.tencent_cos_region.placeholder": "Please enter region (e.g. ap-guangzhou)",
|
||||
"domain.deployment.form.tencent_cos_bucket.label": "Bucket",
|
||||
@@ -73,6 +103,10 @@
|
||||
"domain.deployment.form.tencent_clb_listener.placeholder": "Please enter listener ID (e.g. lbl-xxxxxxxx). The specific listener should have set the corresponding domain HTTPS forwarding, and the original certificate domain should be consistent with the certificate to be deployed.",
|
||||
"domain.deployment.form.tencent_clb_domain.label": "Deploy to domain (Wildcard domain is also supported)",
|
||||
"domain.deployment.form.tencent_clb_domain.placeholder": "Please enter domain to be deployed. If SNI is not enabled, you can leave it blank.",
|
||||
"domain.deployment.form.tencent_teo_zone_id.label": "Zone ID",
|
||||
"domain.deployment.form.tencent_teo_zone_id.placeholder": "Please enter zone id, e.g. zone-xxxxxxxxx",
|
||||
"domain.deployment.form.tencent_teo_domain.label": "Deploy to domain (Wildcard domain is also supported, but should be same as the config on server, one domain each line)",
|
||||
"domain.deployment.form.tencent_teo_domain.placeholder": "Please enter domain to be deployed.",
|
||||
"domain.deployment.form.huaweicloud_elb_region.label": "Region",
|
||||
"domain.deployment.form.huaweicloud_elb_region.placeholder": "Please enter region (e.g. cn-north-1)",
|
||||
"domain.deployment.form.huaweicloud_elb_resource_type.label": "Resource Type",
|
||||
|
@@ -35,6 +35,7 @@
|
||||
"settings.notification.config.push.test.message.success.message": "Send test notification successfully",
|
||||
"settings.notification.dingtalk.secret.placeholder": "Signature for signed addition",
|
||||
"settings.notification.url.errmsg.invalid": "Invalid Url format",
|
||||
"settings.notification.serverchan.url.placeholder": "Url, e.g. https://sctapi.ftqq.com/****************.send",
|
||||
|
||||
"settings.ca.tab": "Certificate Authority",
|
||||
"settings.ca.provider.errmsg.empty": "Please select a Certificate Authority",
|
||||
|
@@ -69,7 +69,7 @@
|
||||
"access.authorization.form.ssh_key_passphrase.placeholder": "请输入 Key 口令",
|
||||
"access.authorization.form.webhook_url.label": "Webhook URL",
|
||||
"access.authorization.form.webhook_url.placeholder": "请输入 Webhook URL",
|
||||
"access.authorization.form.k8s_kubeconfig.label": "KubeConfig",
|
||||
"access.authorization.form.k8s_kubeconfig.label": "KubeConfig(不选将使用Pod的ServiceAccount)",
|
||||
"access.authorization.form.k8s_kubeconfig.placeholder": "请输入 KubeConfig",
|
||||
"access.authorization.form.k8s_kubeconfig_file.placeholder": "请选择文件",
|
||||
|
||||
|
@@ -51,19 +51,26 @@
|
||||
"common.errmsg.host_invalid": "请输入正确的域名或 IP 地址",
|
||||
"common.errmsg.ip_invalid": "请输入正确的 IP 地址",
|
||||
"common.errmsg.url_invalid": "请输入正确的 URL",
|
||||
"common.errmsg.zoneid_invalid": "请输入正确的 Zone ID",
|
||||
|
||||
"common.provider.aliyun": "阿里云",
|
||||
"common.provider.aliyun.oss": "阿里云 - OSS",
|
||||
"common.provider.aliyun.cdn": "阿里云 - CDN",
|
||||
"common.provider.aliyun.dcdn": "阿里云 - DCDN",
|
||||
"common.provider.aliyun.oss": "阿里云 - 对象存储 OSS",
|
||||
"common.provider.aliyun.cdn": "阿里云 - 内容分发网络 CDN",
|
||||
"common.provider.aliyun.dcdn": "阿里云 - 全站加速 DCDN",
|
||||
"common.provider.aliyun.clb": "阿里云 - 传统型负载均衡 CLB",
|
||||
"common.provider.aliyun.alb": "阿里云 - 应用型负载均衡 ALB",
|
||||
"common.provider.aliyun.nlb": "阿里云 - 网络型负载均衡 NLB",
|
||||
"common.provider.tencent": "腾讯云",
|
||||
"common.provider.tencent.cos": "腾讯云 - COS",
|
||||
"common.provider.tencent.cdn": "腾讯云 - CDN",
|
||||
"common.provider.tencent.clb": "腾讯云 - CLB",
|
||||
"common.provider.tencent.cos": "腾讯云 - 对象存储 COS",
|
||||
"common.provider.tencent.cdn": "腾讯云 - 内容分发网络 CDN",
|
||||
"common.provider.tencent.ecdn": "腾讯云 - 全站加速网络 ECDN",
|
||||
"common.provider.tencent.clb": "腾讯云 - 负载均衡 CLB",
|
||||
"common.provider.tencent.teo": "腾讯云 - 边缘安全加速平台 EO",
|
||||
"common.provider.huaweicloud": "华为云",
|
||||
"common.provider.huaweicloud.cdn": "华为云 - CDN",
|
||||
"common.provider.huaweicloud.elb": "华为云 - ELB",
|
||||
"common.provider.huaweicloud.cdn": "华为云 - 内容分发网络 CDN",
|
||||
"common.provider.huaweicloud.elb": "华为云 - 弹性负载均衡 ELB",
|
||||
"common.provider.qiniu": "七牛云",
|
||||
"common.provider.qiniu.cdn": "七牛云 - CDN",
|
||||
"common.provider.qiniu.cdn": "七牛云 - 内容分发网络 CDN",
|
||||
"common.provider.aws": "AWS",
|
||||
"common.provider.cloudflare": "Cloudflare",
|
||||
"common.provider.namesilo": "Namesilo",
|
||||
@@ -73,9 +80,11 @@
|
||||
"common.provider.local": "本地部署",
|
||||
"common.provider.ssh": "SSH 部署",
|
||||
"common.provider.webhook": "Webhook",
|
||||
"common.provider.serverchan": "Server酱",
|
||||
"common.provider.kubernetes": "Kubernetes",
|
||||
"common.provider.kubernetes.secret": "Kubernetes - Secret",
|
||||
"common.provider.dingtalk": "钉钉",
|
||||
"common.provider.telegram": "Telegram",
|
||||
"common.provider.lark": "飞书"
|
||||
}
|
||||
|
||||
|
@@ -61,6 +61,36 @@
|
||||
"domain.deployment.form.aliyun_oss_endpoint.placeholder": "请输入 Endpoint",
|
||||
"domain.deployment.form.aliyun_oss_bucket.label": "存储桶",
|
||||
"domain.deployment.form.aliyun_oss_bucket.placeholder": "请输入存储桶名",
|
||||
"domain.deployment.form.aliyun_clb_region.label": "地域",
|
||||
"domain.deployment.form.aliyun_clb_region.placeholder": "请输入地域(如 cn-hangzhou)",
|
||||
"domain.deployment.form.aliyun_clb_resource_type.label": "替换方式",
|
||||
"domain.deployment.form.aliyun_clb_resource_type.placeholder": "请选择替换方式",
|
||||
"domain.deployment.form.aliyun_clb_resource_type.option.loadbalancer.label": "替换指定负载均衡器的全部监听的证书(仅支持 HTTPS 监听)",
|
||||
"domain.deployment.form.aliyun_clb_resource_type.option.listener.label": "替换指定负载均衡监听的证书",
|
||||
"domain.deployment.form.aliyun_clb_loadbalancer_id.label": "负载均衡器 ID",
|
||||
"domain.deployment.form.aliyun_clb_loadbalancer_id.placeholder": "请输入负载均衡器 ID",
|
||||
"domain.deployment.form.aliyun_clb_listener_port.label": "监听端口",
|
||||
"domain.deployment.form.aliyun_clb_listener_port.placeholder": "请输入监听端口",
|
||||
"domain.deployment.form.aliyun_alb_region.label": "地域",
|
||||
"domain.deployment.form.aliyun_alb_region.placeholder": "请输入地域(如 cn-hangzhou)",
|
||||
"domain.deployment.form.aliyun_alb_resource_type.label": "替换方式",
|
||||
"domain.deployment.form.aliyun_alb_resource_type.placeholder": "请选择替换方式",
|
||||
"domain.deployment.form.aliyun_alb_resource_type.option.loadbalancer.label": "替换指定负载均衡器的全部监听的证书(仅支持 HTTPS/QUIC 监听)",
|
||||
"domain.deployment.form.aliyun_alb_resource_type.option.listener.label": "替换指定监听器的证书",
|
||||
"domain.deployment.form.aliyun_alb_loadbalancer_id.label": "负载均衡器 ID",
|
||||
"domain.deployment.form.aliyun_alb_loadbalancer_id.placeholder": "请输入负载均衡器 ID",
|
||||
"domain.deployment.form.aliyun_alb_listener_id.label": "监听器 ID",
|
||||
"domain.deployment.form.aliyun_alb_listener_id.placeholder": "请输入监听器 ID",
|
||||
"domain.deployment.form.aliyun_nlb_region.label": "地域",
|
||||
"domain.deployment.form.aliyun_nlb_region.placeholder": "请输入地域(如 cn-hangzhou)",
|
||||
"domain.deployment.form.aliyun_nlb_resource_type.label": "替换方式",
|
||||
"domain.deployment.form.aliyun_nlb_resource_type.placeholder": "请选择替换方式",
|
||||
"domain.deployment.form.aliyun_nlb_resource_type.option.loadbalancer.label": "替换指定负载均衡器的全部监听的证书(仅支持 TCPSSL 监听)",
|
||||
"domain.deployment.form.aliyun_nlb_resource_type.option.listener.label": "替换指定监听器的证书",
|
||||
"domain.deployment.form.aliyun_nlb_loadbalancer_id.label": "负载均衡器 ID",
|
||||
"domain.deployment.form.aliyun_nlb_loadbalancer_id.placeholder": "请输入负载均衡器 ID",
|
||||
"domain.deployment.form.aliyun_nlb_listener_id.label": "监听器 ID",
|
||||
"domain.deployment.form.aliyun_nlb_listener_id.placeholder": "请输入监听器 ID",
|
||||
"domain.deployment.form.tencent_cos_region.label": "地域",
|
||||
"domain.deployment.form.tencent_cos_region.placeholder": "请输入地域(如 ap-guangzhou)",
|
||||
"domain.deployment.form.tencent_cos_bucket.label": "存储桶",
|
||||
@@ -73,19 +103,23 @@
|
||||
"domain.deployment.form.tencent_clb_listener.placeholder": "请输入监听器 ID(如 lb-xxxxxxxx)",
|
||||
"domain.deployment.form.tencent_clb_domain.label": "部署到域名(支持泛域名)",
|
||||
"domain.deployment.form.tencent_clb_domain.placeholder": "请输入部署到的域名, 如未开启 SNI, 可置空忽略此项",
|
||||
"domain.deployment.form.tencent_teo_zone_id.label": "Zone ID",
|
||||
"domain.deployment.form.tencent_teo_zone_id.placeholder": "请输入 Zone ID",
|
||||
"domain.deployment.form.tencent_teo_domain.label": "部署到域名(支持泛域名, 应与服务器上配置的域名完全一致, 每行一个域名)",
|
||||
"domain.deployment.form.tencent_teo_domain.placeholder": "请输入部署到的域名",
|
||||
"domain.deployment.form.huaweicloud_elb_region.label": "地域",
|
||||
"domain.deployment.form.huaweicloud_elb_region.placeholder": "请输入地域(如 cn-north-1)",
|
||||
"domain.deployment.form.huaweicloud_elb_resource_type.label": "资源类型替换方式",
|
||||
"domain.deployment.form.huaweicloud_elb_resource_type.placeholder": "请选择资源类型替换方式",
|
||||
"domain.deployment.form.huaweicloud_elb_resource_type.option.certificate.label": "按证书替换",
|
||||
"domain.deployment.form.huaweicloud_elb_resource_type.option.loadbalancer.label": "按负载均衡器替换",
|
||||
"domain.deployment.form.huaweicloud_elb_resource_type.option.listener.label": "按监听器替换",
|
||||
"domain.deployment.form.huaweicloud_elb_resource_type.label": "替换方式",
|
||||
"domain.deployment.form.huaweicloud_elb_resource_type.placeholder": "请选择替换方式",
|
||||
"domain.deployment.form.huaweicloud_elb_resource_type.option.certificate.label": "替换指定证书",
|
||||
"domain.deployment.form.huaweicloud_elb_resource_type.option.loadbalancer.label": "替换指定负载均衡器的全部监听器的证书(仅支持 HTTPS 监听)",
|
||||
"domain.deployment.form.huaweicloud_elb_resource_type.option.listener.label": "替换指定监听器",
|
||||
"domain.deployment.form.huaweicloud_elb_certificate_id.label": "证书 ID",
|
||||
"domain.deployment.form.huaweicloud_elb_certificate_id.placeholder": "请输入证书 ID(可从华为云控制面板获取)",
|
||||
"domain.deployment.form.huaweicloud_elb_certificate_id.placeholder": "请输入证书 ID",
|
||||
"domain.deployment.form.huaweicloud_elb_loadbalancer_id.label": "负载均衡器 ID",
|
||||
"domain.deployment.form.huaweicloud_elb_loadbalancer_id.placeholder": "请输入负载均衡器 ID(可从华为云控制面板获取)",
|
||||
"domain.deployment.form.huaweicloud_elb_loadbalancer_id.placeholder": "请输入负载均衡器 ID",
|
||||
"domain.deployment.form.huaweicloud_elb_listener_id.label": "监听器 ID",
|
||||
"domain.deployment.form.huaweicloud_elb_listener_id.placeholder": "请输入监听器 ID(可从华为云控制面板获取)",
|
||||
"domain.deployment.form.huaweicloud_elb_listener_id.placeholder": "请输入监听器 ID",
|
||||
"domain.deployment.form.file_format.label": "证书格式",
|
||||
"domain.deployment.form.file_format.placeholder": "请选择证书格式",
|
||||
"domain.deployment.form.file_cert_path.label": "证书保存路径",
|
||||
|
@@ -35,6 +35,7 @@
|
||||
"settings.notification.config.push.test.message.success.message": "推送测试消息成功",
|
||||
"settings.notification.dingtalk.secret.placeholder": "加签的签名",
|
||||
"settings.notification.url.errmsg.invalid": "URL 格式不正确",
|
||||
"settings.notification.serverchan.url.placeholder": "Url, 形如: https://sctapi.ftqq.com/****************.send",
|
||||
|
||||
"settings.ca.tab": "证书颁发机构(CA)",
|
||||
"settings.ca.provider.errmsg.empty": "请选择证书分发机构",
|
||||
|
@@ -6,6 +6,7 @@ import Lark from "@/components/notify/Lark";
|
||||
import NotifyTemplate from "@/components/notify/NotifyTemplate";
|
||||
import Telegram from "@/components/notify/Telegram";
|
||||
import Webhook from "@/components/notify/Webhook";
|
||||
import ServerChan from "@/components/notify/ServerChan";
|
||||
import { NotifyProvider } from "@/providers/notify";
|
||||
|
||||
const Notify = () => {
|
||||
@@ -53,6 +54,13 @@ const Notify = () => {
|
||||
<Webhook />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
|
||||
<AccordionItem value="item-6" className="dark:border-stone-200">
|
||||
<AccordionTrigger>{t("common.provider.serverchan")}</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<ServerChan />
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</div>
|
||||
</NotifyProvider>
|
||||
|
Reference in New Issue
Block a user