diff --git a/ui/src/components/certimate/DeployList.tsx b/ui/src/components/certimate/DeployList.tsx new file mode 100644 index 00000000..aae7a817 --- /dev/null +++ b/ui/src/components/certimate/DeployList.tsx @@ -0,0 +1,338 @@ +import { createContext, useContext, useEffect, useState } from "react"; +import { Button } from "../ui/button"; +import { EditIcon, Plus, Trash2 } from "lucide-react"; +import { DeployConfig, targetTypeKeys, targetTypeMap } from "@/domain/domain"; +import Show from "../Show"; +import { Alert, AlertDescription } from "../ui/alert"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "../ui/dialog"; + +import { Label } from "../ui/label"; +import { useConfig } from "@/providers/config"; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectTrigger, + SelectValue, +} from "../ui/select"; +import { Access, accessTypeMap } from "@/domain/access"; +import { useTranslation } from "react-i18next"; +import { AccessEdit } from "./AccessEdit"; +import { Input } from "../ui/input"; +import { Textarea } from "../ui/textarea"; +import KVList from "./KVList"; + +type DeployListContextProps = { + deploys: DeployConfig[]; +}; + +const DeployListContext = createContext({ + deploys: [], +}); + +export const useDeployListContext = () => { + return useContext(DeployListContext); +}; + +type DeployListProps = { + deploys: DeployConfig[]; +}; + +const DeployList = ({ deploys }: DeployListProps) => { + const [list, setList] = useState([]); + + useEffect(() => { + setList(deploys); + }, [deploys]); + + return ( + <> + + 0} + fallback={ + + +
暂无部署配置,请添加后开始部署证书吧
+
+ 添加部署} + /> +
+
+
+ } + > +
+ 添加部署} /> +
+ +
+
+
+
+
+ +
+
+
ssh部署
+
业务服务器
+
+
+
+ + +
+
+
+
+
+
+ + ); +}; + +type DeployEditDialogProps = { + trigger: React.ReactNode; +}; +const DeployEditDialog = ({ trigger }: DeployEditDialogProps) => { + const { + config: { accesses }, + } = useConfig(); + + const [access, setAccess] = useState(); + const [deployType, setDeployType] = useState(); + const [accessType, setAccessType] = useState(""); + + useEffect(() => { + const temp = accessType.split("-"); + console.log(temp); + let t; + if (temp && temp.length > 1) { + t = temp[1]; + } else { + t = accessType; + } + setDeployType(t as TargetType); + }, [accessType]); + + const { t } = useTranslation(); + + const targetAccesses = accesses.filter((item) => { + if (item.usage == "apply") { + return false; + } + + if (accessType == "") { + return true; + } + const types = accessType.split("-"); + return item.configType === types[0]; + }); + + return ( + + {trigger} + + + 部署 + + + {/* 授权类型 */} +
+ + + +
+ {/* 授权 */} +
+
+ } + op="add" + /> + + + + + + + + + + +
+
+ ); +}; + +type TargetType = "ssh" | "cdn" | "webhook" | "local" | "oss" | "dcdn"; + +type DeployEditProps = { + type: TargetType; + data?: DeployConfig; +}; +const DeployEdit = ({ type, data }: DeployEditProps) => { + const getDeploy = () => { + switch (type) { + case "ssh": + return ; + case "local": + return ; + case "cdn": + return ; + case "dcdn": + return ; + case "oss": + return ; + case "webhook": + return ; + default: + return ; + } + }; + return getDeploy(); +}; + +type DeployProps = { + data?: DeployConfig; +}; + +const DeploySSH = ({ data }: DeployProps) => { + const { t } = useTranslation(); + return ( + <> +
+
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ + ); +}; + +const DeployCDN = ({ data }: DeployProps) => { + return ( +
+
+ + +
+
+ ); +}; + +const DeployWebhook = ({ data }: DeployProps) => { + return ( + <> + + + ); +}; + +export default DeployList; diff --git a/ui/src/components/certimate/KVList.tsx b/ui/src/components/certimate/KVList.tsx new file mode 100644 index 00000000..383381f7 --- /dev/null +++ b/ui/src/components/certimate/KVList.tsx @@ -0,0 +1,215 @@ +import { KVType } from "@/domain/domain"; +import { useEffect, useState } from "react"; +import { Label } from "../ui/label"; +import { Edit, Plus, Trash2 } from "lucide-react"; +import { useTranslation } from "react-i18next"; +import Show from "../Show"; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "../ui/dialog"; +import { Input } from "../ui/input"; +import { Button } from "../ui/button"; + +type KVListProps = { + variables?: KVType[]; +}; + +const KVList = ({ variables }: KVListProps) => { + const [locVariables, setLocVariables] = useState([]); + + const { t } = useTranslation(); + + useEffect(() => { + if (variables) { + setLocVariables(variables); + } + }, [variables]); + + const handleAddClick = (variable: KVType) => { + // 查看是否存在key,存在则更新,不存在则添加 + const index = locVariables.findIndex((item) => { + return item.key === variable.key; + }); + + if (index === -1) { + setLocVariables([...locVariables, variable]); + } else { + const newList = [...locVariables]; + newList[index] = variable; + setLocVariables(newList); + } + }; + + const handleDeleteClick = (index: number) => { + const newList = [...locVariables]; + newList.splice(index, 1); + setLocVariables(newList); + }; + + const handleEditClick = (index: number, variable: KVType) => { + const newList = [...locVariables]; + newList[index] = variable; + setLocVariables(newList); + }; + + return ( + <> +
+ + + + + +
{t("add")}
+
+ } + onSave={(variable) => { + handleAddClick(variable); + }} + /> + + + + +
+ {t("not.added.yet.variable")} +
+ + + + +
{t("add")}
+ + } + variable={{ + key: "", + value: "", + }} + onSave={(variable) => { + handleAddClick(variable); + }} + /> + + } + > +
+ {locVariables?.map((item, index) => ( +
+
+ {item.key}={item.value} +
+
+ } + variable={item} + onSave={(variable) => { + handleEditClick(index, variable); + }} + /> + + { + handleDeleteClick(index); + }} + /> +
+
+ ))} +
+
+ + ); +}; + +type KVEditProps = { + variable?: KVType; + trigger: React.ReactNode; + onSave: (variable: KVType) => void; +}; + +const KVEdit = ({ variable, trigger, onSave }: KVEditProps) => { + const [locVariable, setLocVariable] = useState({ + key: "", + value: "", + }); + + useEffect(() => { + if (variable) setLocVariable(variable!); + }, [variable]); + + const { t } = useTranslation(); + + const [open, setOpen] = useState(false); + + return ( + { + setOpen(!open); + }} + > + {trigger} + + + 变量 + +
+ + { + setLocVariable({ ...locVariable, key: e.target.value }); + }} + className="w-full mt-1" + /> +
+ +
+ + { + setLocVariable({ ...locVariable, value: e.target.value }); + }} + className="w-full mt-1" + /> +
+
+ +
+ +
+
+
+
+ ); +}; + +export default KVList; diff --git a/ui/src/domain/domain.ts b/ui/src/domain/domain.ts index a49378bf..e7f09bbd 100644 --- a/ui/src/domain/domain.ts +++ b/ui/src/domain/domain.ts @@ -31,7 +31,7 @@ export type Domain = { deployConfig?: DeployConfig[]; }; -type KVType = { +export type KVType = { key: string; value: string; }; diff --git a/ui/src/pages/domains/Edit.tsx b/ui/src/pages/domains/Edit.tsx index b01c9219..32213a73 100644 --- a/ui/src/pages/domains/Edit.tsx +++ b/ui/src/pages/domains/Edit.tsx @@ -40,6 +40,7 @@ import { EmailsSetting } from "@/domain/settings"; import { useTranslation } from "react-i18next"; import StringList from "@/components/certimate/StringList"; import { Input } from "@/components/ui/input"; +import DeployList from "@/components/certimate/DeployList"; const Edit = () => { const { @@ -420,26 +421,11 @@ const Edit = () => {
-
- -
-
-
-
-
ALIYUN-CDN
-
- - -
-
-
-
+