mirror of
https://github.com/woodchen-ink/certimate.git
synced 2025-07-19 09:51:55 +08:00
refactor: divide DeployList
This commit is contained in:
parent
e53749e16e
commit
062d66222a
@ -36,10 +36,10 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
|
|
||||||
const [configType, setConfigType] = useState(data?.configType || "");
|
const [configType, setConfigType] = useState(data?.configType || "");
|
||||||
|
|
||||||
let form = <> </>;
|
let childComponent = <> </>;
|
||||||
switch (configType) {
|
switch (configType) {
|
||||||
case "aliyun":
|
case "aliyun":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessAliyunForm
|
<AccessAliyunForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -50,7 +50,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "tencent":
|
case "tencent":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessTencentForm
|
<AccessTencentForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -61,7 +61,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "huaweicloud":
|
case "huaweicloud":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessHuaweiCloudForm
|
<AccessHuaweiCloudForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -72,7 +72,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "qiniu":
|
case "qiniu":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessQiniuForm
|
<AccessQiniuForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -83,7 +83,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "aws":
|
case "aws":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessAwsForm
|
<AccessAwsForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -94,7 +94,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "cloudflare":
|
case "cloudflare":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessCloudflareForm
|
<AccessCloudflareForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -105,7 +105,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "namesilo":
|
case "namesilo":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessNamesiloForm
|
<AccessNamesiloForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -116,7 +116,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "godaddy":
|
case "godaddy":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessGodaddyForm
|
<AccessGodaddyForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -127,7 +127,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "pdns":
|
case "pdns":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessPdnsForm
|
<AccessPdnsForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -138,7 +138,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "httpreq":
|
case "httpreq":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessHttpreqForm
|
<AccessHttpreqForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -149,7 +149,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "local":
|
case "local":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessLocalForm
|
<AccessLocalForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -160,7 +160,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "ssh":
|
case "ssh":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessSSHForm
|
<AccessSSHForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -171,7 +171,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "webhook":
|
case "webhook":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessWebhookForm
|
<AccessWebhookForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -182,7 +182,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case "k8s":
|
case "k8s":
|
||||||
form = (
|
childComponent = (
|
||||||
<AccessKubernetesForm
|
<AccessKubernetesForm
|
||||||
data={data}
|
data={data}
|
||||||
op={op}
|
op={op}
|
||||||
@ -244,7 +244,7 @@ const AccessEditDialog = ({ trigger, op, data, className }: AccessEditProps) =>
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-8">{form}</div>
|
<div className="mt-8">{childComponent}</div>
|
||||||
</div>
|
</div>
|
||||||
</ScrollArea>
|
</ScrollArea>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
16
ui/src/components/certimate/DeployEdit.tsx
Normal file
16
ui/src/components/certimate/DeployEdit.tsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { createContext, useContext } from "react";
|
||||||
|
|
||||||
|
import { DeployConfig } from "@/domain/domain";
|
||||||
|
|
||||||
|
type DeployEditContext = {
|
||||||
|
deploy: DeployConfig;
|
||||||
|
error: Record<string, string>;
|
||||||
|
setDeploy: (deploy: DeployConfig) => void;
|
||||||
|
setError: (error: Record<string, string>) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Context = createContext<DeployEditContext>({} as DeployEditContext);
|
||||||
|
|
||||||
|
export const useDeployEditContext = () => {
|
||||||
|
return useContext(Context);
|
||||||
|
};
|
252
ui/src/components/certimate/DeployEditDialog.tsx
Normal file
252
ui/src/components/certimate/DeployEditDialog.tsx
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Plus } from "lucide-react";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||||
|
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
|
import AccessEditDialog from "./AccessEditDialog";
|
||||||
|
import { Context as DeployEditContext } from "./DeployEdit";
|
||||||
|
import DeployToAliyunOSS from "./DeployToAliyunOSS";
|
||||||
|
import DeployToAliyunCDN from "./DeployToAliyunCDN";
|
||||||
|
import DeployToTencentCDN from "./DeployToTencentCDN";
|
||||||
|
import DeployToHuaweiCloudCDN from "./DeployToHuaweiCloudCDN";
|
||||||
|
import DeployToQiniuCDN from "./DeployToQiniuCDN";
|
||||||
|
import DeployToSSH from "./DeployToSSH";
|
||||||
|
import DeployToWebhook from "./DeployToWebhook";
|
||||||
|
import DeployToKubernetesSecret from "./DeployToKubernetesSecret";
|
||||||
|
import { deployTargetsMap, type DeployConfig } from "@/domain/domain";
|
||||||
|
import { accessProvidersMap } from "@/domain/access";
|
||||||
|
import { useConfigContext } from "@/providers/config";
|
||||||
|
|
||||||
|
type DeployEditDialogProps = {
|
||||||
|
trigger: React.ReactNode;
|
||||||
|
deployConfig?: DeployConfig;
|
||||||
|
onSave: (deploy: DeployConfig) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeployEditDialog = ({ trigger, deployConfig, onSave }: DeployEditDialogProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const {
|
||||||
|
config: { accesses },
|
||||||
|
} = useConfigContext();
|
||||||
|
|
||||||
|
const [deployType, setDeployType] = useState("");
|
||||||
|
|
||||||
|
const [locDeployConfig, setLocDeployConfig] = useState<DeployConfig>({
|
||||||
|
access: "",
|
||||||
|
type: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const [error, setError] = useState<Record<string, string>>({});
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (deployConfig) {
|
||||||
|
setLocDeployConfig({ ...deployConfig });
|
||||||
|
} else {
|
||||||
|
setLocDeployConfig({
|
||||||
|
access: "",
|
||||||
|
type: "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [deployConfig]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setDeployType(locDeployConfig.type);
|
||||||
|
setError({});
|
||||||
|
}, [locDeployConfig.type]);
|
||||||
|
|
||||||
|
const setDeploy = useCallback(
|
||||||
|
(deploy: DeployConfig) => {
|
||||||
|
if (deploy.type !== locDeployConfig.type) {
|
||||||
|
setLocDeployConfig({ ...deploy, access: "", config: {} });
|
||||||
|
} else {
|
||||||
|
setLocDeployConfig({ ...deploy });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[locDeployConfig.type]
|
||||||
|
);
|
||||||
|
|
||||||
|
const targetAccesses = accesses.filter((item) => {
|
||||||
|
if (item.usage == "apply") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (locDeployConfig.type == "") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return item.configType === locDeployConfig.type.split("-")[0];
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSaveClick = () => {
|
||||||
|
// 验证数据
|
||||||
|
const newError = { ...error };
|
||||||
|
newError.type = locDeployConfig.type === "" ? t("domain.deployment.form.access.placeholder") : "";
|
||||||
|
newError.access = locDeployConfig.access === "" ? t("domain.deployment.form.access.placeholder") : "";
|
||||||
|
setError(newError);
|
||||||
|
if (Object.values(newError).some((e) => !!e)) return;
|
||||||
|
|
||||||
|
// 保存数据
|
||||||
|
onSave(locDeployConfig);
|
||||||
|
|
||||||
|
// 清理数据
|
||||||
|
setLocDeployConfig({
|
||||||
|
access: "",
|
||||||
|
type: "",
|
||||||
|
});
|
||||||
|
setError({});
|
||||||
|
|
||||||
|
// 关闭弹框
|
||||||
|
setOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
let childComponent = <></>;
|
||||||
|
switch (deployType) {
|
||||||
|
case "aliyun-oss":
|
||||||
|
childComponent = <DeployToAliyunOSS />;
|
||||||
|
break;
|
||||||
|
case "aliyun-cdn":
|
||||||
|
case "aliyun-dcdn":
|
||||||
|
childComponent = <DeployToAliyunCDN />;
|
||||||
|
break;
|
||||||
|
case "tencent-cdn":
|
||||||
|
childComponent = <DeployToTencentCDN />;
|
||||||
|
break;
|
||||||
|
case "huaweicloud-cdn":
|
||||||
|
childComponent = <DeployToHuaweiCloudCDN />;
|
||||||
|
break;
|
||||||
|
case "qiniu-cdn":
|
||||||
|
childComponent = <DeployToQiniuCDN />;
|
||||||
|
break;
|
||||||
|
case "ssh":
|
||||||
|
case "local":
|
||||||
|
childComponent = <DeployToSSH />;
|
||||||
|
break;
|
||||||
|
case "webhook":
|
||||||
|
childComponent = <DeployToWebhook />;
|
||||||
|
break;
|
||||||
|
case "k8s-secret":
|
||||||
|
childComponent = <DeployToKubernetesSecret />;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DeployEditContext.Provider
|
||||||
|
value={{
|
||||||
|
deploy: locDeployConfig,
|
||||||
|
error: error,
|
||||||
|
setDeploy: setDeploy,
|
||||||
|
setError: setError,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
|
<DialogTrigger>{trigger}</DialogTrigger>
|
||||||
|
<DialogContent className="dark:text-stone-200">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>{t("domain.deployment.tab")}</DialogTitle>
|
||||||
|
<DialogDescription></DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
<ScrollArea className="max-h-[80vh]">
|
||||||
|
<div className="container py-3">
|
||||||
|
{/* 部署方式 */}
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.type.label")}</Label>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
value={locDeployConfig.type}
|
||||||
|
onValueChange={(val: string) => {
|
||||||
|
setDeploy({ ...locDeployConfig, type: val });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="mt-2">
|
||||||
|
<SelectValue placeholder={t("domain.deployment.form.type.placeholder")} />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>{t("domain.deployment.form.type.list")}</SelectLabel>
|
||||||
|
{Array.from(deployTargetsMap.entries()).map(([key, target]) => (
|
||||||
|
<SelectItem key={key} value={key}>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<img className="w-6" src={target.icon} />
|
||||||
|
<div>{t(target.name)}</div>
|
||||||
|
</div>
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
<div className="text-red-500 text-sm mt-1">{error.type}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 授权配置 */}
|
||||||
|
<div className="mt-8">
|
||||||
|
<Label className="flex justify-between">
|
||||||
|
<div>{t("domain.deployment.form.access.label")}</div>
|
||||||
|
<AccessEditDialog
|
||||||
|
trigger={
|
||||||
|
<div className="font-normal text-primary hover:underline cursor-pointer flex items-center">
|
||||||
|
<Plus size={14} />
|
||||||
|
{t("common.add")}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
op="add"
|
||||||
|
/>
|
||||||
|
</Label>
|
||||||
|
|
||||||
|
<Select
|
||||||
|
value={locDeployConfig.access}
|
||||||
|
onValueChange={(val: string) => {
|
||||||
|
setDeploy({ ...locDeployConfig, access: val });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SelectTrigger className="mt-2">
|
||||||
|
<SelectValue placeholder={t("domain.deployment.form.access.placeholder")} />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectGroup>
|
||||||
|
<SelectLabel>{t("domain.deployment.form.access.list")}</SelectLabel>
|
||||||
|
{targetAccesses.map((item) => (
|
||||||
|
<SelectItem key={item.id} value={item.id}>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<img className="w-6" src={accessProvidersMap.get(item.configType)?.icon} />
|
||||||
|
<div>{item.name}</div>
|
||||||
|
</div>
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
|
||||||
|
<div className="text-red-500 text-sm mt-1">{error.access}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 其他参数 */}
|
||||||
|
<div className="mt-8">{childComponent}</div>
|
||||||
|
</div>
|
||||||
|
</ScrollArea>
|
||||||
|
|
||||||
|
<DialogFooter>
|
||||||
|
<Button
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleSaveClick();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("common.save")}
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</DeployEditContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeployEditDialog;
|
@ -1,37 +1,16 @@
|
|||||||
import { createContext, useCallback, useContext, useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { z } from "zod";
|
|
||||||
import { produce } from "immer";
|
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { EditIcon, Plus, Trash2 } from "lucide-react";
|
import { EditIcon, Trash2 } from "lucide-react";
|
||||||
|
|
||||||
import Show from "@/components/Show";
|
import Show from "@/components/Show";
|
||||||
import { Alert, AlertDescription } from "@/components/ui/alert";
|
import { Alert, AlertDescription } from "@/components/ui/alert";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
import DeployEditDialog from "./DeployEditDialog";
|
||||||
import { Input } from "@/components/ui/input";
|
import { DeployConfig } from "@/domain/domain";
|
||||||
import { Label } from "@/components/ui/label";
|
|
||||||
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
|
||||||
import AccessEditDialog from "./AccessEditDialog";
|
|
||||||
import KVList from "./KVList";
|
|
||||||
import { DeployConfig, KVType, targetTypeKeys, targetTypeMap } from "@/domain/domain";
|
|
||||||
import { accessProvidersMap } from "@/domain/access";
|
import { accessProvidersMap } from "@/domain/access";
|
||||||
import { useConfigContext } from "@/providers/config";
|
import { useConfigContext } from "@/providers/config";
|
||||||
|
|
||||||
type DeployEditContextProps = {
|
|
||||||
deploy: DeployConfig;
|
|
||||||
error: Record<string, string>;
|
|
||||||
setDeploy: (deploy: DeployConfig) => void;
|
|
||||||
setError: (error: Record<string, string>) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const DeployEditContext = createContext<DeployEditContextProps>({} as DeployEditContextProps);
|
|
||||||
|
|
||||||
export const useDeployEditContext = () => {
|
|
||||||
return useContext(DeployEditContext);
|
|
||||||
};
|
|
||||||
|
|
||||||
type DeployItemProps = {
|
type DeployItemProps = {
|
||||||
item: DeployConfig;
|
item: DeployConfig;
|
||||||
onDelete: () => void;
|
onDelete: () => void;
|
||||||
@ -190,693 +169,3 @@ const DeployList = ({ deploys, onChange }: DeployListProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default DeployList;
|
export default DeployList;
|
||||||
|
|
||||||
type DeployEditDialogProps = {
|
|
||||||
trigger: React.ReactNode;
|
|
||||||
deployConfig?: DeployConfig;
|
|
||||||
onSave: (deploy: DeployConfig) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const DeployEditDialog = ({ trigger, deployConfig, onSave }: DeployEditDialogProps) => {
|
|
||||||
const {
|
|
||||||
config: { accesses },
|
|
||||||
} = useConfigContext();
|
|
||||||
|
|
||||||
const [deployType, setDeployType] = useState<TargetType>();
|
|
||||||
|
|
||||||
const [locDeployConfig, setLocDeployConfig] = useState<DeployConfig>({
|
|
||||||
access: "",
|
|
||||||
type: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
const [error, setError] = useState<Record<string, string>>({});
|
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (deployConfig) {
|
|
||||||
setLocDeployConfig({ ...deployConfig });
|
|
||||||
} else {
|
|
||||||
setLocDeployConfig({
|
|
||||||
access: "",
|
|
||||||
type: "",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [deployConfig]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const temp = locDeployConfig.type.split("-");
|
|
||||||
|
|
||||||
let t;
|
|
||||||
if (temp && temp.length > 1) {
|
|
||||||
// TODO: code smell, maybe a dictionary is better
|
|
||||||
t = temp[0] === "k8s" ? temp[0] : temp[1];
|
|
||||||
} else {
|
|
||||||
t = locDeployConfig.type;
|
|
||||||
}
|
|
||||||
|
|
||||||
setDeployType(t as TargetType);
|
|
||||||
setError({});
|
|
||||||
}, [locDeployConfig.type]);
|
|
||||||
|
|
||||||
const setDeploy = useCallback(
|
|
||||||
(deploy: DeployConfig) => {
|
|
||||||
if (deploy.type !== locDeployConfig.type) {
|
|
||||||
setLocDeployConfig({ ...deploy, access: "", config: {} });
|
|
||||||
} else {
|
|
||||||
setLocDeployConfig({ ...deploy });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[locDeployConfig.type]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const targetAccesses = accesses.filter((item) => {
|
|
||||||
if (item.usage == "apply") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (locDeployConfig.type == "") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const types = locDeployConfig.type.split("-");
|
|
||||||
return item.configType === types[0];
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleSaveClick = () => {
|
|
||||||
// 验证数据
|
|
||||||
// 保存数据
|
|
||||||
// 清理数据
|
|
||||||
// 关闭弹框
|
|
||||||
const newError = { ...error };
|
|
||||||
if (locDeployConfig.type === "") {
|
|
||||||
newError.type = t("domain.deployment.form.access.placeholder");
|
|
||||||
} else {
|
|
||||||
newError.type = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (locDeployConfig.access === "") {
|
|
||||||
newError.access = t("domain.deployment.form.access.placeholder");
|
|
||||||
} else {
|
|
||||||
newError.access = "";
|
|
||||||
}
|
|
||||||
setError(newError);
|
|
||||||
|
|
||||||
for (const key in newError) {
|
|
||||||
if (newError[key] !== "") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onSave(locDeployConfig);
|
|
||||||
|
|
||||||
setLocDeployConfig({
|
|
||||||
access: "",
|
|
||||||
type: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
setError({});
|
|
||||||
|
|
||||||
setOpen(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DeployEditContext.Provider
|
|
||||||
value={{
|
|
||||||
deploy: locDeployConfig,
|
|
||||||
error: error,
|
|
||||||
setDeploy: setDeploy,
|
|
||||||
setError: setError,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Dialog open={open} onOpenChange={setOpen}>
|
|
||||||
<DialogTrigger>{trigger}</DialogTrigger>
|
|
||||||
<DialogContent className="dark:text-stone-200">
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle>{t("domain.deployment.tab")}</DialogTitle>
|
|
||||||
<DialogDescription></DialogDescription>
|
|
||||||
</DialogHeader>
|
|
||||||
|
|
||||||
{/* 部署方式 */}
|
|
||||||
<div>
|
|
||||||
<Label>{t("domain.deployment.form.type.label")}</Label>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
value={locDeployConfig.type}
|
|
||||||
onValueChange={(val: string) => {
|
|
||||||
setDeploy({ ...locDeployConfig, type: val });
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="mt-2">
|
|
||||||
<SelectValue placeholder={t("domain.deployment.form.type.placeholder")} />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectGroup>
|
|
||||||
<SelectLabel>{t("domain.deployment.form.type.list")}</SelectLabel>
|
|
||||||
{targetTypeKeys.map((item) => (
|
|
||||||
<SelectItem key={item} value={item}>
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<img className="w-6" src={targetTypeMap.get(item)?.[1]} />
|
|
||||||
<div>{t(targetTypeMap.get(item)?.[0] ?? "")}</div>
|
|
||||||
</div>
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectGroup>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
<div className="text-red-500 text-sm mt-1">{error.type}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 授权配置 */}
|
|
||||||
<div>
|
|
||||||
<Label className="flex justify-between">
|
|
||||||
<div>{t("domain.deployment.form.access.label")}</div>
|
|
||||||
<AccessEditDialog
|
|
||||||
trigger={
|
|
||||||
<div className="font-normal text-primary hover:underline cursor-pointer flex items-center">
|
|
||||||
<Plus size={14} />
|
|
||||||
{t("common.add")}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
op="add"
|
|
||||||
/>
|
|
||||||
</Label>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
value={locDeployConfig.access}
|
|
||||||
onValueChange={(val: string) => {
|
|
||||||
setDeploy({ ...locDeployConfig, access: val });
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="mt-2">
|
|
||||||
<SelectValue placeholder={t("domain.deployment.form.access.placeholder")} />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectGroup>
|
|
||||||
<SelectLabel>{t("domain.deployment.form.access.list")}</SelectLabel>
|
|
||||||
{targetAccesses.map((item) => (
|
|
||||||
<SelectItem key={item.id} value={item.id}>
|
|
||||||
<div className="flex items-center space-x-2">
|
|
||||||
<img className="w-6" src={accessProvidersMap.get(item.configType)?.icon} />
|
|
||||||
<div>{item.name}</div>
|
|
||||||
</div>
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectGroup>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
<div className="text-red-500 text-sm mt-1">{error.access}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 其他参数 */}
|
|
||||||
<DeployEdit type={deployType!} />
|
|
||||||
|
|
||||||
<DialogFooter>
|
|
||||||
<Button
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
handleSaveClick();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("common.save")}
|
|
||||||
</Button>
|
|
||||||
</DialogFooter>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
</DeployEditContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
type TargetType = "oss" | "cdn" | "dcdn" | "local" | "ssh" | "webhook" | "k8s";
|
|
||||||
|
|
||||||
type DeployEditProps = {
|
|
||||||
type: TargetType;
|
|
||||||
};
|
|
||||||
|
|
||||||
const DeployEdit = ({ type }: DeployEditProps) => {
|
|
||||||
const getDeploy = () => {
|
|
||||||
switch (type) {
|
|
||||||
case "cdn":
|
|
||||||
return <DeployToCDN />;
|
|
||||||
case "dcdn":
|
|
||||||
return <DeployToCDN />;
|
|
||||||
case "oss":
|
|
||||||
return <DeployToOSS />;
|
|
||||||
case "ssh":
|
|
||||||
return <DeployToSSH />;
|
|
||||||
case "local":
|
|
||||||
return <DeployToSSH />;
|
|
||||||
case "webhook":
|
|
||||||
return <DeployToWebhook />;
|
|
||||||
case "k8s":
|
|
||||||
return <DeployToKubernetes />;
|
|
||||||
default:
|
|
||||||
return <DeployToCDN />;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return getDeploy();
|
|
||||||
};
|
|
||||||
|
|
||||||
const DeployToSSH = () => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const { setError } = useDeployEditContext();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setError({});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const { deploy: data, setDeploy } = useDeployEditContext();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!data.id) {
|
|
||||||
setDeploy({
|
|
||||||
...data,
|
|
||||||
config: {
|
|
||||||
certPath: "/etc/nginx/ssl/nginx.crt",
|
|
||||||
keyPath: "/etc/nginx/ssl/nginx.key",
|
|
||||||
preCommand: "",
|
|
||||||
command: "sudo service nginx reload",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="flex flex-col space-y-8">
|
|
||||||
<div>
|
|
||||||
<Label>{t("domain.deployment.form.ssh_cert_path.label")}</Label>
|
|
||||||
<Input
|
|
||||||
placeholder={t("domain.deployment.form.ssh_cert_path.label")}
|
|
||||||
className="w-full mt-1"
|
|
||||||
value={data?.config?.certPath}
|
|
||||||
onChange={(e) => {
|
|
||||||
const newData = produce(data, (draft) => {
|
|
||||||
if (!draft.config) {
|
|
||||||
draft.config = {};
|
|
||||||
}
|
|
||||||
draft.config.certPath = e.target.value;
|
|
||||||
});
|
|
||||||
setDeploy(newData);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Label>{t("domain.deployment.form.ssh_key_path.label")}</Label>
|
|
||||||
<Input
|
|
||||||
placeholder={t("domain.deployment.form.ssh_key_path.placeholder")}
|
|
||||||
className="w-full mt-1"
|
|
||||||
value={data?.config?.keyPath}
|
|
||||||
onChange={(e) => {
|
|
||||||
const newData = produce(data, (draft) => {
|
|
||||||
if (!draft.config) {
|
|
||||||
draft.config = {};
|
|
||||||
}
|
|
||||||
draft.config.keyPath = e.target.value;
|
|
||||||
});
|
|
||||||
setDeploy(newData);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<Label>{t("domain.deployment.form.ssh_pre_command.label")}</Label>
|
|
||||||
<Textarea
|
|
||||||
className="mt-1"
|
|
||||||
value={data?.config?.preCommand}
|
|
||||||
placeholder={t("domain.deployment.form.ssh_pre_command.placeholder")}
|
|
||||||
onChange={(e) => {
|
|
||||||
const newData = produce(data, (draft) => {
|
|
||||||
if (!draft.config) {
|
|
||||||
draft.config = {};
|
|
||||||
}
|
|
||||||
draft.config.preCommand = e.target.value;
|
|
||||||
});
|
|
||||||
setDeploy(newData);
|
|
||||||
}}
|
|
||||||
></Textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<Label>{t("domain.deployment.form.ssh_command.label")}</Label>
|
|
||||||
<Textarea
|
|
||||||
className="mt-1"
|
|
||||||
value={data?.config?.command}
|
|
||||||
placeholder={t("domain.deployment.form.ssh_command.placeholder")}
|
|
||||||
onChange={(e) => {
|
|
||||||
const newData = produce(data, (draft) => {
|
|
||||||
if (!draft.config) {
|
|
||||||
draft.config = {};
|
|
||||||
}
|
|
||||||
draft.config.command = e.target.value;
|
|
||||||
});
|
|
||||||
setDeploy(newData);
|
|
||||||
}}
|
|
||||||
></Textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const DeployToWebhook = () => {
|
|
||||||
const { deploy: data, setDeploy } = useDeployEditContext();
|
|
||||||
|
|
||||||
const { setError } = useDeployEditContext();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setError({});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<KVList
|
|
||||||
variables={data?.config?.variables}
|
|
||||||
onValueChange={(variables: KVType[]) => {
|
|
||||||
const newData = produce(data, (draft) => {
|
|
||||||
if (!draft.config) {
|
|
||||||
draft.config = {};
|
|
||||||
}
|
|
||||||
draft.config.variables = variables;
|
|
||||||
});
|
|
||||||
setDeploy(newData);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const DeployToOSS = () => {
|
|
||||||
const { deploy: data, setDeploy, error, setError } = useDeployEditContext();
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
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 bucketResp = bucketSchema.safeParse(data.config?.domain);
|
|
||||||
if (!bucketResp.success) {
|
|
||||||
setError({
|
|
||||||
...error,
|
|
||||||
bucket: JSON.parse(bucketResp.error.message)[0].message,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setError({
|
|
||||||
...error,
|
|
||||||
bucket: "",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!data.id) {
|
|
||||||
setDeploy({
|
|
||||||
...data,
|
|
||||||
config: {
|
|
||||||
endpoint: "oss-cn-hangzhou.aliyuncs.com",
|
|
||||||
bucket: "",
|
|
||||||
domain: "",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const domainSchema = z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
|
||||||
message: t("common.errmsg.domain_invalid"),
|
|
||||||
});
|
|
||||||
|
|
||||||
const bucketSchema = z.string().min(1, {
|
|
||||||
message: t("domain.deployment.form.oss_bucket.placeholder"),
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col space-y-8">
|
|
||||||
<div>
|
|
||||||
<Label>{t("domain.deployment.form.oss_endpoint.label")}</Label>
|
|
||||||
|
|
||||||
<Input
|
|
||||||
placeholder={t("domain.deployment.form.oss_endpoint.placeholder")}
|
|
||||||
className="w-full mt-1"
|
|
||||||
value={data?.config?.endpoint}
|
|
||||||
onChange={(e) => {
|
|
||||||
const temp = e.target.value;
|
|
||||||
|
|
||||||
const newData = produce(data, (draft) => {
|
|
||||||
if (!draft.config) {
|
|
||||||
draft.config = {};
|
|
||||||
}
|
|
||||||
draft.config.endpoint = temp;
|
|
||||||
});
|
|
||||||
setDeploy(newData);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div className="text-red-600 text-sm mt-1">{error?.endpoint}</div>
|
|
||||||
|
|
||||||
<Label>{t("domain.deployment.form.oss_bucket.label")}</Label>
|
|
||||||
<Input
|
|
||||||
placeholder={t("domain.deployment.form.oss_bucket.placeholder")}
|
|
||||||
className="w-full mt-1"
|
|
||||||
value={data?.config?.bucket}
|
|
||||||
onChange={(e) => {
|
|
||||||
const temp = e.target.value;
|
|
||||||
|
|
||||||
const resp = bucketSchema.safeParse(temp);
|
|
||||||
if (!resp.success) {
|
|
||||||
setError({
|
|
||||||
...error,
|
|
||||||
bucket: JSON.parse(resp.error.message)[0].message,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setError({
|
|
||||||
...error,
|
|
||||||
bucket: "",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const newData = produce(data, (draft) => {
|
|
||||||
if (!draft.config) {
|
|
||||||
draft.config = {};
|
|
||||||
}
|
|
||||||
draft.config.bucket = temp;
|
|
||||||
});
|
|
||||||
setDeploy(newData);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div className="text-red-600 text-sm mt-1">{error?.bucket}</div>
|
|
||||||
|
|
||||||
<Label>{t("domain.deployment.form.domain.label")}</Label>
|
|
||||||
<Input
|
|
||||||
placeholder={t("domain.deployment.form.domain.label")}
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const DeployToCDN = () => {
|
|
||||||
const { deploy: data, setDeploy, error, setError } = useDeployEditContext();
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
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]);
|
|
||||||
|
|
||||||
const domainSchema = z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
|
||||||
message: t("common.errmsg.domain_invalid"),
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex flex-col space-y-8">
|
|
||||||
<div>
|
|
||||||
<Label>{t("domain.deployment.form.domain.label")}</Label>
|
|
||||||
<Input
|
|
||||||
placeholder={t("domain.deployment.form.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>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const DeployToKubernetes = () => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const { setError } = useDeployEditContext();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setError({});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const { deploy: data, setDeploy } = useDeployEditContext();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!data.id) {
|
|
||||||
setDeploy({
|
|
||||||
...data,
|
|
||||||
config: {
|
|
||||||
namespace: "default",
|
|
||||||
secretName: "",
|
|
||||||
secretDataKeyForCrt: "tls.crt",
|
|
||||||
secretDataKeyForKey: "tls.key",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className="flex flex-col space-y-8">
|
|
||||||
<div>
|
|
||||||
<Label>{t("domain.deployment.form.k8s_namespace.label")}</Label>
|
|
||||||
<Input
|
|
||||||
placeholder={t("domain.deployment.form.k8s_namespace.label")}
|
|
||||||
className="w-full mt-1"
|
|
||||||
value={data?.config?.namespace}
|
|
||||||
onChange={(e) => {
|
|
||||||
const newData = produce(data, (draft) => {
|
|
||||||
draft.config ??= {};
|
|
||||||
draft.config.namespace = e.target.value;
|
|
||||||
});
|
|
||||||
setDeploy(newData);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<Label>{t("domain.deployment.form.k8s_secret_name.label")}</Label>
|
|
||||||
<Input
|
|
||||||
placeholder={t("domain.deployment.form.k8s_secret_name.label")}
|
|
||||||
className="w-full mt-1"
|
|
||||||
value={data?.config?.secretName}
|
|
||||||
onChange={(e) => {
|
|
||||||
const newData = produce(data, (draft) => {
|
|
||||||
draft.config ??= {};
|
|
||||||
draft.config.secretName = e.target.value;
|
|
||||||
});
|
|
||||||
setDeploy(newData);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<Label>{t("domain.deployment.form.k8s_secret_data_key_for_crt.label")}</Label>
|
|
||||||
<Input
|
|
||||||
placeholder={t("domain.deployment.form.k8s_secret_data_key_for_crt.label")}
|
|
||||||
className="w-full mt-1"
|
|
||||||
value={data?.config?.secretDataKeyForCrt}
|
|
||||||
onChange={(e) => {
|
|
||||||
const newData = produce(data, (draft) => {
|
|
||||||
draft.config ??= {};
|
|
||||||
draft.config.secretDataKeyForCrt = e.target.value;
|
|
||||||
});
|
|
||||||
setDeploy(newData);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<Label>{t("domain.deployment.form.k8s_secret_data_key_for_key.label")}</Label>
|
|
||||||
<Input
|
|
||||||
placeholder={t("domain.deployment.form.k8s_secret_data_key_for_key.label")}
|
|
||||||
className="w-full mt-1"
|
|
||||||
value={data?.config?.secretDataKeyForKey}
|
|
||||||
onChange={(e) => {
|
|
||||||
const newData = produce(data, (draft) => {
|
|
||||||
draft.config ??= {};
|
|
||||||
draft.config.secretDataKeyForKey = e.target.value;
|
|
||||||
});
|
|
||||||
setDeploy(newData);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
77
ui/src/components/certimate/DeployToAliyunCDN.tsx
Normal file
77
ui/src/components/certimate/DeployToAliyunCDN.tsx
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
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 { useDeployEditContext } from "./DeployEdit";
|
||||||
|
|
||||||
|
const DeployToAliyunCDN = () => {
|
||||||
|
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]);
|
||||||
|
|
||||||
|
const domainSchema = z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||||
|
message: t("common.errmsg.domain_invalid"),
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col space-y-8">
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.domain.label")}</Label>
|
||||||
|
<Input
|
||||||
|
placeholder={t("domain.deployment.form.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 DeployToAliyunCDN;
|
164
ui/src/components/certimate/DeployToAliyunOSS.tsx
Normal file
164
ui/src/components/certimate/DeployToAliyunOSS.tsx
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
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 { useDeployEditContext } from "./DeployEdit";
|
||||||
|
|
||||||
|
const DeployToAliyunOSS = () => {
|
||||||
|
const { deploy: data, setDeploy, error, setError } = useDeployEditContext();
|
||||||
|
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
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 bucketResp = bucketSchema.safeParse(data.config?.domain);
|
||||||
|
if (!bucketResp.success) {
|
||||||
|
setError({
|
||||||
|
...error,
|
||||||
|
bucket: JSON.parse(bucketResp.error.message)[0].message,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setError({
|
||||||
|
...error,
|
||||||
|
bucket: "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!data.id) {
|
||||||
|
setDeploy({
|
||||||
|
...data,
|
||||||
|
config: {
|
||||||
|
endpoint: "oss-cn-hangzhou.aliyuncs.com",
|
||||||
|
bucket: "",
|
||||||
|
domain: "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const domainSchema = z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||||
|
message: t("common.errmsg.domain_invalid"),
|
||||||
|
});
|
||||||
|
|
||||||
|
const bucketSchema = z.string().min(1, {
|
||||||
|
message: t("domain.deployment.form.oss_bucket.placeholder"),
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col space-y-8">
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.oss_endpoint.label")}</Label>
|
||||||
|
<Input
|
||||||
|
placeholder={t("domain.deployment.form.oss_endpoint.placeholder")}
|
||||||
|
className="w-full mt-1"
|
||||||
|
value={data?.config?.endpoint}
|
||||||
|
onChange={(e) => {
|
||||||
|
const temp = e.target.value;
|
||||||
|
|
||||||
|
const newData = produce(data, (draft) => {
|
||||||
|
if (!draft.config) {
|
||||||
|
draft.config = {};
|
||||||
|
}
|
||||||
|
draft.config.endpoint = temp;
|
||||||
|
});
|
||||||
|
setDeploy(newData);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="text-red-600 text-sm mt-1">{error?.endpoint}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.oss_bucket.label")}</Label>
|
||||||
|
<Input
|
||||||
|
placeholder={t("domain.deployment.form.oss_bucket.placeholder")}
|
||||||
|
className="w-full mt-1"
|
||||||
|
value={data?.config?.bucket}
|
||||||
|
onChange={(e) => {
|
||||||
|
const temp = e.target.value;
|
||||||
|
|
||||||
|
const resp = bucketSchema.safeParse(temp);
|
||||||
|
if (!resp.success) {
|
||||||
|
setError({
|
||||||
|
...error,
|
||||||
|
bucket: JSON.parse(resp.error.message)[0].message,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setError({
|
||||||
|
...error,
|
||||||
|
bucket: "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const newData = produce(data, (draft) => {
|
||||||
|
if (!draft.config) {
|
||||||
|
draft.config = {};
|
||||||
|
}
|
||||||
|
draft.config.bucket = temp;
|
||||||
|
});
|
||||||
|
setDeploy(newData);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="text-red-600 text-sm mt-1">{error?.bucket}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.domain.label")}</Label>
|
||||||
|
<Input
|
||||||
|
placeholder={t("domain.deployment.form.domain.label")}
|
||||||
|
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 DeployToAliyunOSS;
|
77
ui/src/components/certimate/DeployToHuaweiCloudCDN.tsx
Normal file
77
ui/src/components/certimate/DeployToHuaweiCloudCDN.tsx
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
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 { useDeployEditContext } from "./DeployEdit";
|
||||||
|
|
||||||
|
const DeployToHuaweiCloudCDN = () => {
|
||||||
|
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]);
|
||||||
|
|
||||||
|
const domainSchema = z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||||
|
message: t("common.errmsg.domain_invalid"),
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col space-y-8">
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.domain.label")}</Label>
|
||||||
|
<Input
|
||||||
|
placeholder={t("domain.deployment.form.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 DeployToHuaweiCloudCDN;
|
104
ui/src/components/certimate/DeployToKubernetesSecret.tsx
Normal file
104
ui/src/components/certimate/DeployToKubernetesSecret.tsx
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { produce } from "immer";
|
||||||
|
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Label } from "@/components/ui/label";
|
||||||
|
import { useDeployEditContext } from "./DeployEdit";
|
||||||
|
|
||||||
|
const DeployToKubernetesSecret = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { setError } = useDeployEditContext();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setError({});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const { deploy: data, setDeploy } = useDeployEditContext();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!data.id) {
|
||||||
|
setDeploy({
|
||||||
|
...data,
|
||||||
|
config: {
|
||||||
|
namespace: "default",
|
||||||
|
secretName: "",
|
||||||
|
secretDataKeyForCrt: "tls.crt",
|
||||||
|
secretDataKeyForKey: "tls.key",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="flex flex-col space-y-8">
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.k8s_namespace.label")}</Label>
|
||||||
|
<Input
|
||||||
|
placeholder={t("domain.deployment.form.k8s_namespace.label")}
|
||||||
|
className="w-full mt-1"
|
||||||
|
value={data?.config?.namespace}
|
||||||
|
onChange={(e) => {
|
||||||
|
const newData = produce(data, (draft) => {
|
||||||
|
draft.config ??= {};
|
||||||
|
draft.config.namespace = e.target.value;
|
||||||
|
});
|
||||||
|
setDeploy(newData);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.k8s_secret_name.label")}</Label>
|
||||||
|
<Input
|
||||||
|
placeholder={t("domain.deployment.form.k8s_secret_name.label")}
|
||||||
|
className="w-full mt-1"
|
||||||
|
value={data?.config?.secretName}
|
||||||
|
onChange={(e) => {
|
||||||
|
const newData = produce(data, (draft) => {
|
||||||
|
draft.config ??= {};
|
||||||
|
draft.config.secretName = e.target.value;
|
||||||
|
});
|
||||||
|
setDeploy(newData);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.k8s_secret_data_key_for_crt.label")}</Label>
|
||||||
|
<Input
|
||||||
|
placeholder={t("domain.deployment.form.k8s_secret_data_key_for_crt.label")}
|
||||||
|
className="w-full mt-1"
|
||||||
|
value={data?.config?.secretDataKeyForCrt}
|
||||||
|
onChange={(e) => {
|
||||||
|
const newData = produce(data, (draft) => {
|
||||||
|
draft.config ??= {};
|
||||||
|
draft.config.secretDataKeyForCrt = e.target.value;
|
||||||
|
});
|
||||||
|
setDeploy(newData);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.k8s_secret_data_key_for_key.label")}</Label>
|
||||||
|
<Input
|
||||||
|
placeholder={t("domain.deployment.form.k8s_secret_data_key_for_key.label")}
|
||||||
|
className="w-full mt-1"
|
||||||
|
value={data?.config?.secretDataKeyForKey}
|
||||||
|
onChange={(e) => {
|
||||||
|
const newData = produce(data, (draft) => {
|
||||||
|
draft.config ??= {};
|
||||||
|
draft.config.secretDataKeyForKey = e.target.value;
|
||||||
|
});
|
||||||
|
setDeploy(newData);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeployToKubernetesSecret;
|
77
ui/src/components/certimate/DeployToQiniuCDN.tsx
Normal file
77
ui/src/components/certimate/DeployToQiniuCDN.tsx
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
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 { useDeployEditContext } from "./DeployEdit";
|
||||||
|
|
||||||
|
const DeployToQiniuCDN = () => {
|
||||||
|
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]);
|
||||||
|
|
||||||
|
const domainSchema = z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||||
|
message: t("common.errmsg.domain_invalid"),
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col space-y-8">
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.domain.label")}</Label>
|
||||||
|
<Input
|
||||||
|
placeholder={t("domain.deployment.form.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 DeployToQiniuCDN;
|
113
ui/src/components/certimate/DeployToSSH.tsx
Normal file
113
ui/src/components/certimate/DeployToSSH.tsx
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
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 DeployToSSH = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { setError } = useDeployEditContext();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setError({});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const { deploy: data, setDeploy } = useDeployEditContext();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!data.id) {
|
||||||
|
setDeploy({
|
||||||
|
...data,
|
||||||
|
config: {
|
||||||
|
certPath: "/etc/nginx/ssl/nginx.crt",
|
||||||
|
keyPath: "/etc/nginx/ssl/nginx.key",
|
||||||
|
preCommand: "",
|
||||||
|
command: "sudo service nginx reload",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="flex flex-col space-y-8">
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.ssh_cert_path.label")}</Label>
|
||||||
|
<Input
|
||||||
|
placeholder={t("domain.deployment.form.ssh_cert_path.label")}
|
||||||
|
className="w-full mt-1"
|
||||||
|
value={data?.config?.certPath}
|
||||||
|
onChange={(e) => {
|
||||||
|
const newData = produce(data, (draft) => {
|
||||||
|
if (!draft.config) {
|
||||||
|
draft.config = {};
|
||||||
|
}
|
||||||
|
draft.config.certPath = e.target.value;
|
||||||
|
});
|
||||||
|
setDeploy(newData);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.ssh_key_path.label")}</Label>
|
||||||
|
<Input
|
||||||
|
placeholder={t("domain.deployment.form.ssh_key_path.placeholder")}
|
||||||
|
className="w-full mt-1"
|
||||||
|
value={data?.config?.keyPath}
|
||||||
|
onChange={(e) => {
|
||||||
|
const newData = produce(data, (draft) => {
|
||||||
|
if (!draft.config) {
|
||||||
|
draft.config = {};
|
||||||
|
}
|
||||||
|
draft.config.keyPath = e.target.value;
|
||||||
|
});
|
||||||
|
setDeploy(newData);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.ssh_pre_command.label")}</Label>
|
||||||
|
<Textarea
|
||||||
|
className="mt-1"
|
||||||
|
value={data?.config?.preCommand}
|
||||||
|
placeholder={t("domain.deployment.form.ssh_pre_command.placeholder")}
|
||||||
|
onChange={(e) => {
|
||||||
|
const newData = produce(data, (draft) => {
|
||||||
|
if (!draft.config) {
|
||||||
|
draft.config = {};
|
||||||
|
}
|
||||||
|
draft.config.preCommand = e.target.value;
|
||||||
|
});
|
||||||
|
setDeploy(newData);
|
||||||
|
}}
|
||||||
|
></Textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.ssh_command.label")}</Label>
|
||||||
|
<Textarea
|
||||||
|
className="mt-1"
|
||||||
|
value={data?.config?.command}
|
||||||
|
placeholder={t("domain.deployment.form.ssh_command.placeholder")}
|
||||||
|
onChange={(e) => {
|
||||||
|
const newData = produce(data, (draft) => {
|
||||||
|
if (!draft.config) {
|
||||||
|
draft.config = {};
|
||||||
|
}
|
||||||
|
draft.config.command = e.target.value;
|
||||||
|
});
|
||||||
|
setDeploy(newData);
|
||||||
|
}}
|
||||||
|
></Textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeployToSSH;
|
77
ui/src/components/certimate/DeployToTencentCDN.tsx
Normal file
77
ui/src/components/certimate/DeployToTencentCDN.tsx
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
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 { useDeployEditContext } from "./DeployEdit";
|
||||||
|
|
||||||
|
const DeployToTencentCDN = () => {
|
||||||
|
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]);
|
||||||
|
|
||||||
|
const domainSchema = z.string().regex(/^(?:\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$/, {
|
||||||
|
message: t("common.errmsg.domain_invalid"),
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col space-y-8">
|
||||||
|
<div>
|
||||||
|
<Label>{t("domain.deployment.form.domain.label")}</Label>
|
||||||
|
<Input
|
||||||
|
placeholder={t("domain.deployment.form.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 DeployToTencentCDN;
|
35
ui/src/components/certimate/DeployToWebhook.tsx
Normal file
35
ui/src/components/certimate/DeployToWebhook.tsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import { useEffect } from "react";
|
||||||
|
import { produce } from "immer";
|
||||||
|
|
||||||
|
import { useDeployEditContext } from "./DeployEdit";
|
||||||
|
import KVList from "./KVList";
|
||||||
|
import { type KVType } from "@/domain/domain";
|
||||||
|
|
||||||
|
const DeployToWebhook = () => {
|
||||||
|
const { deploy: data, setDeploy } = useDeployEditContext();
|
||||||
|
|
||||||
|
const { setError } = useDeployEditContext();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setError({});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<KVList
|
||||||
|
variables={data?.config?.variables}
|
||||||
|
onValueChange={(variables: KVType[]) => {
|
||||||
|
const newData = produce(data, (draft) => {
|
||||||
|
if (!draft.config) {
|
||||||
|
draft.config = {};
|
||||||
|
}
|
||||||
|
draft.config.variables = variables;
|
||||||
|
});
|
||||||
|
setDeploy(newData);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeployToWebhook;
|
@ -63,21 +63,23 @@ export type Statistic = {
|
|||||||
disabled: number;
|
disabled: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getLastDeployment = (domain: Domain): Deployment | undefined => {
|
type DeployTarget = {
|
||||||
return domain.expand?.lastDeployment;
|
type: string;
|
||||||
|
name: string;
|
||||||
|
icon: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const targetTypeMap: Map<string, [string, string]> = new Map([
|
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-oss", "common.provider.aliyun.oss", "/imgs/providers/aliyun.svg"],
|
||||||
["aliyun-dcdn", ["common.provider.aliyun.dcdn", "/imgs/providers/aliyun.svg"]],
|
["aliyun-cdn", "common.provider.aliyun.cdn", "/imgs/providers/aliyun.svg"],
|
||||||
["tencent-cdn", ["common.provider.tencent.cdn", "/imgs/providers/tencent.svg"]],
|
["aliyun-dcdn", "common.provider.aliyun.dcdn", "/imgs/providers/aliyun.svg"],
|
||||||
["huaweicloud-cdn", ["common.provider.huaweicloud.cdn", "/imgs/providers/huaweicloud.svg"]],
|
["tencent-cdn", "common.provider.tencent.cdn", "/imgs/providers/tencent.svg"],
|
||||||
["qiniu-cdn", ["common.provider.qiniu.cdn", "/imgs/providers/qiniu.svg"]],
|
["huaweicloud-cdn", "common.provider.huaweicloud.cdn", "/imgs/providers/huaweicloud.svg"],
|
||||||
["local", ["common.provider.local", "/imgs/providers/local.svg"]],
|
["qiniu-cdn", "common.provider.qiniu.cdn", "/imgs/providers/qiniu.svg"],
|
||||||
["ssh", ["common.provider.ssh", "/imgs/providers/ssh.svg"]],
|
["local", "common.provider.local", "/imgs/providers/local.svg"],
|
||||||
["webhook", ["common.provider.webhook", "/imgs/providers/webhook.svg"]],
|
["ssh", "common.provider.ssh", "/imgs/providers/ssh.svg"],
|
||||||
["k8s-secret", ["common.provider.kubernetes.secret", "/imgs/providers/k8s.svg"]],
|
["webhook", "common.provider.webhook", "/imgs/providers/webhook.svg"],
|
||||||
]);
|
["k8s-secret", "common.provider.kubernetes.secret", "/imgs/providers/k8s.svg"],
|
||||||
|
].map(([type, name, icon]) => [type, { type, name, icon }])
|
||||||
export const targetTypeKeys = Array.from(targetTypeMap.keys());
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user