From 7f366218828bb9973419f1ec3429dd14c56badae Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Thu, 2 Jan 2025 10:11:35 +0800 Subject: [PATCH] refactor(ui): clean code --- ui/src/components/access/AccessEditModal.tsx | 6 +++--- ui/src/components/access/AccessSelect.tsx | 5 +++-- ui/src/components/notification/NotifyChannels.tsx | 7 ++++--- ui/src/components/workflow/Node.tsx | 5 ++++- ui/src/components/workflow/node/ApplyNodeForm.tsx | 6 +++--- ui/src/components/workflow/node/NotifyNodeForm.tsx | 14 +++++++++----- ui/src/pages/accesses/AccessList.tsx | 7 +++++-- ui/src/pages/settings/SettingsNotification.tsx | 5 +++-- ui/src/stores/access/index.ts | 10 +++++----- ui/src/stores/contact/index.ts | 6 +++--- ui/src/stores/notify/index.ts | 6 +++--- 11 files changed, 45 insertions(+), 32 deletions(-) diff --git a/ui/src/components/access/AccessEditModal.tsx b/ui/src/components/access/AccessEditModal.tsx index e209b115..9caea4e5 100644 --- a/ui/src/components/access/AccessEditModal.tsx +++ b/ui/src/components/access/AccessEditModal.tsx @@ -4,8 +4,8 @@ import { useControllableValue } from "ahooks"; import { Modal, notification } from "antd"; import { type AccessModel } from "@/domain/access"; -import { useTriggerElement } from "@/hooks"; -import { useAccessStore } from "@/stores/access"; +import { useTriggerElement, useZustandShallowSelector } from "@/hooks"; +import { useAccessesStore } from "@/stores/access"; import { getErrMsg } from "@/utils/error"; import AccessEditForm, { type AccessEditFormInstance, type AccessEditFormProps } from "./AccessEditForm"; @@ -25,7 +25,7 @@ const AccessEditModal = ({ data, loading, trigger, preset, onSubmit, ...props }: const [notificationApi, NotificationContextHolder] = notification.useNotification(); - const { createAccess, updateAccess } = useAccessStore(); + const { createAccess, updateAccess } = useAccessesStore(useZustandShallowSelector(["createAccess", "updateAccess"])); const [open, setOpen] = useControllableValue(props, { valuePropName: "open", diff --git a/ui/src/components/access/AccessSelect.tsx b/ui/src/components/access/AccessSelect.tsx index cd072b01..07191582 100644 --- a/ui/src/components/access/AccessSelect.tsx +++ b/ui/src/components/access/AccessSelect.tsx @@ -3,7 +3,8 @@ import { Avatar, Select, Space, Typography, type SelectProps } from "antd"; import { type AccessModel } from "@/domain/access"; import { accessProvidersMap } from "@/domain/provider"; -import { useAccessStore } from "@/stores/access"; +import { useZustandShallowSelector } from "@/hooks"; +import { useAccessesStore } from "@/stores/access"; export type AccessTypeSelectProps = Omit< SelectProps, @@ -13,7 +14,7 @@ export type AccessTypeSelectProps = Omit< }; const AccessSelect = ({ filter, ...props }: AccessTypeSelectProps) => { - const { accesses, loadedAtOnce, fetchAccesses } = useAccessStore(); + const { accesses, loadedAtOnce, fetchAccesses } = useAccessesStore(useZustandShallowSelector(["accesses", "loadedAtOnce", "fetchAccesses"])); useEffect(() => { fetchAccesses(); }, [fetchAccesses]); diff --git a/ui/src/components/notification/NotifyChannels.tsx b/ui/src/components/notification/NotifyChannels.tsx index b10f179e..7e73a394 100644 --- a/ui/src/components/notification/NotifyChannels.tsx +++ b/ui/src/components/notification/NotifyChannels.tsx @@ -5,7 +5,8 @@ import { Button, Collapse, message, notification, Skeleton, Space, Switch, type import Show from "@/components/Show"; import { notifyChannelsMap } from "@/domain/settings"; -import { useNotifyChannelStore } from "@/stores/notify"; +import { useZustandShallowSelector } from "@/hooks"; +import { useNotifyChannelsStore } from "@/stores/notify"; import { getErrMsg } from "@/utils/error"; import NotifyChannelEditForm, { type NotifyChannelEditFormInstance } from "./NotifyChannelEditForm"; @@ -23,7 +24,7 @@ const NotifyChannel = ({ className, style, channel }: NotifyChannelProps) => { const [messageApi, MessageContextHolder] = message.useMessage(); const [notificationApi, NotificationContextHolder] = notification.useNotification(); - const { channels, setChannel } = useNotifyChannelStore(); + const { channels, setChannel } = useNotifyChannelsStore(useZustandShallowSelector(["channels", "setChannel"])); const channelConfig = useDeepCompareMemo(() => channels[channel], [channels, channel]); const channelFormRef = useRef(null); @@ -78,7 +79,7 @@ export type NotifyChannelsProps = { const NotifyChannels = ({ className, classNames, style, styles }: NotifyChannelsProps) => { const { t, i18n } = useTranslation(); - const { channels, loadedAtOnce, setChannel, fetchChannels } = useNotifyChannelStore(); + const { channels, loadedAtOnce, setChannel, fetchChannels } = useNotifyChannelsStore(); useEffect(() => { fetchChannels(); }, [fetchChannels]); diff --git a/ui/src/components/workflow/Node.tsx b/ui/src/components/workflow/Node.tsx index d8dfce78..0e98b0e4 100644 --- a/ui/src/components/workflow/Node.tsx +++ b/ui/src/components/workflow/Node.tsx @@ -35,7 +35,7 @@ const Node = ({ data }: NodeProps) => { updateNode( produce(data, (draft) => { - draft.name = e.target.innerText; + draft.name = newName; }) ); }; @@ -66,8 +66,10 @@ const Node = ({ data }: NodeProps) => { ); + case WorkflowNodeType.Apply: return
{data.config?.domain as string}
; + case WorkflowNodeType.Deploy: { const provider = deployProvidersMap.get(data.config?.providerType as string); return ( @@ -77,6 +79,7 @@ const Node = ({ data }: NodeProps) => { ); } + case WorkflowNodeType.Notify: { const channelLabel = notifyChannelsMap.get(data.config?.channel as string); return ( diff --git a/ui/src/components/workflow/node/ApplyNodeForm.tsx b/ui/src/components/workflow/node/ApplyNodeForm.tsx index 2c115e5a..02bbd6c7 100644 --- a/ui/src/components/workflow/node/ApplyNodeForm.tsx +++ b/ui/src/components/workflow/node/ApplyNodeForm.tsx @@ -14,7 +14,7 @@ import MultipleInput from "@/components/core/MultipleInput"; import { ACCESS_USAGES, accessProvidersMap } from "@/domain/provider"; import { type WorkflowNode, type WorkflowNodeConfig } from "@/domain/workflow"; import { useAntdForm, useZustandShallowSelector } from "@/hooks"; -import { useContactStore } from "@/stores/contact"; +import { useContactEmailsStore } from "@/stores/contact"; import { useWorkflowStore } from "@/stores/workflow"; import { validDomainName, validIPv4Address, validIPv6Address } from "@/utils/validators"; import { usePanel } from "../PanelProvider"; @@ -38,7 +38,7 @@ const initFormModel = (): WorkflowNodeConfig => { const ApplyNodeForm = ({ data }: ApplyNodeFormProps) => { const { t } = useTranslation(); - const { addEmail } = useContactStore(); + const { addEmail } = useContactEmailsStore(useZustandShallowSelector("addEmail")); const { updateNode } = useWorkflowStore(useZustandShallowSelector(["updateNode"])); const { hidePanel } = usePanel(); @@ -277,7 +277,7 @@ const FormFieldEmailSelect = ({ value?: string; onChange?: (value: string) => void; }) => { - const { emails, fetchEmails } = useContactStore(); + const { emails, fetchEmails } = useContactEmailsStore(); const emailsToOptions = useCallback(() => emails.map((email) => ({ label: email, value: email })), [emails]); useEffect(() => { fetchEmails(); diff --git a/ui/src/components/workflow/node/NotifyNodeForm.tsx b/ui/src/components/workflow/node/NotifyNodeForm.tsx index bbe0567b..fc23277a 100644 --- a/ui/src/components/workflow/node/NotifyNodeForm.tsx +++ b/ui/src/components/workflow/node/NotifyNodeForm.tsx @@ -10,7 +10,7 @@ import { z } from "zod"; import { notifyChannelsMap } from "@/domain/settings"; import { type WorkflowNode, type WorkflowNodeConfig } from "@/domain/workflow"; import { useAntdForm, useZustandShallowSelector } from "@/hooks"; -import { useNotifyChannelStore } from "@/stores/notify"; +import { useNotifyChannelsStore } from "@/stores/notify"; import { useWorkflowStore } from "@/stores/workflow"; import { usePanel } from "../PanelProvider"; @@ -28,14 +28,18 @@ const initFormModel = (): WorkflowNodeConfig => { const NotifyNodeForm = ({ data }: NotifyNodeFormProps) => { const { t } = useTranslation(); - const { updateNode } = useWorkflowStore(useZustandShallowSelector(["updateNode"])); - const { hidePanel } = usePanel(); - - const { channels, loadedAtOnce: channelsLoadedAtOnce, fetchChannels } = useNotifyChannelStore(); + const { + channels, + loadedAtOnce: channelsLoadedAtOnce, + fetchChannels, + } = useNotifyChannelsStore(useZustandShallowSelector(["channels", "loadedAtOnce", "fetchChannels"])); useEffect(() => { fetchChannels(); }, [fetchChannels]); + const { updateNode } = useWorkflowStore(useZustandShallowSelector(["updateNode"])); + const { hidePanel } = usePanel(); + const formSchema = z.object({ subject: z .string({ message: t("workflow_node.notify.form.subject.placeholder") }) diff --git a/ui/src/pages/accesses/AccessList.tsx b/ui/src/pages/accesses/AccessList.tsx index 9276b8e6..e55e78c1 100644 --- a/ui/src/pages/accesses/AccessList.tsx +++ b/ui/src/pages/accesses/AccessList.tsx @@ -15,7 +15,8 @@ import { ClientResponseError } from "pocketbase"; import AccessEditModal from "@/components/access/AccessEditModal"; import { type AccessModel } from "@/domain/access"; import { accessProvidersMap } from "@/domain/provider"; -import { useAccessStore } from "@/stores/access"; +import { useZustandShallowSelector } from "@/hooks"; +import { useAccessesStore } from "@/stores/access"; import { getErrMsg } from "@/utils/error"; const AccessList = () => { @@ -24,7 +25,9 @@ const AccessList = () => { const [modalApi, ModelContextHolder] = Modal.useModal(); const [notificationApi, NotificationContextHolder] = notification.useNotification(); - const { accesses, loadedAtOnce, fetchAccesses, deleteAccess } = useAccessStore(); + const { accesses, loadedAtOnce, fetchAccesses, deleteAccess } = useAccessesStore( + useZustandShallowSelector(["accesses", "loadedAtOnce", "fetchAccesses", "deleteAccess"]) + ); const tableColumns: TableProps["columns"] = [ { diff --git a/ui/src/pages/settings/SettingsNotification.tsx b/ui/src/pages/settings/SettingsNotification.tsx index 7ac8aa31..950149e2 100644 --- a/ui/src/pages/settings/SettingsNotification.tsx +++ b/ui/src/pages/settings/SettingsNotification.tsx @@ -3,12 +3,13 @@ import { Card, Divider } from "antd"; import NotifyChannels from "@/components/notification/NotifyChannels"; import NotifyTemplate from "@/components/notification/NotifyTemplate"; -import { useNotifyChannelStore } from "@/stores/notify"; +import { useZustandShallowSelector } from "@/hooks"; +import { useNotifyChannelsStore } from "@/stores/notify"; const SettingsNotification = () => { const { t } = useTranslation(); - const { loadedAtOnce } = useNotifyChannelStore(); + const { loadedAtOnce } = useNotifyChannelsStore(useZustandShallowSelector(["loadedAtOnce"])); return (
diff --git a/ui/src/stores/access/index.ts b/ui/src/stores/access/index.ts index ea94ecef..d37b1566 100644 --- a/ui/src/stores/access/index.ts +++ b/ui/src/stores/access/index.ts @@ -4,7 +4,7 @@ import { create } from "zustand"; import { type AccessModel } from "@/domain/access"; import { list as listAccess, save as saveAccess, remove as removeAccess } from "@/repository/access"; -export interface AccessState { +export interface AccessesState { accesses: AccessModel[]; loading: boolean; loadedAtOnce: boolean; @@ -15,7 +15,7 @@ export interface AccessState { deleteAccess: (access: MaybeModelRecordWithId) => Promise; } -export const useAccessStore = create((set) => { +export const useAccessesStore = create((set) => { let fetcher: Promise | null = null; // 防止多次重复请求 return { @@ -39,7 +39,7 @@ export const useAccessStore = create((set) => { createAccess: async (access) => { const record = await saveAccess(access); set( - produce((state: AccessState) => { + produce((state: AccessesState) => { state.accesses.unshift(record); }) ); @@ -50,7 +50,7 @@ export const useAccessStore = create((set) => { updateAccess: async (access) => { const record = await saveAccess(access); set( - produce((state: AccessState) => { + produce((state: AccessesState) => { const index = state.accesses.findIndex((e) => e.id === record.id); if (index !== -1) { state.accesses[index] = record; @@ -64,7 +64,7 @@ export const useAccessStore = create((set) => { deleteAccess: async (access) => { await removeAccess(access); set( - produce((state: AccessState) => { + produce((state: AccessesState) => { state.accesses = state.accesses.filter((a) => a.id !== access.id); }) ); diff --git a/ui/src/stores/contact/index.ts b/ui/src/stores/contact/index.ts index 5f7a68de..db4bb33f 100644 --- a/ui/src/stores/contact/index.ts +++ b/ui/src/stores/contact/index.ts @@ -4,7 +4,7 @@ import { create } from "zustand"; import { SETTINGS_NAMES, type EmailsSettingsContent, type SettingsModel } from "@/domain/settings"; import { get as getSettings, save as saveSettings } from "@/repository/settings"; -export interface ContactState { +export interface ContactEmailsState { emails: string[]; loading: boolean; loadedAtOnce: boolean; @@ -15,7 +15,7 @@ export interface ContactState { removeEmail: (email: string) => Promise; } -export const useContactStore = create((set, get) => { +export const useContactEmailsStore = create((set, get) => { let fetcher: Promise> | null = null; // 防止多次重复请求 let settings: SettingsModel; // 记录当前设置的其他字段,保存回数据库时用 @@ -48,7 +48,7 @@ export const useContactStore = create((set, get) => { }); set( - produce((state: ContactState) => { + produce((state: ContactEmailsState) => { state.emails = settings.content.emails?.sort() ?? []; state.loadedAtOnce = true; }) diff --git a/ui/src/stores/notify/index.ts b/ui/src/stores/notify/index.ts index 80a6602a..843c0cf0 100644 --- a/ui/src/stores/notify/index.ts +++ b/ui/src/stores/notify/index.ts @@ -4,7 +4,7 @@ import { create } from "zustand"; import { SETTINGS_NAMES, type NotifyChannelsSettingsContent, type SettingsModel } from "@/domain/settings"; import { get as getSettings, save as saveSettings } from "@/repository/settings"; -export interface NotifyChannelState { +export interface NotifyChannelsState { channels: NotifyChannelsSettingsContent; loading: boolean; loadedAtOnce: boolean; @@ -14,7 +14,7 @@ export interface NotifyChannelState { setChannels: (channels: NotifyChannelsSettingsContent) => Promise; } -export const useNotifyChannelStore = create((set, get) => { +export const useNotifyChannelsStore = create((set, get) => { let fetcher: Promise> | null = null; // 防止多次重复请求 let settings: SettingsModel; // 记录当前设置的其他字段,保存回数据库时用 @@ -54,7 +54,7 @@ export const useNotifyChannelStore = create((set, get) => { }); set( - produce((state: NotifyChannelState) => { + produce((state: NotifyChannelsState) => { state.channels = settings.content; state.loadedAtOnce = true; })