refactor(ui): refactor accesses state using zustand store

This commit is contained in:
Fu Diwei 2024-12-11 19:55:50 +08:00
parent b744363736
commit bb3009a124
48 changed files with 359 additions and 404 deletions

View File

@ -1,3 +1,4 @@
import { Statistics } from "@/domain/statistics";
import { getPocketBase } from "@/repository/pocketbase"; import { getPocketBase } from "@/repository/pocketbase";
export const get = async () => { export const get = async () => {
@ -7,9 +8,9 @@ export const get = async () => {
method: "GET", method: "GET",
}); });
if (resp.code != 0) { if (resp.code !== 0) {
throw new Error(resp.msg); throw new Error(resp.msg);
} }
return resp.data; return resp.data as Statistics;
}; };

View File

@ -3,11 +3,11 @@ import { Button, Dropdown, Form, Input, message, Space, Tooltip } from "antd";
import { CopyToClipboard } from "react-copy-to-clipboard"; import { CopyToClipboard } from "react-copy-to-clipboard";
import { ChevronDown as ChevronDownIcon, Clipboard as ClipboardIcon, ThumbsUp as ThumbsUpIcon } from "lucide-react"; import { ChevronDown as ChevronDownIcon, Clipboard as ClipboardIcon, ThumbsUp as ThumbsUpIcon } from "lucide-react";
import { type Certificate } from "@/domain/certificate"; import { type CertificateModel } from "@/domain/certificate";
import { saveFiles2Zip } from "@/utils/file"; import { saveFiles2Zip } from "@/utils/file";
type CertificateDetailProps = { type CertificateDetailProps = {
data: Certificate; data: CertificateModel;
}; };
const CertificateDetail = ({ data }: CertificateDetailProps) => { const CertificateDetail = ({ data }: CertificateDetailProps) => {

View File

@ -1,11 +1,11 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Drawer } from "antd"; import { Drawer } from "antd";
import { type Certificate } from "@/domain/certificate"; import { type CertificateModel } from "@/domain/certificate";
import CertificateDetail from "./CertificateDetail"; import CertificateDetail from "./CertificateDetail";
type CertificateDetailDrawerProps = { type CertificateDetailDrawerProps = {
data?: Certificate; data?: CertificateModel;
open?: boolean; open?: boolean;
onClose?: () => void; onClose?: () => void;
}; };

View File

@ -8,19 +8,21 @@ import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type AliyunConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type AliyunConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessAliyunFormProps = { type AccessAliyunFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessAliyunForm = ({ data, op, onAfterReq }: AccessAliyunFormProps) => { const AccessAliyunForm = ({ data, op, onAfterReq }: AccessAliyunFormProps) => {
const { addAccess, updateAccess } = useConfigContext();
const { t } = useTranslation(); const { t } = useTranslation();
const { createAccess, updateAccess } = useAccessStore();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
name: z name: z
@ -56,7 +58,7 @@ const AccessAliyunForm = ({ data, op, onAfterReq }: AccessAliyunFormProps) => {
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -81,7 +83,7 @@ const AccessAliyunForm = ({ data, op, onAfterReq }: AccessAliyunFormProps) => {
return; return;
} }
addAccess(req); createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,19 +8,21 @@ import { Input } from "@/components/ui/input";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { Access, accessProvidersMap, accessTypeFormSchema, type AwsConfig } from "@/domain/access"; import { AccessModel, accessProvidersMap, accessTypeFormSchema, type AwsConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessAwsFormProps = { type AccessAwsFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessAwsForm = ({ data, op, onAfterReq }: AccessAwsFormProps) => { const AccessAwsForm = ({ data, op, onAfterReq }: AccessAwsFormProps) => {
const { addAccess, updateAccess } = useConfigContext();
const { t } = useTranslation(); const { t } = useTranslation();
const { createAccess, updateAccess } = useAccessStore();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
name: z name: z
@ -68,7 +70,7 @@ const AccessAwsForm = ({ data, op, onAfterReq }: AccessAwsFormProps) => {
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -94,7 +96,8 @@ const AccessAwsForm = ({ data, op, onAfterReq }: AccessAwsFormProps) => {
updateAccess(req); updateAccess(req);
return; return;
} }
addAccess(req);
createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,19 +8,21 @@ import { Input } from "@/components/ui/input";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type BaiduCloudConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type BaiduCloudConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessBaiduCloudFormProps = { type AccessBaiduCloudFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessBaiduCloudForm = ({ data, op, onAfterReq }: AccessBaiduCloudFormProps) => { const AccessBaiduCloudForm = ({ data, op, onAfterReq }: AccessBaiduCloudFormProps) => {
const { addAccess, updateAccess } = useConfigContext();
const { t } = useTranslation(); const { t } = useTranslation();
const { createAccess, updateAccess } = useAccessStore();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
name: z name: z
@ -56,7 +58,7 @@ const AccessBaiduCloudForm = ({ data, op, onAfterReq }: AccessBaiduCloudFormProp
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -80,7 +82,8 @@ const AccessBaiduCloudForm = ({ data, op, onAfterReq }: AccessBaiduCloudFormProp
updateAccess(req); updateAccess(req);
return; return;
} }
addAccess(req);
createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,18 +8,18 @@ import { Input } from "@/components/ui/input";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type ByteplusConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type ByteplusConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessByteplusFormProps = { type AccessByteplusFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessByteplusForm = ({ data, op, onAfterReq }: AccessByteplusFormProps) => { const AccessByteplusForm = ({ data, op, onAfterReq }: AccessByteplusFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const { t } = useTranslation(); const { t } = useTranslation();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
@ -56,7 +56,7 @@ const AccessByteplusForm = ({ data, op, onAfterReq }: AccessByteplusFormProps) =
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -80,7 +80,7 @@ const AccessByteplusForm = ({ data, op, onAfterReq }: AccessByteplusFormProps) =
updateAccess(req); updateAccess(req);
return; return;
} }
addAccess(req); createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,18 +8,18 @@ import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type CloudflareConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type CloudflareConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessCloudflareFormProps = { type AccessCloudflareFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessCloudflareForm = ({ data, op, onAfterReq }: AccessCloudflareFormProps) => { const AccessCloudflareForm = ({ data, op, onAfterReq }: AccessCloudflareFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const { t } = useTranslation(); const { t } = useTranslation();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
@ -50,7 +50,7 @@ const AccessCloudflareForm = ({ data, op, onAfterReq }: AccessCloudflareFormProp
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -73,7 +73,7 @@ const AccessCloudflareForm = ({ data, op, onAfterReq }: AccessCloudflareFormProp
updateAccess(req); updateAccess(req);
return; return;
} }
addAccess(req); createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,18 +8,18 @@ import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type DogeCloudConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type DogeCloudConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessDogeCloudFormProps = { type AccessDogeCloudFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessDogeCloudForm = ({ data, op, onAfterReq }: AccessDogeCloudFormProps) => { const AccessDogeCloudForm = ({ data, op, onAfterReq }: AccessDogeCloudFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const { t } = useTranslation(); const { t } = useTranslation();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
@ -50,7 +50,7 @@ const AccessDogeCloudForm = ({ data, op, onAfterReq }: AccessDogeCloudFormProps)
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -74,7 +74,7 @@ const AccessDogeCloudForm = ({ data, op, onAfterReq }: AccessDogeCloudFormProps)
updateAccess(req); updateAccess(req);
return; return;
} }
addAccess(req); createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -23,14 +23,14 @@ import AccessWebhookForm from "./AccessWebhookForm";
import AccessKubernetesForm from "./AccessKubernetesForm"; import AccessKubernetesForm from "./AccessKubernetesForm";
import AccessVolcengineForm from "./AccessVolcengineForm"; import AccessVolcengineForm from "./AccessVolcengineForm";
import AccessByteplusForm from "./AccessByteplusForm"; import AccessByteplusForm from "./AccessByteplusForm";
import { Access } from "@/domain/access"; import { AccessModel } from "@/domain/access";
import { AccessTypeSelect } from "./AccessTypeSelect"; import { AccessTypeSelect } from "./AccessTypeSelect";
type AccessEditProps = { type AccessEditProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
className?: string; className?: string;
trigger: React.ReactNode; trigger: React.ReactNode;
data?: Access; data?: AccessModel;
outConfigType?: string; outConfigType?: string;
}; };

View File

@ -8,18 +8,18 @@ import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type GodaddyConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type GodaddyConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessGodaddyFormProps = { type AccessGodaddyFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessGodaddyForm = ({ data, op, onAfterReq }: AccessGodaddyFormProps) => { const AccessGodaddyForm = ({ data, op, onAfterReq }: AccessGodaddyFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const { t } = useTranslation(); const { t } = useTranslation();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
@ -56,7 +56,7 @@ const AccessGodaddyForm = ({ data, op, onAfterReq }: AccessGodaddyFormProps) =>
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -80,7 +80,7 @@ const AccessGodaddyForm = ({ data, op, onAfterReq }: AccessGodaddyFormProps) =>
updateAccess(req); updateAccess(req);
return; return;
} }
addAccess(req); createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,18 +8,18 @@ import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type HttpreqConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type HttpreqConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessHttpreqFormProps = { type AccessHttpreqFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessHttpreqForm = ({ data, op, onAfterReq }: AccessHttpreqFormProps) => { const AccessHttpreqForm = ({ data, op, onAfterReq }: AccessHttpreqFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const { t } = useTranslation(); const { t } = useTranslation();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
@ -62,7 +62,7 @@ const AccessHttpreqForm = ({ data, op, onAfterReq }: AccessHttpreqFormProps) =>
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -89,7 +89,7 @@ const AccessHttpreqForm = ({ data, op, onAfterReq }: AccessHttpreqFormProps) =>
return; return;
} }
addAccess(req); createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,18 +8,18 @@ import { Input } from "@/components/ui/input";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type HuaweiCloudConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type HuaweiCloudConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessHuaweiCloudFormProps = { type AccessHuaweiCloudFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessHuaweiCloudForm = ({ data, op, onAfterReq }: AccessHuaweiCloudFormProps) => { const AccessHuaweiCloudForm = ({ data, op, onAfterReq }: AccessHuaweiCloudFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const { t } = useTranslation(); const { t } = useTranslation();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
@ -62,7 +62,7 @@ const AccessHuaweiCloudForm = ({ data, op, onAfterReq }: AccessHuaweiCloudFormPr
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -87,7 +87,7 @@ const AccessHuaweiCloudForm = ({ data, op, onAfterReq }: AccessHuaweiCloudFormPr
updateAccess(req); updateAccess(req);
return; return;
} }
addAccess(req); createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -10,18 +10,18 @@ import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { readFileContent } from "@/utils/file"; import { readFileContent } from "@/utils/file";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type KubernetesConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type KubernetesConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessKubernetesFormProps = { type AccessKubernetesFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessKubernetesForm = ({ data, op, onAfterReq }: AccessKubernetesFormProps) => { const AccessKubernetesForm = ({ data, op, onAfterReq }: AccessKubernetesFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const fileInputRef = useRef<HTMLInputElement | null>(null); const fileInputRef = useRef<HTMLInputElement | null>(null);
const [fileName, setFileName] = useState(""); const [fileName, setFileName] = useState("");
@ -60,7 +60,7 @@ const AccessKubernetesForm = ({ data, op, onAfterReq }: AccessKubernetesFormProp
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -82,7 +82,7 @@ const AccessKubernetesForm = ({ data, op, onAfterReq }: AccessKubernetesFormProp
if (data.id && op == "edit") { if (data.id && op == "edit") {
updateAccess(req); updateAccess(req);
} else { } else {
addAccess(req); createAccess(req);
} }
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,18 +8,18 @@ import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessLocalFormProps = { type AccessLocalFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessLocalForm = ({ data, op, onAfterReq }: AccessLocalFormProps) => { const AccessLocalForm = ({ data, op, onAfterReq }: AccessLocalFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const { t } = useTranslation(); const { t } = useTranslation();
const formSchema = z.object({ const formSchema = z.object({
@ -41,7 +41,7 @@ const AccessLocalForm = ({ data, op, onAfterReq }: AccessLocalFormProps) => {
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -62,7 +62,7 @@ const AccessLocalForm = ({ data, op, onAfterReq }: AccessLocalFormProps) => {
if (data.id && op == "edit") { if (data.id && op == "edit") {
updateAccess(req); updateAccess(req);
} else { } else {
addAccess(req); createAccess(req);
} }
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,18 +8,18 @@ import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type NamesiloConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type NamesiloConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessNamesiloFormProps = { type AccessNamesiloFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessNamesiloForm = ({ data, op, onAfterReq }: AccessNamesiloFormProps) => { const AccessNamesiloForm = ({ data, op, onAfterReq }: AccessNamesiloFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const { t } = useTranslation(); const { t } = useTranslation();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
@ -50,7 +50,7 @@ const AccessNamesiloForm = ({ data, op, onAfterReq }: AccessNamesiloFormProps) =
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -73,7 +73,7 @@ const AccessNamesiloForm = ({ data, op, onAfterReq }: AccessNamesiloFormProps) =
updateAccess(req); updateAccess(req);
return; return;
} }
addAccess(req); createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,18 +8,18 @@ import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type PdnsConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type PdnsConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessPdnsFormProps = { type AccessPdnsFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessPdnsForm = ({ data, op, onAfterReq }: AccessPdnsFormProps) => { const AccessPdnsForm = ({ data, op, onAfterReq }: AccessPdnsFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const { t } = useTranslation(); const { t } = useTranslation();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
@ -53,7 +53,7 @@ const AccessPdnsForm = ({ data, op, onAfterReq }: AccessPdnsFormProps) => {
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -78,7 +78,7 @@ const AccessPdnsForm = ({ data, op, onAfterReq }: AccessPdnsFormProps) => {
return; return;
} }
addAccess(req); createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,18 +8,18 @@ import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type QiniuConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type QiniuConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessQiniuFormProps = { type AccessQiniuFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessQiniuForm = ({ data, op, onAfterReq }: AccessQiniuFormProps) => { const AccessQiniuForm = ({ data, op, onAfterReq }: AccessQiniuFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const { t } = useTranslation(); const { t } = useTranslation();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
@ -50,7 +50,7 @@ const AccessQiniuForm = ({ data, op, onAfterReq }: AccessQiniuFormProps) => {
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -74,7 +74,7 @@ const AccessQiniuForm = ({ data, op, onAfterReq }: AccessQiniuFormProps) => {
updateAccess(req); updateAccess(req);
return; return;
} }
addAccess(req); createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -10,18 +10,18 @@ import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { readFileContent } from "@/utils/file"; import { readFileContent } from "@/utils/file";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type SSHConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type SSHConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessSSHFormProps = { type AccessSSHFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessSSHForm = ({ data, op, onAfterReq }: AccessSSHFormProps) => { const AccessSSHForm = ({ data, op, onAfterReq }: AccessSSHFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const fileInputRef = useRef<HTMLInputElement | null>(null); const fileInputRef = useRef<HTMLInputElement | null>(null);
@ -103,7 +103,7 @@ const AccessSSHForm = ({ data, op, onAfterReq }: AccessSSHFormProps) => {
let group = data.group; let group = data.group;
if (group == "emptyId") group = ""; if (group == "emptyId") group = "";
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -131,7 +131,7 @@ const AccessSSHForm = ({ data, op, onAfterReq }: AccessSSHFormProps) => {
if (data.id && op == "edit") { if (data.id && op == "edit") {
updateAccess(req); updateAccess(req);
} else { } else {
addAccess(req); createAccess(req);
} }
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,18 +8,18 @@ import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type TencentConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type TencentConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessTencentFormProps = { type AccessTencentFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessTencentForm = ({ data, op, onAfterReq }: AccessTencentFormProps) => { const AccessTencentForm = ({ data, op, onAfterReq }: AccessTencentFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const { t } = useTranslation(); const { t } = useTranslation();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
@ -56,7 +56,7 @@ const AccessTencentForm = ({ data, op, onAfterReq }: AccessTencentFormProps) =>
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -80,7 +80,7 @@ const AccessTencentForm = ({ data, op, onAfterReq }: AccessTencentFormProps) =>
updateAccess(req); updateAccess(req);
return; return;
} }
addAccess(req); createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,18 +8,18 @@ import { Input } from "@/components/ui/input";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { accessProvidersMap, accessTypeFormSchema, type Access, type VolcengineConfig } from "@/domain/access"; import { accessProvidersMap, accessTypeFormSchema, type AccessModel, type VolcengineConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessVolcengineFormProps = { type AccessVolcengineFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessVolcengineForm = ({ data, op, onAfterReq }: AccessVolcengineFormProps) => { const AccessVolcengineForm = ({ data, op, onAfterReq }: AccessVolcengineFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const { t } = useTranslation(); const { t } = useTranslation();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
@ -56,7 +56,7 @@ const AccessVolcengineForm = ({ data, op, onAfterReq }: AccessVolcengineFormProp
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -80,7 +80,7 @@ const AccessVolcengineForm = ({ data, op, onAfterReq }: AccessVolcengineFormProp
updateAccess(req); updateAccess(req);
return; return;
} }
addAccess(req); createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -8,18 +8,18 @@ import { Button } from "@/components/ui/button";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input"; import { Input } from "@/components/ui/input";
import { PbErrorData } from "@/domain/base"; import { PbErrorData } from "@/domain/base";
import { Access, accessProvidersMap, accessTypeFormSchema, WebhookConfig } from "@/domain/access"; import { AccessModel, accessProvidersMap, accessTypeFormSchema, WebhookConfig } from "@/domain/access";
import { save } from "@/repository/access"; import { save } from "@/repository/access";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
type AccessWebhookFormProps = { type AccessWebhookFormProps = {
op: "add" | "edit" | "copy"; op: "add" | "edit" | "copy";
data?: Access; data?: AccessModel;
onAfterReq: () => void; onAfterReq: () => void;
}; };
const AccessWebhookForm = ({ data, op, onAfterReq }: AccessWebhookFormProps) => { const AccessWebhookForm = ({ data, op, onAfterReq }: AccessWebhookFormProps) => {
const { addAccess, updateAccess } = useConfigContext(); const { createAccess, updateAccess } = useAccessStore();
const { t } = useTranslation(); const { t } = useTranslation();
const formSchema = z.object({ const formSchema = z.object({
id: z.string().optional(), id: z.string().optional(),
@ -47,7 +47,7 @@ const AccessWebhookForm = ({ data, op, onAfterReq }: AccessWebhookFormProps) =>
}); });
const onSubmit = async (data: z.infer<typeof formSchema>) => { const onSubmit = async (data: z.infer<typeof formSchema>) => {
const req: Access = { const req: AccessModel = {
id: data.id as string, id: data.id as string,
name: data.name, name: data.name,
configType: data.configType, configType: data.configType,
@ -70,7 +70,7 @@ const AccessWebhookForm = ({ data, op, onAfterReq }: AccessWebhookFormProps) =>
updateAccess(req); updateAccess(req);
return; return;
} }
addAccess(req); createAccess(req);
} catch (e) { } catch (e) {
const err = e as ClientResponseError; const err = e as ClientResponseError;

View File

@ -2,7 +2,7 @@ import React, { useEffect } from "react";
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "../ui/select"; import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from "../ui/select";
import { accessProvidersMap } from "@/domain/access"; import { accessProvidersMap } from "@/domain/access";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useConfigContext } from "@/providers/config"; import { useAccessStore } from "@/stores/access";
import { deployTargetsMap } from "@/domain/domain"; import { deployTargetsMap } from "@/domain/domain";
type AccessSelectProps = { type AccessSelectProps = {
@ -13,9 +13,7 @@ type AccessSelectProps = {
const AccessSelect = ({ value, onValueChange, providerType }: AccessSelectProps) => { const AccessSelect = ({ value, onValueChange, providerType }: AccessSelectProps) => {
const [localValue, setLocalValue] = React.useState<string>(""); const [localValue, setLocalValue] = React.useState<string>("");
const { t } = useTranslation(); const { t } = useTranslation();
const { const { accesses } = useAccessStore();
config: { accesses },
} = useConfigContext();
useEffect(() => { useEffect(() => {
setLocalValue(value); setLocalValue(value);

View File

@ -15,8 +15,8 @@ import EmailsEdit from "@/components/certimate/EmailsEdit";
import StringList from "@/components/certimate/StringList"; import StringList from "@/components/certimate/StringList";
import { accessProvidersMap } from "@/domain/access"; import { accessProvidersMap } from "@/domain/access";
import { useAccessStore } from "@/stores/access";
import { useContactStore } from "@/stores/contact"; import { useContactStore } from "@/stores/contact";
import { useConfigContext } from "@/providers/config";
import { Switch } from "@/components/ui/switch"; import { Switch } from "@/components/ui/switch";
import { TooltipFast } from "@/components/ui/tooltip"; import { TooltipFast } from "@/components/ui/tooltip";
import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow"; import { WorkflowNode, WorkflowNodeConfig } from "@/domain/workflow";
@ -33,9 +33,7 @@ const selectState = (state: WorkflowState) => ({
const ApplyForm = ({ data }: ApplyFormProps) => { const ApplyForm = ({ data }: ApplyFormProps) => {
const { updateNode } = useWorkflowStore(useShallow(selectState)); const { updateNode } = useWorkflowStore(useShallow(selectState));
const { const { accesses } = useAccessStore();
config: { accesses },
} = useConfigContext();
const { emails, fetchEmails } = useContactStore(); const { emails, fetchEmails } = useContactStore();
useEffect(() => { useEffect(() => {

View File

@ -1,15 +1,13 @@
import { ConfigProvider } from "@/providers/config";
import React from "react"; import React from "react";
import { PanelProvider } from "./PanelProvider";
import { NotifyProvider } from "@/providers/notify"; import { NotifyProvider } from "@/providers/notify";
import { PanelProvider } from "./PanelProvider";
const WorkflowProvider = ({ children }: { children: React.ReactNode }) => { const WorkflowProvider = ({ children }: { children: React.ReactNode }) => {
return ( return (
<ConfigProvider>
<NotifyProvider> <NotifyProvider>
<PanelProvider>{children}</PanelProvider> <PanelProvider>{children}</PanelProvider>
</NotifyProvider> </NotifyProvider>
</ConfigProvider>
); );
}; };

View File

@ -1,4 +1,5 @@
import { z } from "zod"; import { z } from "zod";
import { type BaseModel } from "pocketbase";
type AccessUsages = "apply" | "deploy" | "all"; type AccessUsages = "apply" | "deploy" | "all";
@ -59,8 +60,7 @@ export const accessTypeFormSchema = z.union(
{ message: "access.authorization.form.type.placeholder" } { message: "access.authorization.form.type.placeholder" }
); );
export type Access = { export interface AccessModel extends BaseModel {
id: string;
name: string; name: string;
configType: string; configType: string;
usage: AccessUsages; usage: AccessUsages;
@ -83,10 +83,7 @@ export type Access = {
| KubernetesConfig | KubernetesConfig
| VolcengineConfig | VolcengineConfig
| ByteplusConfig; | ByteplusConfig;
deleted?: string; }
created?: string;
updated?: string;
};
export type AliyunConfig = { export type AliyunConfig = {
accessKeyId: string; accessKeyId: string;

View File

@ -1,7 +1,8 @@
import { Workflow } from "./workflow"; import { type BaseModel } from "pocketbase";
export type Certificate = { import { WorkflowModel } from "./workflow";
id: string;
export interface CertificateModel extends BaseModel {
san: string; san: string;
certificate: string; certificate: string;
privateKey: string; privateKey: string;
@ -12,10 +13,7 @@ export type Certificate = {
expireAt: string; expireAt: string;
workflow: string; workflow: string;
nodeId: string; nodeId: string;
created: string;
updated: string;
expand: { expand: {
workflow?: Workflow; workflow?: WorkflowModel;
}; };
}; }

View File

@ -56,16 +56,6 @@ export type ApplyConfig = {
disableFollowCNAME?: boolean; disableFollowCNAME?: boolean;
}; };
export type Statistic = {
certificateTotal: number;
certificateExpired: number;
certificateExpireSoon: number;
workflowTotal: number;
workflowEnabled: number;
workflowDisabled: number;
};
export type DeployTarget = { export type DeployTarget = {
type: string; type: string;
provider: string; provider: string;

View File

@ -1,6 +1,6 @@
import { type BaseModel } from "pocketbase"; import { type BaseModel } from "pocketbase";
export interface Settings<T> extends BaseModel { export interface SettingsModel<T> extends BaseModel {
name: string; name: string;
content: T; content: T;
} }

View File

@ -0,0 +1,8 @@
export type Statistics = {
certificateTotal: number;
certificateExpired: number;
certificateExpireSoon: number;
workflowTotal: number;
workflowEnabled: number;
workflowDisabled: number;
};

View File

@ -1,5 +1,6 @@
import { produce } from "immer"; import { produce } from "immer";
import { nanoid } from "nanoid"; import { nanoid } from "nanoid";
import { type BaseModel } from "pocketbase";
import i18n from "@/i18n"; import i18n from "@/i18n";
import { deployTargets, KVType } from "./domain"; import { deployTargets, KVType } from "./domain";
@ -27,8 +28,7 @@ export type WorkflowOutput = {
error: string; error: string;
}; };
export type Workflow = { export interface WorkflowModel extends BaseModel {
id: string;
name: string; name: string;
description?: string; description?: string;
type: string; type: string;
@ -37,9 +37,7 @@ export type Workflow = {
draft?: WorkflowNode; draft?: WorkflowNode;
enabled?: boolean; enabled?: boolean;
hasDraft?: boolean; hasDraft?: boolean;
created?: string; }
updated?: string;
};
export enum WorkflowNodeType { export enum WorkflowNodeType {
Start = "start", Start = "start",
@ -131,7 +129,7 @@ type NewWorkflowNodeOptions = {
providerType?: string; providerType?: string;
}; };
export const initWorkflow = (): Workflow => { export const initWorkflow = (): WorkflowModel => {
// 开始节点 // 开始节点
const rs = newWorkflowNode(WorkflowNodeType.Start, {}); const rs = newWorkflowNode(WorkflowNodeType.Start, {});
let root = rs; let root = rs;

View File

@ -18,7 +18,6 @@ import {
import Version from "@/components/certimate/Version"; import Version from "@/components/certimate/Version";
import { useTheme } from "@/hooks"; import { useTheme } from "@/hooks";
import { getPocketBase } from "@/repository/pocketbase"; import { getPocketBase } from "@/repository/pocketbase";
import { ConfigProvider } from "@/providers/config";
const ConsoleLayout = () => { const ConsoleLayout = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@ -52,8 +51,6 @@ const ConsoleLayout = () => {
} }
return ( return (
<>
<ConfigProvider>
<Layout className="w-full min-h-screen"> <Layout className="w-full min-h-screen">
<Layout.Sider className="max-md:hidden" theme="light" width={256}> <Layout.Sider className="max-md:hidden" theme="light" width={256}>
<div className="flex flex-col items-center justify-between w-full h-full overflow-hidden"> <div className="flex flex-col items-center justify-between w-full h-full overflow-hidden">
@ -109,8 +106,6 @@ const ConsoleLayout = () => {
</Layout.Content> </Layout.Content>
</Layout> </Layout>
</Layout> </Layout>
</ConfigProvider>
</>
); );
}; };

View File

@ -7,9 +7,8 @@ import dayjs from "dayjs";
import { ClientResponseError } from "pocketbase"; import { ClientResponseError } from "pocketbase";
import AccessEditDialog from "@/components/certimate/AccessEditDialog"; import AccessEditDialog from "@/components/certimate/AccessEditDialog";
import { accessProvidersMap, type Access as AccessType } from "@/domain/access"; import { accessProvidersMap, type AccessModel } from "@/domain/access";
import { remove as removeAccess } from "@/repository/access"; import { useAccessStore } from "@/stores/access";
import { useConfigContext } from "@/providers/config";
const AccessList = () => { const AccessList = () => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -17,9 +16,11 @@ const AccessList = () => {
const [modalApi, ModelContextHolder] = Modal.useModal(); const [modalApi, ModelContextHolder] = Modal.useModal();
const [notificationApi, NotificationContextHolder] = notification.useNotification(); const [notificationApi, NotificationContextHolder] = notification.useNotification();
const { accesses, fetchAccesses, deleteAccess } = useAccessStore();
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const tableColumns: TableProps<AccessType>["columns"] = [ const tableColumns: TableProps<AccessModel>["columns"] = [
{ {
key: "$index", key: "$index",
align: "center", align: "center",
@ -105,13 +106,15 @@ const AccessList = () => {
), ),
}, },
]; ];
const [tableData, setTableData] = useState<AccessType[]>([]); const [tableData, setTableData] = useState<AccessModel[]>([]);
const [tableTotal, setTableTotal] = useState<number>(0); const [tableTotal, setTableTotal] = useState<number>(0);
const [page, setPage] = useState<number>(1); const [page, setPage] = useState<number>(1);
const [pageSize, setPageSize] = useState<number>(10); const [pageSize, setPageSize] = useState<number>(10);
const configContext = useConfigContext(); useEffect(() => {
fetchAccesses();
}, []);
const fetchTableData = useCallback(async () => { const fetchTableData = useCallback(async () => {
if (loading) return; if (loading) return;
@ -120,10 +123,10 @@ const AccessList = () => {
try { try {
const startIndex = (page - 1) * pageSize; const startIndex = (page - 1) * pageSize;
const endIndex = startIndex + pageSize; const endIndex = startIndex + pageSize;
const items = configContext.config?.accesses?.slice(startIndex, endIndex) ?? []; const items = accesses.slice(startIndex, endIndex);
setTableData(items); setTableData(items);
setTableTotal(configContext.config?.accesses?.length ?? 0); setTableTotal(accesses.length);
} catch (err) { } catch (err) {
if (err instanceof ClientResponseError && err.isAbort) { if (err instanceof ClientResponseError && err.isAbort) {
return; return;
@ -134,21 +137,20 @@ const AccessList = () => {
} finally { } finally {
setLoading(false); setLoading(false);
} }
}, [page, pageSize, configContext.config.accesses]); }, [page, pageSize, accesses]);
useEffect(() => { useEffect(() => {
fetchTableData(); fetchTableData();
}, [fetchTableData]); }, [fetchTableData]);
const handleDeleteClick = async (data: AccessType) => { const handleDeleteClick = async (data: AccessModel) => {
modalApi.confirm({ modalApi.confirm({
title: t("access.action.delete"), title: t("access.action.delete"),
content: t("access.action.delete.confirm"), content: t("access.action.delete.confirm"),
onOk: async () => { onOk: async () => {
// TODO: 有关联数据的不允许被删除 // TODO: 有关联数据的不允许被删除
try { try {
const res = await removeAccess(data); await deleteAccess(data);
configContext.deleteAccess(res.id);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
notificationApi.error({ message: t("common.text.request_error"), description: <>{String(err)}</> }); notificationApi.error({ message: t("common.text.request_error"), description: <>{String(err)}</> });
@ -177,7 +179,7 @@ const AccessList = () => {
]} ]}
/> />
<Table<AccessType> <Table<AccessModel>
columns={tableColumns} columns={tableColumns}
dataSource={tableData} dataSource={tableData}
loading={loading} loading={loading}

View File

@ -8,7 +8,7 @@ import dayjs from "dayjs";
import { ClientResponseError } from "pocketbase"; import { ClientResponseError } from "pocketbase";
import CertificateDetailDrawer from "@/components/certificate/CertificateDetailDrawer"; import CertificateDetailDrawer from "@/components/certificate/CertificateDetailDrawer";
import { Certificate as CertificateType } from "@/domain/certificate"; import { CertificateModel } from "@/domain/certificate";
import { list as listCertificate, type CertificateListReq } from "@/repository/certificate"; import { list as listCertificate, type CertificateListReq } from "@/repository/certificate";
const CertificateList = () => { const CertificateList = () => {
@ -23,7 +23,7 @@ const CertificateList = () => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const tableColumns: TableProps<CertificateType>["columns"] = [ const tableColumns: TableProps<CertificateModel>["columns"] = [
{ {
key: "$index", key: "$index",
align: "center", align: "center",
@ -165,7 +165,7 @@ const CertificateList = () => {
), ),
}, },
]; ];
const [tableData, setTableData] = useState<CertificateType[]>([]); const [tableData, setTableData] = useState<CertificateModel[]>([]);
const [tableTotal, setTableTotal] = useState<number>(0); const [tableTotal, setTableTotal] = useState<number>(0);
const [filters, setFilters] = useState<Record<string, unknown>>(() => { const [filters, setFilters] = useState<Record<string, unknown>>(() => {
@ -177,7 +177,7 @@ const CertificateList = () => {
const [page, setPage] = useState<number>(() => parseInt(+searchParams.get("page")! + "") || 1); const [page, setPage] = useState<number>(() => parseInt(+searchParams.get("page")! + "") || 1);
const [pageSize, setPageSize] = useState<number>(() => parseInt(+searchParams.get("perPage")! + "") || 10); const [pageSize, setPageSize] = useState<number>(() => parseInt(+searchParams.get("perPage")! + "") || 10);
const [currentRecord, setCurrentRecord] = useState<CertificateType>(); const [currentRecord, setCurrentRecord] = useState<CertificateModel>();
const [drawerOpen, setDrawerOpen] = useState(false); const [drawerOpen, setDrawerOpen] = useState(false);
@ -210,7 +210,7 @@ const CertificateList = () => {
fetchTableData(); fetchTableData();
}, [fetchTableData]); }, [fetchTableData]);
const handleViewClick = (certificate: CertificateType) => { const handleViewClick = (certificate: CertificateModel) => {
setDrawerOpen(true); setDrawerOpen(true);
setCurrentRecord(certificate); setCurrentRecord(certificate);
}; };
@ -221,7 +221,7 @@ const CertificateList = () => {
<PageHeader title={t("certificate.page.title")} /> <PageHeader title={t("certificate.page.title")} />
<Table<CertificateType> <Table<CertificateModel>
columns={tableColumns} columns={tableColumns}
dataSource={tableData} dataSource={tableData}
loading={loading} loading={loading}

View File

@ -12,7 +12,7 @@ import {
} from "lucide-react"; } from "lucide-react";
import { ClientResponseError } from "pocketbase"; import { ClientResponseError } from "pocketbase";
import { type Statistic as StatisticType } from "@/domain/domain"; import { type Statistics } from "@/domain/statistics";
import { get as getStatistics } from "@/api/statistics"; import { get as getStatistics } from "@/api/statistics";
const Dashboard = () => { const Dashboard = () => {
@ -26,7 +26,7 @@ const Dashboard = () => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const statisticGridSpans = { const statisticsGridSpans = {
xs: { flex: "50%" }, xs: { flex: "50%" },
md: { flex: "50%" }, md: { flex: "50%" },
lg: { flex: "33.3333%" }, lg: { flex: "33.3333%" },
@ -34,15 +34,15 @@ const Dashboard = () => {
xxl: { flex: "20%" }, xxl: { flex: "20%" },
}; };
const [statistic, setStatistic] = useState<StatisticType>(); const [statistics, setStatistics] = useState<Statistics>();
const fetchStatistic = useCallback(async () => { const fetchStatistics = useCallback(async () => {
if (loading) return; if (loading) return;
setLoading(true); setLoading(true);
try { try {
const data = await getStatistics(); const data = await getStatistics();
setStatistic(data); setStatistics(data);
} catch (err) { } catch (err) {
if (err instanceof ClientResponseError && err.isAbort) { if (err instanceof ClientResponseError && err.isAbort) {
return; return;
@ -56,7 +56,7 @@ const Dashboard = () => {
}, []); }, []);
useEffect(() => { useEffect(() => {
fetchStatistic(); fetchStatistics();
}, []); }, []);
return ( return (
@ -66,47 +66,47 @@ const Dashboard = () => {
<PageHeader title={t("dashboard.page.title")} /> <PageHeader title={t("dashboard.page.title")} />
<Row className="justify-stretch" gutter={[16, 16]}> <Row className="justify-stretch" gutter={[16, 16]}>
<Col {...statisticGridSpans}> <Col {...statisticsGridSpans}>
<StatisticCard <StatisticCard
icon={<SquareSigmaIcon size={48} strokeWidth={1} color={themeToken.colorInfo} />} icon={<SquareSigmaIcon size={48} strokeWidth={1} color={themeToken.colorInfo} />}
label={t("dashboard.statistics.all_certificates")} label={t("dashboard.statistics.all_certificates")}
value={statistic?.certificateTotal ?? "-"} value={statistics?.certificateTotal ?? "-"}
suffix={t("dashboard.statistics.unit")} suffix={t("dashboard.statistics.unit")}
onClick={() => navigate("/certificates")} onClick={() => navigate("/certificates")}
/> />
</Col> </Col>
<Col {...statisticGridSpans}> <Col {...statisticsGridSpans}>
<StatisticCard <StatisticCard
icon={<CalendarClockIcon size={48} strokeWidth={1} color={themeToken.colorWarning} />} icon={<CalendarClockIcon size={48} strokeWidth={1} color={themeToken.colorWarning} />}
label={t("dashboard.statistics.expire_soon_certificates")} label={t("dashboard.statistics.expire_soon_certificates")}
value={statistic?.certificateExpireSoon ?? "-"} value={statistics?.certificateExpireSoon ?? "-"}
suffix={t("dashboard.statistics.unit")} suffix={t("dashboard.statistics.unit")}
onClick={() => navigate("/certificates?state=expireSoon")} onClick={() => navigate("/certificates?state=expireSoon")}
/> />
</Col> </Col>
<Col {...statisticGridSpans}> <Col {...statisticsGridSpans}>
<StatisticCard <StatisticCard
icon={<CalendarX2Icon size={48} strokeWidth={1} color={themeToken.colorError} />} icon={<CalendarX2Icon size={48} strokeWidth={1} color={themeToken.colorError} />}
label={t("dashboard.statistics.expired_certificates")} label={t("dashboard.statistics.expired_certificates")}
value={statistic?.certificateExpired ?? "-"} value={statistics?.certificateExpired ?? "-"}
suffix={t("dashboard.statistics.unit")} suffix={t("dashboard.statistics.unit")}
onClick={() => navigate("/certificates?state=expired")} onClick={() => navigate("/certificates?state=expired")}
/> />
</Col> </Col>
<Col {...statisticGridSpans}> <Col {...statisticsGridSpans}>
<StatisticCard <StatisticCard
icon={<WorkflowIcon size={48} strokeWidth={1} color={themeToken.colorInfo} />} icon={<WorkflowIcon size={48} strokeWidth={1} color={themeToken.colorInfo} />}
label={t("dashboard.statistics.all_workflows")} label={t("dashboard.statistics.all_workflows")}
value={statistic?.workflowTotal ?? "-"} value={statistics?.workflowTotal ?? "-"}
suffix={t("dashboard.statistics.unit")} suffix={t("dashboard.statistics.unit")}
onClick={() => navigate("/workflows")} onClick={() => navigate("/workflows")}
/> />
</Col> </Col>
<Col {...statisticGridSpans}> <Col {...statisticsGridSpans}>
<StatisticCard <StatisticCard
icon={<FolderCheckIcon size={48} strokeWidth={1} color={themeToken.colorSuccess} />} icon={<FolderCheckIcon size={48} strokeWidth={1} color={themeToken.colorSuccess} />}
label={t("dashboard.statistics.enabled_workflows")} label={t("dashboard.statistics.enabled_workflows")}
value={statistic?.workflowEnabled ?? "-"} value={statistics?.workflowEnabled ?? "-"}
suffix={t("dashboard.statistics.unit")} suffix={t("dashboard.statistics.unit")}
onClick={() => navigate("/workflows?state=enabled")} onClick={() => navigate("/workflows?state=enabled")}
/> />

View File

@ -12,14 +12,14 @@ import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { useToast } from "@/components/ui/use-toast"; import { useToast } from "@/components/ui/use-toast";
import { getErrMsg } from "@/utils/error"; import { getErrMsg } from "@/utils/error";
import { SSLProvider as SSLProviderType, SSLProviderSetting, Settings } from "@/domain/settings"; import { SSLProvider as SSLProviderType, SSLProviderSetting, SettingsModel } from "@/domain/settings";
import { get, save } from "@/repository/settings"; import { get, save } from "@/repository/settings";
import { produce } from "immer"; import { produce } from "immer";
type SSLProviderContext = { type SSLProviderContext = {
setting: Settings<SSLProviderSetting>; setting: SettingsModel<SSLProviderSetting>;
onSubmit: (data: Settings<SSLProviderSetting>) => void; onSubmit: (data: SettingsModel<SSLProviderSetting>) => void;
setConfig: (config: Settings<SSLProviderSetting>) => void; setConfig: (config: SettingsModel<SSLProviderSetting>) => void;
}; };
const Context = createContext({} as SSLProviderContext); const Context = createContext({} as SSLProviderContext);
@ -31,12 +31,12 @@ export const useSSLProviderContext = () => {
const SSLProvider = () => { const SSLProvider = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const [config, setConfig] = useState<Settings<SSLProviderSetting>>({ const [config, setConfig] = useState<SettingsModel<SSLProviderSetting>>({
content: { content: {
provider: "letsencrypt", provider: "letsencrypt",
config: {}, config: {},
}, },
} as Settings<SSLProviderSetting>); } as SettingsModel<SSLProviderSetting>);
const { toast } = useToast(); const { toast } = useToast();
@ -73,7 +73,7 @@ const SSLProvider = () => {
return ""; return "";
}; };
const onSubmit = async (data: Settings<SSLProviderSetting>) => { const onSubmit = async (data: SettingsModel<SSLProviderSetting>) => {
try { try {
console.log(data); console.log(data);
const resp = await save({ ...data }); const resp = await save({ ...data });

View File

@ -23,7 +23,7 @@ import { Filter as FilterIcon, Pencil as PencilIcon, Plus as PlusIcon, Trash2 as
import dayjs from "dayjs"; import dayjs from "dayjs";
import { ClientResponseError } from "pocketbase"; import { ClientResponseError } from "pocketbase";
import { Workflow as WorkflowType } from "@/domain/workflow"; import { WorkflowModel } from "@/domain/workflow";
import { list as listWorkflow, remove as removeWorkflow, save as saveWorkflow } from "@/repository/workflow"; import { list as listWorkflow, remove as removeWorkflow, save as saveWorkflow } from "@/repository/workflow";
const WorkflowList = () => { const WorkflowList = () => {
@ -39,7 +39,7 @@ const WorkflowList = () => {
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const tableColumns: TableProps<WorkflowType>["columns"] = [ const tableColumns: TableProps<WorkflowModel>["columns"] = [
{ {
key: "$index", key: "$index",
align: "center", align: "center",
@ -196,7 +196,7 @@ const WorkflowList = () => {
), ),
}, },
]; ];
const [tableData, setTableData] = useState<WorkflowType[]>([]); const [tableData, setTableData] = useState<WorkflowModel[]>([]);
const [tableTotal, setTableTotal] = useState<number>(0); const [tableTotal, setTableTotal] = useState<number>(0);
const [filters, setFilters] = useState<Record<string, unknown>>(() => { const [filters, setFilters] = useState<Record<string, unknown>>(() => {
@ -237,7 +237,7 @@ const WorkflowList = () => {
fetchTableData(); fetchTableData();
}, [fetchTableData]); }, [fetchTableData]);
const handleEnabledChange = async (workflow: WorkflowType) => { const handleEnabledChange = async (workflow: WorkflowModel) => {
try { try {
const resp = await saveWorkflow({ const resp = await saveWorkflow({
id: workflow.id, id: workflow.id,
@ -259,7 +259,7 @@ const WorkflowList = () => {
} }
}; };
const handleDeleteClick = (workflow: WorkflowType) => { const handleDeleteClick = (workflow: WorkflowModel) => {
modalApi.confirm({ modalApi.confirm({
title: t("workflow.action.delete"), title: t("workflow.action.delete"),
content: t("workflow.action.delete.confirm"), content: t("workflow.action.delete.confirm"),
@ -302,7 +302,7 @@ const WorkflowList = () => {
]} ]}
/> />
<Table<WorkflowType> <Table<WorkflowModel>
columns={tableColumns} columns={tableColumns}
dataSource={tableData} dataSource={tableData}
loading={loading} loading={loading}

View File

@ -1,61 +0,0 @@
import { createContext, useCallback, useContext, useEffect, useReducer, type ReactNode } from "react";
import { type Access as AccessType } from "@/domain/access";
import { list as listAccess } from "@/repository/access";
import { configReducer } from "./reducer";
export type ConfigData = {
accesses: AccessType[];
};
export type ConfigContext = {
config: ConfigData;
addAccess: (access: AccessType) => void;
updateAccess: (access: AccessType) => void;
deleteAccess: (id: string) => void;
};
const Context = createContext({} as ConfigContext);
export const useConfigContext = () => useContext(Context);
export const ConfigProvider = ({ children }: { children: ReactNode }) => {
const [config, dispatchConfig] = useReducer(configReducer, {
accesses: [],
});
useEffect(() => {
const featchData = async () => {
const data = await listAccess();
dispatchConfig({ type: "SET_ACCESSES", payload: data });
};
featchData();
}, []);
const deleteAccess = useCallback((id: string) => {
dispatchConfig({ type: "DELETE_ACCESS", payload: id });
}, []);
const addAccess = useCallback((access: AccessType) => {
dispatchConfig({ type: "ADD_ACCESS", payload: access });
}, []);
const updateAccess = useCallback((access: AccessType) => {
dispatchConfig({ type: "UPDATE_ACCESS", payload: access });
}, []);
return (
<Context.Provider
value={{
config: {
accesses: config.accesses,
},
addAccess,
updateAccess,
deleteAccess,
}}
>
{children}
</Context.Provider>
);
};

View File

@ -1,39 +0,0 @@
import { Access } from "@/domain/access";
import { ConfigData } from "./";
type Action =
| { type: "ADD_ACCESS"; payload: Access }
| { type: "DELETE_ACCESS"; payload: string }
| { type: "UPDATE_ACCESS"; payload: Access }
| { type: "SET_ACCESSES"; payload: Access[] };
export const configReducer = (state: ConfigData, action: Action): ConfigData => {
switch (action.type) {
case "SET_ACCESSES": {
return {
...state,
accesses: action.payload,
};
}
case "ADD_ACCESS": {
return {
...state,
accesses: [action.payload, ...state.accesses],
};
}
case "DELETE_ACCESS": {
return {
...state,
accesses: state.accesses.filter((access) => access.id !== action.payload),
};
}
case "UPDATE_ACCESS": {
return {
...state,
accesses: state.accesses.map((access) => (access.id === action.payload.id ? action.payload : access)),
};
}
default:
return state;
}
};

View File

@ -1,13 +1,13 @@
import { ReactNode, useContext, createContext, useEffect, useReducer, useCallback } from "react"; import { ReactNode, useContext, createContext, useEffect, useReducer, useCallback } from "react";
import { NotifyChannel, NotifyChannels, Settings } from "@/domain/settings"; import { NotifyChannel, NotifyChannels, SettingsModel } from "@/domain/settings";
import { get } from "@/repository/settings"; import { get } from "@/repository/settings";
import { notifyReducer } from "./reducer"; import { notifyReducer } from "./reducer";
export type NotifyContext = { export type NotifyContext = {
config: Settings<NotifyChannels>; config: SettingsModel<NotifyChannels>;
setChannel: (data: { channel: string; data: NotifyChannel }) => void; setChannel: (data: { channel: string; data: NotifyChannel }) => void;
setChannels: (data: Settings<NotifyChannels>) => void; setChannels: (data: SettingsModel<NotifyChannels>) => void;
initChannels: () => void; initChannels: () => void;
}; };
@ -45,7 +45,7 @@ export const NotifyProvider = ({ children }: NotifyProviderProps) => {
}); });
}, []); }, []);
const setChannels = useCallback((setting: Settings<NotifyChannels>) => { const setChannels = useCallback((setting: SettingsModel<NotifyChannels>) => {
dispatchNotify({ dispatchNotify({
type: "SET_CHANNELS", type: "SET_CHANNELS",
payload: setting, payload: setting,

View File

@ -1,4 +1,4 @@
import { NotifyChannel, NotifyChannels, Settings } from "@/domain/settings"; import { NotifyChannel, NotifyChannels, SettingsModel } from "@/domain/settings";
type Action = type Action =
| { | {
@ -10,10 +10,10 @@ type Action =
} }
| { | {
type: "SET_CHANNELS"; type: "SET_CHANNELS";
payload: Settings<NotifyChannels>; payload: SettingsModel<NotifyChannels>;
}; };
export const notifyReducer = (state: Settings<NotifyChannels>, action: Action) => { export const notifyReducer = (state: SettingsModel<NotifyChannels>, action: Action) => {
switch (action.type) { switch (action.type) {
case "SET_CHANNEL": { case "SET_CHANNEL": {
const channel = action.payload.channel; const channel = action.payload.channel;

View File

@ -1,24 +1,26 @@
import dayjs from "dayjs"; import dayjs from "dayjs";
import { type Access } from "@/domain/access"; import { type AccessModel } from "@/domain/access";
import { getPocketBase } from "./pocketbase"; import { getPocketBase } from "./pocketbase";
const COLLECTION_NAME = "access";
export const list = async () => { export const list = async () => {
return await getPocketBase().collection("access").getFullList<Access>({ return await getPocketBase().collection(COLLECTION_NAME).getFullList<AccessModel>({
sort: "-created", sort: "-created",
filter: "deleted = null", filter: "deleted=null",
}); });
}; };
export const save = async (record: Access) => { export const save = async (record: AccessModel) => {
if (record.id) { if (record.id) {
return await getPocketBase().collection("access").update(record.id, record); return await getPocketBase().collection(COLLECTION_NAME).update<AccessModel>(record.id, record);
} }
return await getPocketBase().collection("access").create(record); return await getPocketBase().collection(COLLECTION_NAME).create<AccessModel>(record);
}; };
export const remove = async (record: Access) => { export const remove = async (record: AccessModel) => {
record.deleted = dayjs.utc().format("YYYY-MM-DD HH:mm:ss"); record = { ...record, deleted: dayjs.utc().format("YYYY-MM-DD HH:mm:ss") };
return await getPocketBase().collection("access").update(record.id, record); await getPocketBase().collection(COLLECTION_NAME).update<AccessModel>(record.id, record);
}; };

View File

@ -1,9 +1,11 @@
import dayjs from "dayjs"; import dayjs from "dayjs";
import { type RecordListOptions } from "pocketbase"; import { type RecordListOptions } from "pocketbase";
import { type Certificate } from "@/domain/certificate"; import { type CertificateModel } from "@/domain/certificate";
import { getPocketBase } from "./pocketbase"; import { getPocketBase } from "./pocketbase";
const COLLECTION_NAME = "certificate";
export type CertificateListReq = { export type CertificateListReq = {
page?: number; page?: number;
perPage?: number; perPage?: number;
@ -31,5 +33,5 @@ export const list = async (req: CertificateListReq) => {
}); });
} }
return pb.collection("certificate").getList<Certificate>(page, perPage, options); return pb.collection(COLLECTION_NAME).getList<CertificateModel>(page, perPage, options);
}; };

View File

@ -1,22 +1,22 @@
import { Settings } from "@/domain/settings"; import { SettingsModel } from "@/domain/settings";
import { getPocketBase } from "./pocketbase"; import { getPocketBase } from "./pocketbase";
export const get = async <T>(name: string) => { export const get = async <T>(name: string) => {
try { try {
const resp = await getPocketBase().collection("settings").getFirstListItem<Settings<T>>(`name='${name}'`); const resp = await getPocketBase().collection("settings").getFirstListItem<SettingsModel<T>>(`name='${name}'`);
return resp; return resp;
} catch { } catch {
return { return {
name: name, name: name,
content: {} as T, content: {} as T,
} as Settings<T>; } as SettingsModel<T>;
} }
}; };
export const save = async <T>(record: Settings<T>) => { export const save = async <T>(record: SettingsModel<T>) => {
if (record.id) { if (record.id) {
return await getPocketBase().collection("settings").update<Settings<T>>(record.id, record); return await getPocketBase().collection("settings").update<SettingsModel<T>>(record.id, record);
} }
return await getPocketBase().collection("settings").create<Settings<T>>(record); return await getPocketBase().collection("settings").create<SettingsModel<T>>(record);
}; };

View File

@ -1,8 +1,10 @@
import { type RecordListOptions } from "pocketbase"; import { type RecordListOptions } from "pocketbase";
import { type Workflow, type WorkflowNode, type WorkflowRunLog } from "@/domain/workflow"; import { type WorkflowModel, type WorkflowNode, type WorkflowRunLog } from "@/domain/workflow";
import { getPocketBase } from "./pocketbase"; import { getPocketBase } from "./pocketbase";
const COLLECTION_NAME = "workflow";
export type WorkflowListReq = { export type WorkflowListReq = {
page?: number; page?: number;
perPage?: number; perPage?: number;
@ -20,25 +22,25 @@ export const list = async (req: WorkflowListReq) => {
options.filter = pb.filter("enabled={:enabled}", { enabled: req.enabled }); options.filter = pb.filter("enabled={:enabled}", { enabled: req.enabled });
} }
return await pb.collection("workflow").getList<Workflow>(page, perPage, options); return await pb.collection(COLLECTION_NAME).getList<WorkflowModel>(page, perPage, options);
}; };
export const get = async (id: string) => { export const get = async (id: string) => {
return await getPocketBase().collection("workflow").getOne<Workflow>(id); return await getPocketBase().collection(COLLECTION_NAME).getOne<WorkflowModel>(id);
}; };
export const save = async (record: Record<string, string | boolean | WorkflowNode>) => { export const save = async (record: Record<string, string | boolean | WorkflowNode>) => {
if (record.id) { if (record.id) {
return await getPocketBase() return await getPocketBase()
.collection("workflow") .collection(COLLECTION_NAME)
.update<Workflow>(record.id as string, record); .update<WorkflowModel>(record.id as string, record);
} }
return await getPocketBase().collection("workflow").create<Workflow>(record); return await getPocketBase().collection(COLLECTION_NAME).create<WorkflowModel>(record);
}; };
export const remove = async (record: Workflow) => { export const remove = async (record: WorkflowModel) => {
return await getPocketBase().collection("workflow").delete(record.id); await getPocketBase().collection(COLLECTION_NAME).delete(record.id);
}; };
type WorkflowLogsReq = { type WorkflowLogsReq = {

View File

@ -0,0 +1,58 @@
import { create } from "zustand";
import { produce } from "immer";
import { type AccessModel } from "@/domain/access";
import { list as listAccess, save as saveAccess, remove as removeAccess } from "@/repository/access";
export interface AccessState {
accesses: AccessModel[];
createAccess: (access: AccessModel) => void;
updateAccess: (access: AccessModel) => void;
deleteAccess: (access: AccessModel) => void;
fetchAccesses: () => Promise<void>;
}
export const useAccessStore = create<AccessState>((set) => {
return {
accesses: [],
createAccess: async (access) => {
access = await saveAccess(access);
set(
produce((state: AccessState) => {
state.accesses.unshift(access);
})
);
},
updateAccess: async (access) => {
access = await saveAccess(access);
set(
produce((state: AccessState) => {
const index = state.accesses.findIndex((e) => e.id === access.id);
state.accesses[index] = access;
})
);
},
deleteAccess: async (access) => {
await removeAccess(access);
set(
produce((state: AccessState) => {
state.accesses = state.accesses.filter((a) => a.id !== access.id);
})
);
},
fetchAccesses: async () => {
const accesses = await listAccess();
set({
accesses: accesses ?? [],
});
},
};
});

View File

@ -1,7 +1,7 @@
import { create } from "zustand"; import { create } from "zustand";
import { produce } from "immer"; import { produce } from "immer";
import { type EmailsSettingsContent, type Settings } from "@/domain/settings"; import { type EmailsSettingsContent, type SettingsModel } from "@/domain/settings";
import { get as getSettings, save as saveSettings } from "@/repository/settings"; import { get as getSettings, save as saveSettings } from "@/repository/settings";
export interface ContactState { export interface ContactState {
@ -11,7 +11,7 @@ export interface ContactState {
} }
export const useContactStore = create<ContactState>((set) => { export const useContactStore = create<ContactState>((set) => {
let settings: Settings<EmailsSettingsContent>; let settings: SettingsModel<EmailsSettingsContent>;
return { return {
emails: [], emails: [],

View File

@ -9,7 +9,7 @@ import {
removeBranch, removeBranch,
removeNode, removeNode,
updateNode, updateNode,
Workflow, WorkflowModel,
WorkflowBranchNode, WorkflowBranchNode,
WorkflowNode, WorkflowNode,
WorkflowNodeType, WorkflowNodeType,
@ -17,7 +17,7 @@ import {
import { get as getWorkflow, save as saveWorkflow } from "@/repository/workflow"; import { get as getWorkflow, save as saveWorkflow } from "@/repository/workflow";
export type WorkflowState = { export type WorkflowState = {
workflow: Workflow; workflow: WorkflowModel;
initialized: boolean; initialized: boolean;
updateNode: (node: WorkflowNode) => void; updateNode: (node: WorkflowNode) => void;
addNode: (node: WorkflowNode, preId: string) => void; addNode: (node: WorkflowNode, preId: string) => void;