From 70e6920288a3000b8a6b18a8b5b4fc8921b3ba9c Mon Sep 17 00:00:00 2001 From: Fu Diwei Date: Mon, 16 Dec 2024 13:37:10 +0800 Subject: [PATCH] refactor(ui): clean code --- ui/package-lock.json | 23 ------- ui/package.json | 1 - .../access/AccessProviderSelect.tsx | 48 -------------- ui/src/components/access/AccessTypeSelect.tsx | 66 +++++++++++++++++++ .../certificate/CertificateDetail.tsx | 6 +- .../certificate/CertificateDetailDrawer.tsx | 38 +++++++++-- .../components/certimate/AccessEditDialog.tsx | 6 +- ui/src/components/ui/alert.tsx | 36 ---------- ui/src/components/ui/separator.tsx | 19 ------ ui/src/i18n/locales/en/nls.access.json | 6 +- ui/src/i18n/locales/zh/nls.access.json | 2 + ui/src/pages/ConsoleLayout.tsx | 8 +-- ui/src/pages/accesses/AccessList.tsx | 2 +- ui/src/pages/certificates/CertificateList.tsx | 35 +++------- ui/src/pages/login/Login.tsx | 2 +- 15 files changed, 126 insertions(+), 172 deletions(-) delete mode 100644 ui/src/components/access/AccessProviderSelect.tsx create mode 100644 ui/src/components/access/AccessTypeSelect.tsx delete mode 100644 ui/src/components/ui/alert.tsx delete mode 100644 ui/src/components/ui/separator.tsx diff --git a/ui/package-lock.json b/ui/package-lock.json index f4fd3895..e2b71062 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -19,7 +19,6 @@ "@radix-ui/react-radio-group": "^1.2.0", "@radix-ui/react-scroll-area": "^1.1.0", "@radix-ui/react-select": "^2.1.1", - "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-switch": "^1.1.0", "@radix-ui/react-tabs": "^1.1.0", @@ -2559,28 +2558,6 @@ } } }, - "node_modules/@radix-ui/react-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/@radix-ui/react-separator/-/react-separator-1.1.0.tgz", - "integrity": "sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA==", - "dependencies": { - "@radix-ui/react-primitive": "2.0.0" - }, - "peerDependencies": { - "@types/react": "*", - "@types/react-dom": "*", - "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", - "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - }, - "@types/react-dom": { - "optional": true - } - } - }, "node_modules/@radix-ui/react-slot": { "version": "1.1.0", "resolved": "https://registry.npmmirror.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", diff --git a/ui/package.json b/ui/package.json index a08f888e..a7963f08 100644 --- a/ui/package.json +++ b/ui/package.json @@ -21,7 +21,6 @@ "@radix-ui/react-radio-group": "^1.2.0", "@radix-ui/react-scroll-area": "^1.1.0", "@radix-ui/react-select": "^2.1.1", - "@radix-ui/react-separator": "^1.1.0", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-switch": "^1.1.0", "@radix-ui/react-tabs": "^1.1.0", diff --git a/ui/src/components/access/AccessProviderSelect.tsx b/ui/src/components/access/AccessProviderSelect.tsx deleted file mode 100644 index a7186ea9..00000000 --- a/ui/src/components/access/AccessProviderSelect.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import React from "react"; -import { useTranslation } from "react-i18next"; -import { Avatar, Select, Space, Typography, type SelectProps } from "antd"; - -import { accessProvidersMap } from "@/domain/access"; - -export type AccessProviderSelectProps = Omit & { - className?: string; -}; - -const AccessProviderSelect = React.memo((props: AccessProviderSelectProps) => { - const { t } = useTranslation(); - - const options = Array.from(accessProvidersMap.values()).map((item) => ({ - key: item.type, - value: item.type, - label: t(item.name), - })); - - return ( - { + if (label) { + return ( + + + {label} + + ); + } + + return {props.placeholder}; + }} + options={options} + optionFilterProp={undefined} + optionLabelProp={undefined} + optionRender={(option) => ( +
+ + + {t(accessProvidersMap.get(option.data.value)?.name ?? "")} + +
+ {accessProvidersMap.get(option.data.value)?.usage === "apply" && ( + <> + {t("access.props.provider.usage.dns")} + + )} + {accessProvidersMap.get(option.data.value)?.usage === "deploy" && ( + <> + {t("access.props.provider.usage.host")} + + )} + {accessProvidersMap.get(option.data.value)?.usage === "all" && ( + <> + {t("access.props.provider.usage.dns")} + {t("access.props.provider.usage.host")} + + )} +
+
+ )} + /> + ); +}); + +export default AccessTypeSelect; diff --git a/ui/src/components/certificate/CertificateDetail.tsx b/ui/src/components/certificate/CertificateDetail.tsx index 05b492d3..684784cb 100644 --- a/ui/src/components/certificate/CertificateDetail.tsx +++ b/ui/src/components/certificate/CertificateDetail.tsx @@ -8,10 +8,12 @@ import { type CertificateModel } from "@/domain/certificate"; import { saveFiles2Zip } from "@/utils/file"; type CertificateDetailProps = { + className?: string; + style?: React.CSSProperties; data: CertificateModel; }; -const CertificateDetail = ({ data }: CertificateDetailProps) => { +const CertificateDetail = ({ data, ...props }: CertificateDetailProps) => { const { t } = useTranslation(); const [messageApi, MessageContextHolder] = message.useMessage(); @@ -33,7 +35,7 @@ const CertificateDetail = ({ data }: CertificateDetailProps) => { }; return ( -
+
{MessageContextHolder}
diff --git a/ui/src/components/certificate/CertificateDetailDrawer.tsx b/ui/src/components/certificate/CertificateDetailDrawer.tsx index 6aefd7d6..4108cbee 100644 --- a/ui/src/components/certificate/CertificateDetailDrawer.tsx +++ b/ui/src/components/certificate/CertificateDetailDrawer.tsx @@ -1,4 +1,5 @@ -import { useEffect, useState } from "react"; +import { cloneElement, useEffect, useMemo, useState } from "react"; +import { useControllableValue } from "ahooks"; import { Drawer } from "antd"; import { type CertificateModel } from "@/domain/certificate"; @@ -7,19 +8,44 @@ import CertificateDetail from "./CertificateDetail"; type CertificateDetailDrawerProps = { data?: CertificateModel; open?: boolean; - onClose?: () => void; + trigger?: React.ReactElement; + onOpenChange?: (open: boolean) => void; }; -const CertificateDetailDrawer = ({ data, open, onClose }: CertificateDetailDrawerProps) => { +const CertificateDetailDrawer = ({ data, trigger, ...props }: CertificateDetailDrawerProps) => { + const [open, setOpen] = useControllableValue(props, { + valuePropName: "open", + defaultValuePropName: "defaultOpen", + trigger: "onOpenChange", + }); + const [loading, setLoading] = useState(true); useEffect(() => { setLoading(data == null); }, [data]); + const triggerDom = useMemo(() => { + if (!trigger) { + return null; + } + + return cloneElement(trigger, { + ...trigger.props, + onClick: () => { + setOpen(true); + trigger.props?.onClick?.(); + }, + }); + }, [trigger, setOpen]); + return ( - - {data ? : <>} - + <> + {triggerDom} + + setOpen(false)}> + {data ? : <>} + + ); }; diff --git a/ui/src/components/certimate/AccessEditDialog.tsx b/ui/src/components/certimate/AccessEditDialog.tsx index c4ac874d..36de6fce 100644 --- a/ui/src/components/certimate/AccessEditDialog.tsx +++ b/ui/src/components/certimate/AccessEditDialog.tsx @@ -5,7 +5,8 @@ import { cn } from "@/components/ui/utils"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { Label } from "@/components/ui/label"; import { ScrollArea } from "@/components/ui/scroll-area"; -import AccessProviderSelect from "@/components/access/AccessProviderSelect"; +import AccessEditForm from "@/components/access/AccessEditForm"; +import AccessTypeSelect from "@/components/access/AccessTypeSelect"; import AccessAliyunForm from "./AccessAliyunForm"; import AccessTencentForm from "./AccessTencentForm"; import AccessHuaweiCloudForm from "./AccessHuaweicloudForm"; @@ -281,10 +282,11 @@ const AccessEditDialog = ({ trigger, op, data, className, outConfigType }: Acces +
- svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", - { - variants: { - variant: { - default: "bg-background text-foreground", - destructive: "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", - }, - }, - defaultVariants: { - variant: "default", - }, - } -); - -const Alert = React.forwardRef & VariantProps>( - ({ className, variant, ...props }, ref) =>
-); -Alert.displayName = "Alert"; - -const AlertTitle = React.forwardRef>(({ className, ...props }, ref) => ( -
-)); -AlertTitle.displayName = "AlertTitle"; - -const AlertDescription = React.forwardRef>(({ className, ...props }, ref) => ( -
-)); -AlertDescription.displayName = "AlertDescription"; - -export { Alert, AlertTitle, AlertDescription }; diff --git a/ui/src/components/ui/separator.tsx b/ui/src/components/ui/separator.tsx deleted file mode 100644 index 57070755..00000000 --- a/ui/src/components/ui/separator.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import * as React from "react"; -import * as SeparatorPrimitive from "@radix-ui/react-separator"; - -import { cn } from "./utils"; - -const Separator = React.forwardRef, React.ComponentPropsWithoutRef>( - ({ className, orientation = "horizontal", decorative = true, ...props }, ref) => ( - - ) -); -Separator.displayName = SeparatorPrimitive.Root.displayName; - -export { Separator }; diff --git a/ui/src/i18n/locales/en/nls.access.json b/ui/src/i18n/locales/en/nls.access.json index e36fba19..8fa38ae0 100644 --- a/ui/src/i18n/locales/en/nls.access.json +++ b/ui/src/i18n/locales/en/nls.access.json @@ -11,15 +11,17 @@ "access.props.name": "Name", "access.props.provider": "Provider", + "access.props.provider.usage.dns": "DNS Provider", + "access.props.provider.usage.host": "Hos Provider", "access.props.created_at": "Created At", "access.props.updated_at": "Updated At", + "access.authorization.form.name.label": "Name", + "access.authorization.form.name.placeholder": "Please enter authorization name", "access.authorization.form.type.label": "Provider", "access.authorization.form.type.placeholder": "Please select a provider", "access.authorization.form.type.search.notfound": "Provider not found", "access.authorization.form.type.list": "Authorization List", - "access.authorization.form.name.label": "Name", - "access.authorization.form.name.placeholder": "Please enter authorization name", "access.authorization.form.config.label": "Configuration Type", "access.authorization.form.region.label": "Region", "access.authorization.form.region.placeholder": "Please enter Region", diff --git a/ui/src/i18n/locales/zh/nls.access.json b/ui/src/i18n/locales/zh/nls.access.json index 3c27acaf..068f80a1 100644 --- a/ui/src/i18n/locales/zh/nls.access.json +++ b/ui/src/i18n/locales/zh/nls.access.json @@ -11,6 +11,8 @@ "access.props.name": "名称", "access.props.provider": "服务商", + "access.props.provider.usage.dns": "DNS 服务商", + "access.props.provider.usage.host": "主机服务商", "access.props.created_at": "创建时间", "access.props.updated_at": "更新时间", diff --git a/ui/src/pages/ConsoleLayout.tsx b/ui/src/pages/ConsoleLayout.tsx index c21ab1bf..9929aa5c 100644 --- a/ui/src/pages/ConsoleLayout.tsx +++ b/ui/src/pages/ConsoleLayout.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import { memo, useEffect, useState } from "react"; import { Link, Navigate, Outlet, useLocation, useNavigate } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { Button, Drawer, Dropdown, Layout, Menu, Tooltip, theme, type ButtonProps, type MenuProps } from "antd"; @@ -109,7 +109,7 @@ const ConsoleLayout = () => { ); }; -const SiderMenu = React.memo(({ onSelect }: { onSelect?: (key: string) => void }) => { +const SiderMenu = memo(({ onSelect }: { onSelect?: (key: string) => void }) => { const location = useLocation(); const navigate = useNavigate(); @@ -179,7 +179,7 @@ const SiderMenu = React.memo(({ onSelect }: { onSelect?: (key: string) => void } ); }); -const ThemeToggleButton = React.memo(({ size }: { size?: ButtonProps["size"] }) => { +const ThemeToggleButton = memo(({ size }: { size?: ButtonProps["size"] }) => { const { t } = useTranslation(); const { theme, setThemeMode } = useTheme(); @@ -206,7 +206,7 @@ const ThemeToggleButton = React.memo(({ size }: { size?: ButtonProps["size"] }) ); }); -const LocaleToggleButton = React.memo(({ size }: { size?: ButtonProps["size"] }) => { +const LocaleToggleButton = memo(({ size }: { size?: ButtonProps["size"] }) => { const { i18n } = useTranslation(); const items: Required["items"] = Object.keys(i18n.store.data).map((key) => { diff --git a/ui/src/pages/accesses/AccessList.tsx b/ui/src/pages/accesses/AccessList.tsx index df915bcb..e29f357b 100644 --- a/ui/src/pages/accesses/AccessList.tsx +++ b/ui/src/pages/accesses/AccessList.tsx @@ -40,7 +40,7 @@ const AccessList = () => { ellipsis: true, render: (_, record) => { return ( - + {t(accessProvidersMap.get(record.configType)?.name ?? "")} diff --git a/ui/src/pages/certificates/CertificateList.tsx b/ui/src/pages/certificates/CertificateList.tsx index aa744fff..5e533675 100644 --- a/ui/src/pages/certificates/CertificateList.tsx +++ b/ui/src/pages/certificates/CertificateList.tsx @@ -152,15 +152,14 @@ const CertificateList = () => { width: 120, render: (_, record) => ( - -