mirror of
https://github.com/usual2970/certimate.git
synced 2025-06-22 12:20:04 +00:00
refactor(ui): clean code
This commit is contained in:
parent
b5739c663d
commit
70e6920288
23
ui/package-lock.json
generated
23
ui/package-lock.json
generated
@ -19,7 +19,6 @@
|
|||||||
"@radix-ui/react-radio-group": "^1.2.0",
|
"@radix-ui/react-radio-group": "^1.2.0",
|
||||||
"@radix-ui/react-scroll-area": "^1.1.0",
|
"@radix-ui/react-scroll-area": "^1.1.0",
|
||||||
"@radix-ui/react-select": "^2.1.1",
|
"@radix-ui/react-select": "^2.1.1",
|
||||||
"@radix-ui/react-separator": "^1.1.0",
|
|
||||||
"@radix-ui/react-slot": "^1.1.0",
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
"@radix-ui/react-switch": "^1.1.0",
|
"@radix-ui/react-switch": "^1.1.0",
|
||||||
"@radix-ui/react-tabs": "^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": {
|
"node_modules/@radix-ui/react-slot": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
"@radix-ui/react-radio-group": "^1.2.0",
|
"@radix-ui/react-radio-group": "^1.2.0",
|
||||||
"@radix-ui/react-scroll-area": "^1.1.0",
|
"@radix-ui/react-scroll-area": "^1.1.0",
|
||||||
"@radix-ui/react-select": "^2.1.1",
|
"@radix-ui/react-select": "^2.1.1",
|
||||||
"@radix-ui/react-separator": "^1.1.0",
|
|
||||||
"@radix-ui/react-slot": "^1.1.0",
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
"@radix-ui/react-switch": "^1.1.0",
|
"@radix-ui/react-switch": "^1.1.0",
|
||||||
"@radix-ui/react-tabs": "^1.1.0",
|
"@radix-ui/react-tabs": "^1.1.0",
|
||||||
|
@ -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<SelectProps, "options" | "optionFilterProp" | "optionLabelProp" | "optionRender"> & {
|
|
||||||
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 (
|
|
||||||
<Select
|
|
||||||
{...props}
|
|
||||||
labelRender={({ label, value }) => {
|
|
||||||
if (label) {
|
|
||||||
return (
|
|
||||||
<Space className="max-w-full truncate" align="center" size={4}>
|
|
||||||
<Avatar src={accessProvidersMap.get(String(value))?.icon} size="small" />
|
|
||||||
{label}
|
|
||||||
</Space>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <Typography.Text type="secondary">{props.placeholder}</Typography.Text>;
|
|
||||||
}}
|
|
||||||
options={options}
|
|
||||||
optionFilterProp={undefined}
|
|
||||||
optionLabelProp={undefined}
|
|
||||||
optionRender={(option) => (
|
|
||||||
<Space className="max-w-full truncate" align="center" size={4}>
|
|
||||||
<Avatar src={accessProvidersMap.get(option.data.value)?.icon} size="small" />
|
|
||||||
<Typography.Text ellipsis>{t(accessProvidersMap.get(option.data.value)?.name ?? "")}</Typography.Text>
|
|
||||||
</Space>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default AccessProviderSelect;
|
|
66
ui/src/components/access/AccessTypeSelect.tsx
Normal file
66
ui/src/components/access/AccessTypeSelect.tsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { memo } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Avatar, Select, Space, Tag, Typography, type SelectProps } from "antd";
|
||||||
|
|
||||||
|
import { accessProvidersMap } from "@/domain/access";
|
||||||
|
|
||||||
|
export type AccessTypeSelectProps = Omit<SelectProps, "labelRender" | "options" | "optionFilterProp" | "optionLabelProp" | "optionRender">;
|
||||||
|
|
||||||
|
const AccessTypeSelect = memo((props: AccessTypeSelectProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const options = Array.from(accessProvidersMap.values()).map((item) => ({
|
||||||
|
key: item.type,
|
||||||
|
value: item.type,
|
||||||
|
label: t(item.name),
|
||||||
|
}));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
{...props}
|
||||||
|
labelRender={({ label, value }) => {
|
||||||
|
if (label) {
|
||||||
|
return (
|
||||||
|
<Space className="max-w-full truncate" size={4}>
|
||||||
|
<Avatar src={accessProvidersMap.get(String(value))?.icon} size="small" />
|
||||||
|
{label}
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Typography.Text type="secondary">{props.placeholder}</Typography.Text>;
|
||||||
|
}}
|
||||||
|
options={options}
|
||||||
|
optionFilterProp={undefined}
|
||||||
|
optionLabelProp={undefined}
|
||||||
|
optionRender={(option) => (
|
||||||
|
<div className="flex items-center justify-between gap-4 max-w-full overflow-hidden">
|
||||||
|
<Space className="flex-grow max-w-full truncate" size={4}>
|
||||||
|
<Avatar src={accessProvidersMap.get(option.data.value)?.icon} size="small" />
|
||||||
|
<Typography.Text ellipsis>{t(accessProvidersMap.get(option.data.value)?.name ?? "")}</Typography.Text>
|
||||||
|
</Space>
|
||||||
|
<div>
|
||||||
|
{accessProvidersMap.get(option.data.value)?.usage === "apply" && (
|
||||||
|
<>
|
||||||
|
<Tag color="orange">{t("access.props.provider.usage.dns")}</Tag>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{accessProvidersMap.get(option.data.value)?.usage === "deploy" && (
|
||||||
|
<>
|
||||||
|
<Tag color="blue">{t("access.props.provider.usage.host")}</Tag>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{accessProvidersMap.get(option.data.value)?.usage === "all" && (
|
||||||
|
<>
|
||||||
|
<Tag color="orange">{t("access.props.provider.usage.dns")}</Tag>
|
||||||
|
<Tag color="blue">{t("access.props.provider.usage.host")}</Tag>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default AccessTypeSelect;
|
@ -8,10 +8,12 @@ import { type CertificateModel } from "@/domain/certificate";
|
|||||||
import { saveFiles2Zip } from "@/utils/file";
|
import { saveFiles2Zip } from "@/utils/file";
|
||||||
|
|
||||||
type CertificateDetailProps = {
|
type CertificateDetailProps = {
|
||||||
|
className?: string;
|
||||||
|
style?: React.CSSProperties;
|
||||||
data: CertificateModel;
|
data: CertificateModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
const CertificateDetail = ({ data }: CertificateDetailProps) => {
|
const CertificateDetail = ({ data, ...props }: CertificateDetailProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [messageApi, MessageContextHolder] = message.useMessage();
|
const [messageApi, MessageContextHolder] = message.useMessage();
|
||||||
@ -33,7 +35,7 @@ const CertificateDetail = ({ data }: CertificateDetailProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div {...props}>
|
||||||
{MessageContextHolder}
|
{MessageContextHolder}
|
||||||
|
|
||||||
<Form layout="vertical">
|
<Form layout="vertical">
|
||||||
|
@ -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 { Drawer } from "antd";
|
||||||
|
|
||||||
import { type CertificateModel } from "@/domain/certificate";
|
import { type CertificateModel } from "@/domain/certificate";
|
||||||
@ -7,19 +8,44 @@ import CertificateDetail from "./CertificateDetail";
|
|||||||
type CertificateDetailDrawerProps = {
|
type CertificateDetailDrawerProps = {
|
||||||
data?: CertificateModel;
|
data?: CertificateModel;
|
||||||
open?: boolean;
|
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<boolean>(props, {
|
||||||
|
valuePropName: "open",
|
||||||
|
defaultValuePropName: "defaultOpen",
|
||||||
|
trigger: "onOpenChange",
|
||||||
|
});
|
||||||
|
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(data == null);
|
setLoading(data == null);
|
||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
|
const triggerDom = useMemo(() => {
|
||||||
|
if (!trigger) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cloneElement(trigger, {
|
||||||
|
...trigger.props,
|
||||||
|
onClick: () => {
|
||||||
|
setOpen(true);
|
||||||
|
trigger.props?.onClick?.();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, [trigger, setOpen]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Drawer closable destroyOnClose open={open} loading={loading} placement="right" width={480} onClose={onClose}>
|
<>
|
||||||
{data ? <CertificateDetail data={data} /> : <></>}
|
{triggerDom}
|
||||||
</Drawer>
|
|
||||||
|
<Drawer closable destroyOnClose open={open} loading={loading} placement="right" width={480} onClose={() => setOpen(false)}>
|
||||||
|
{data ? <CertificateDetail data={data} /> : <></>}
|
||||||
|
</Drawer>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,7 +5,8 @@ import { cn } from "@/components/ui/utils";
|
|||||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
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 AccessAliyunForm from "./AccessAliyunForm";
|
||||||
import AccessTencentForm from "./AccessTencentForm";
|
import AccessTencentForm from "./AccessTencentForm";
|
||||||
import AccessHuaweiCloudForm from "./AccessHuaweicloudForm";
|
import AccessHuaweiCloudForm from "./AccessHuaweicloudForm";
|
||||||
@ -281,10 +282,11 @@ const AccessEditDialog = ({ trigger, op, data, className, outConfigType }: Acces
|
|||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<ScrollArea className="max-h-[80vh]">
|
<ScrollArea className="max-h-[80vh]">
|
||||||
|
<AccessEditForm data={data} />
|
||||||
<div className="container py-3">
|
<div className="container py-3">
|
||||||
<div>
|
<div>
|
||||||
<Label>{t("access.authorization.form.type.label")}</Label>
|
<Label>{t("access.authorization.form.type.label")}</Label>
|
||||||
<AccessProviderSelect
|
<AccessTypeSelect
|
||||||
className="w-full mt-3"
|
className="w-full mt-3"
|
||||||
placeholder={t("access.authorization.form.type.placeholder")}
|
placeholder={t("access.authorization.form.type.placeholder")}
|
||||||
value={configType}
|
value={configType}
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
import * as React from "react";
|
|
||||||
import { cva, type VariantProps } from "class-variance-authority";
|
|
||||||
|
|
||||||
import { cn } from "./utils";
|
|
||||||
|
|
||||||
const alertVariants = cva(
|
|
||||||
"relative w-full rounded-lg border p-4 [&>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<HTMLDivElement, React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>>(
|
|
||||||
({ className, variant, ...props }, ref) => <div ref={ref} role="alert" className={cn(alertVariants({ variant }), className)} {...props} />
|
|
||||||
);
|
|
||||||
Alert.displayName = "Alert";
|
|
||||||
|
|
||||||
const AlertTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(({ className, ...props }, ref) => (
|
|
||||||
<h5 ref={ref} className={cn("mb-1 font-medium leading-none tracking-tight", className)} {...props} />
|
|
||||||
));
|
|
||||||
AlertTitle.displayName = "AlertTitle";
|
|
||||||
|
|
||||||
const AlertDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(({ className, ...props }, ref) => (
|
|
||||||
<div ref={ref} className={cn("text-sm [&_p]:leading-relaxed", className)} {...props} />
|
|
||||||
));
|
|
||||||
AlertDescription.displayName = "AlertDescription";
|
|
||||||
|
|
||||||
export { Alert, AlertTitle, AlertDescription };
|
|
@ -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.ElementRef<typeof SeparatorPrimitive.Root>, React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>>(
|
|
||||||
({ className, orientation = "horizontal", decorative = true, ...props }, ref) => (
|
|
||||||
<SeparatorPrimitive.Root
|
|
||||||
ref={ref}
|
|
||||||
decorative={decorative}
|
|
||||||
orientation={orientation}
|
|
||||||
className={cn("shrink-0 bg-border", orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
);
|
|
||||||
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
|
||||||
|
|
||||||
export { Separator };
|
|
@ -11,15 +11,17 @@
|
|||||||
|
|
||||||
"access.props.name": "Name",
|
"access.props.name": "Name",
|
||||||
"access.props.provider": "Provider",
|
"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.created_at": "Created At",
|
||||||
"access.props.updated_at": "Updated 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.label": "Provider",
|
||||||
"access.authorization.form.type.placeholder": "Please select a provider",
|
"access.authorization.form.type.placeholder": "Please select a provider",
|
||||||
"access.authorization.form.type.search.notfound": "Provider not found",
|
"access.authorization.form.type.search.notfound": "Provider not found",
|
||||||
"access.authorization.form.type.list": "Authorization List",
|
"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.config.label": "Configuration Type",
|
||||||
"access.authorization.form.region.label": "Region",
|
"access.authorization.form.region.label": "Region",
|
||||||
"access.authorization.form.region.placeholder": "Please enter Region",
|
"access.authorization.form.region.placeholder": "Please enter Region",
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
"access.props.name": "名称",
|
"access.props.name": "名称",
|
||||||
"access.props.provider": "服务商",
|
"access.props.provider": "服务商",
|
||||||
|
"access.props.provider.usage.dns": "DNS 服务商",
|
||||||
|
"access.props.provider.usage.host": "主机服务商",
|
||||||
"access.props.created_at": "创建时间",
|
"access.props.created_at": "创建时间",
|
||||||
"access.props.updated_at": "更新时间",
|
"access.props.updated_at": "更新时间",
|
||||||
|
|
||||||
|
@ -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 { Link, Navigate, Outlet, useLocation, useNavigate } from "react-router-dom";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Button, Drawer, Dropdown, Layout, Menu, Tooltip, theme, type ButtonProps, type MenuProps } from "antd";
|
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 location = useLocation();
|
||||||
const navigate = useNavigate();
|
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 { t } = useTranslation();
|
||||||
|
|
||||||
const { theme, setThemeMode } = useTheme();
|
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 { i18n } = useTranslation();
|
||||||
|
|
||||||
const items: Required<MenuProps>["items"] = Object.keys(i18n.store.data).map((key) => {
|
const items: Required<MenuProps>["items"] = Object.keys(i18n.store.data).map((key) => {
|
||||||
|
@ -40,7 +40,7 @@ const AccessList = () => {
|
|||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (_, record) => {
|
render: (_, record) => {
|
||||||
return (
|
return (
|
||||||
<Space className="max-w-full truncate" align="center" size={4}>
|
<Space className="max-w-full truncate" size={4}>
|
||||||
<Avatar src={accessProvidersMap.get(record.configType)?.icon} size="small" />
|
<Avatar src={accessProvidersMap.get(record.configType)?.icon} size="small" />
|
||||||
<Typography.Text ellipsis>{t(accessProvidersMap.get(record.configType)?.name ?? "")}</Typography.Text>
|
<Typography.Text ellipsis>{t(accessProvidersMap.get(record.configType)?.name ?? "")}</Typography.Text>
|
||||||
</Space>
|
</Space>
|
||||||
|
@ -152,15 +152,14 @@ const CertificateList = () => {
|
|||||||
width: 120,
|
width: 120,
|
||||||
render: (_, record) => (
|
render: (_, record) => (
|
||||||
<Space size={0}>
|
<Space size={0}>
|
||||||
<Tooltip title={t("certificate.action.view")}>
|
<CertificateDetailDrawer
|
||||||
<Button
|
data={record}
|
||||||
type="link"
|
trigger={
|
||||||
icon={<EyeIcon size={16} />}
|
<Tooltip title={t("certificate.action.view")}>
|
||||||
onClick={() => {
|
<Button type="link" icon={<EyeIcon size={16} />} />
|
||||||
handleViewClick(record);
|
</Tooltip>
|
||||||
}}
|
}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
|
||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
@ -177,10 +176,6 @@ 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<CertificateModel>();
|
|
||||||
|
|
||||||
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
||||||
|
|
||||||
const fetchTableData = useCallback(async () => {
|
const fetchTableData = useCallback(async () => {
|
||||||
if (loading) return;
|
if (loading) return;
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@ -210,11 +205,6 @@ const CertificateList = () => {
|
|||||||
fetchTableData();
|
fetchTableData();
|
||||||
}, [fetchTableData]);
|
}, [fetchTableData]);
|
||||||
|
|
||||||
const handleViewClick = (certificate: CertificateModel) => {
|
|
||||||
setDrawerOpen(true);
|
|
||||||
setCurrentRecord(certificate);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{NotificationContextHolder}
|
{NotificationContextHolder}
|
||||||
@ -244,15 +234,6 @@ const CertificateList = () => {
|
|||||||
rowKey={(record: CertificateModel) => record.id}
|
rowKey={(record: CertificateModel) => record.id}
|
||||||
scroll={{ x: "max(100%, 960px)" }}
|
scroll={{ x: "max(100%, 960px)" }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<CertificateDetailDrawer
|
|
||||||
data={currentRecord}
|
|
||||||
open={drawerOpen}
|
|
||||||
onClose={() => {
|
|
||||||
setDrawerOpen(false);
|
|
||||||
setCurrentRecord(undefined);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -19,7 +19,7 @@ const Login = () => {
|
|||||||
password: z.string().min(10, t("login.password.errmsg.invalid")),
|
password: z.string().min(10, t("login.password.errmsg.invalid")),
|
||||||
});
|
});
|
||||||
const formRule = createSchemaFieldRule(formSchema);
|
const formRule = createSchemaFieldRule(formSchema);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm<z.infer<typeof formSchema>>();
|
||||||
|
|
||||||
const [isPending, setIsPending] = useState(false);
|
const [isPending, setIsPending] = useState(false);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user