certimate/ui/src/components/certimate/DeployEditDialog.tsx

285 lines
9.3 KiB
TypeScript

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 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";
import DeployToLocal from "./DeployToLocal";
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 | undefined>>({});
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 === deployTargetsMap.get(locDeployConfig.type)?.provider;
});
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 "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":
childComponent = <DeployToTencentCLB />;
break;
case "tencent-cos":
childComponent = <DeployToTencentCOS />;
break;
case "tencent-teo":
childComponent = <DeployToTencentTEO />;
break;
case "huaweicloud-cdn":
childComponent = <DeployToHuaweiCloudCDN />;
break;
case "huaweicloud-elb":
childComponent = <DeployToHuaweiCloudELB />;
break;
case "qiniu-cdn":
childComponent = <DeployToQiniuCDN />;
break;
case "local":
childComponent = <DeployToLocal />;
break;
case "ssh":
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;