diff --git a/web/src/components/empty/empty.tsx b/web/src/components/empty/empty.tsx index bd12e9ce9..b637c261f 100644 --- a/web/src/components/empty/empty.tsx +++ b/web/src/components/empty/empty.tsx @@ -2,6 +2,9 @@ import { cn } from '@/lib/utils'; import { t } from 'i18next'; import { useIsDarkTheme } from '../theme-provider'; +import noDataIcon from './no data bri.svg'; +import noDataIconDark from './no data.svg'; + type EmptyProps = { className?: string; children?: React.ReactNode; @@ -10,6 +13,14 @@ type EmptyProps = { const EmptyIcon = () => { const isDarkTheme = useIsDarkTheme(); + return ( + {t('common.noData')} + ); + return ( { return (
+ {!children && ( -
+
{t('common.noData')}
)} diff --git a/web/src/components/empty/no data bri.svg b/web/src/components/empty/no data bri.svg new file mode 100644 index 000000000..d6fa9e000 --- /dev/null +++ b/web/src/components/empty/no data bri.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/src/components/empty/no data.svg b/web/src/components/empty/no data.svg new file mode 100644 index 000000000..19117945a --- /dev/null +++ b/web/src/components/empty/no data.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web/src/components/spotlight.tsx b/web/src/components/spotlight.tsx index 50b4682f5..374b84403 100644 --- a/web/src/components/spotlight.tsx +++ b/web/src/components/spotlight.tsx @@ -1,4 +1,5 @@ import { useIsDarkTheme } from '@/components/theme-provider'; +import { cn } from '@/lib/utils'; import { parseColorToRGB } from '@/utils/common-util'; import React from 'react'; @@ -36,7 +37,7 @@ const Spotlight: React.FC = ({ : '194, 221, 243'; return (
, VariantProps { asChild?: boolean; + loading?: boolean; + block?: boolean; } const Button = React.forwardRef( - ({ className, variant, size, asChild = false, ...props }, ref) => { + ( + { + children, + className, + variant, + size, + asChild = false, + loading = false, + disabled = false, + block = false, + ...props + }, + ref, + ) => { const Comp = asChild ? Slot : 'button'; + return ( + > + {loading && } + {children} + ); }, ); + Button.displayName = 'Button'; -export const ButtonLoading = React.forwardRef< - HTMLButtonElement, - Omit & { loading?: boolean } ->( - ( - { className, variant, size, children, loading = false, disabled, ...props }, - ref, - ) => { - return ( - - ); - }, -); +export const ButtonLoading = Button; ButtonLoading.displayName = 'ButtonLoading'; diff --git a/web/src/components/ui/card.tsx b/web/src/components/ui/card.tsx index 66cfe6504..281199a16 100644 --- a/web/src/components/ui/card.tsx +++ b/web/src/components/ui/card.tsx @@ -9,7 +9,7 @@ const Card = React.forwardRef<
>(({ className, ...props }, ref) => ( -
+
)); CardContent.displayName = 'CardContent'; diff --git a/web/src/components/ui/checkbox.tsx b/web/src/components/ui/checkbox.tsx index eb338959e..64e23d40a 100644 --- a/web/src/components/ui/checkbox.tsx +++ b/web/src/components/ui/checkbox.tsx @@ -13,7 +13,11 @@ const Checkbox = React.forwardRef< - + )); diff --git a/web/src/components/ui/dialog.tsx b/web/src/components/ui/dialog.tsx index be1cca79a..cc4608f57 100644 --- a/web/src/components/ui/dialog.tsx +++ b/web/src/components/ui/dialog.tsx @@ -21,7 +21,7 @@ const DialogOverlay = React.forwardRef< {children} - + Close @@ -102,7 +109,7 @@ const DialogDescription = React.forwardRef< >(({ className, ...props }, ref) => ( )); diff --git a/web/src/components/ui/dropdown-menu.tsx b/web/src/components/ui/dropdown-menu.tsx index 6fadf9765..85aa4ade0 100644 --- a/web/src/components/ui/dropdown-menu.tsx +++ b/web/src/components/ui/dropdown-menu.tsx @@ -65,7 +65,7 @@ const DropdownMenuContent = React.forwardRef< ref={ref} sideOffset={sideOffset} className={cn( - 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', + 'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-bg-base p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', className, )} {...props} diff --git a/web/src/components/ui/form.tsx b/web/src/components/ui/form.tsx index e0ca30845..c4d8c1ea3 100644 --- a/web/src/components/ui/form.tsx +++ b/web/src/components/ui/form.tsx @@ -97,19 +97,18 @@ const FormLabel = React.forwardRef< required?: boolean; } >(({ className, tooltip, required = false, ...props }, ref) => { - const { error, formItemId } = useFormField(); + const { formItemId } = useFormField(); return ( ); @@ -171,7 +170,7 @@ const FormMessage = React.forwardRef<

{body} diff --git a/web/src/components/ui/input.tsx b/web/src/components/ui/input.tsx index a8a0d2962..60acfb4ff 100644 --- a/web/src/components/ui/input.tsx +++ b/web/src/components/ui/input.tsx @@ -3,14 +3,17 @@ import * as React from 'react'; import { cn } from '@/lib/utils'; import { Eye, EyeOff, Search } from 'lucide-react'; import { useState } from 'react'; +import { Button } from './button'; export interface InputProps - extends React.InputHTMLAttributes { + extends Omit, 'prefix'> { value?: string | number | readonly string[] | undefined; + prefix?: React.ReactNode; + suffix?: React.ReactNode; } const Input = React.forwardRef( - ({ className, type, value, onChange, ...props }, ref) => { + ({ className, type, value, onChange, prefix, suffix, ...props }, ref) => { const isControlled = value !== undefined; const { defaultValue, ...restProps } = props; const inputValue = isControlled ? value : defaultValue; @@ -29,99 +32,80 @@ const Input = React.forwardRef( onChange?.(e); } }; - return ( - <> - {type !== 'password' && ( - + + const isPasswordInput = type === 'password'; + + const inputEl = ( + - - -

- )} - - ); + + )} +
+ ); + } + + return inputEl; }, ); + Input.displayName = 'Input'; -export interface ExpandedInputProps extends Omit { - prefix?: React.ReactNode; - suffix?: React.ReactNode; -} +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface ExpandedInputProps extends InputProps {} -const ExpandedInput = ({ - suffix, - prefix, - className, - ...props -}: ExpandedInputProps) => { - return ( -
- - {prefix} - - - - {suffix} - -
- ); -}; +const ExpandedInput = Input; const SearchInput = (props: InputProps) => { - return ( - } - {...props} - > - ); + return } />; }; type Value = string | readonly string[] | number | undefined; diff --git a/web/src/components/ui/pagination.tsx b/web/src/components/ui/pagination.tsx index aa71efee8..68cc6b404 100644 --- a/web/src/components/ui/pagination.tsx +++ b/web/src/components/ui/pagination.tsx @@ -46,6 +46,7 @@ const PaginationLink = ({ ...props }: PaginationLinkProps) => ( - + ); PaginationPrevious.displayName = 'PaginationPrevious'; @@ -85,7 +86,7 @@ const PaginationNext = ({ className={cn('gap-1 pr-2.5', className)} {...props} > - + ); PaginationNext.displayName = 'PaginationNext'; @@ -96,7 +97,7 @@ const PaginationEllipsis = ({ }: React.ComponentProps<'span'>) => ( diff --git a/web/src/components/ui/popover.tsx b/web/src/components/ui/popover.tsx index 86f1dac17..562329e5e 100644 --- a/web/src/components/ui/popover.tsx +++ b/web/src/components/ui/popover.tsx @@ -39,7 +39,11 @@ const PopoverContent = React.forwardRef< align={align} sideOffset={sideOffset} className={cn( - 'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', + 'z-50 w-72 rounded-md border-0.5 border-border-button bg-bg-base p-4 text-text-primary shadow-lg outline-none', + 'data-[state=open]:animate-in data-[state=closed]:animate-out', + 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0', + 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-9', + 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', className, )} {...props} diff --git a/web/src/components/ui/radio-group.tsx b/web/src/components/ui/radio-group.tsx index f1e246ba7..2505f1da7 100644 --- a/web/src/components/ui/radio-group.tsx +++ b/web/src/components/ui/radio-group.tsx @@ -27,7 +27,12 @@ function RadioGroupItem({ - + ); diff --git a/web/src/components/ui/radio.tsx b/web/src/components/ui/radio.tsx index eeea31201..2262ecd8b 100644 --- a/web/src/components/ui/radio.tsx +++ b/web/src/components/ui/radio.tsx @@ -49,7 +49,7 @@ function Radio({ value, checked, disabled, onChange, children }: RadioProps) { + {showSizeChanger && ( + triggerClassName="bg-bg-card border-transparent" + /> )} ); diff --git a/web/src/components/ui/select.tsx b/web/src/components/ui/select.tsx index f17ea26aa..a2edd3263 100644 --- a/web/src/components/ui/select.tsx +++ b/web/src/components/ui/select.tsx @@ -26,7 +26,11 @@ const SelectTrigger = React.forwardRef< span]:line-clamp-1', + 'flex h-8 w-full items-center bg-bg-input justify-between rounded-md border-0.5 border-border-button', + 'px-3 py-2 text-sm outline-none transition-colors text-text-secondary placeholder:text-muted-foreground', + 'hover:text-text-primary hover:bg-border-button', + 'focus-visible:text-text-primary focus-visible:bg-border-button', + 'disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1', className, )} {...props} @@ -91,7 +95,11 @@ const SelectContent = React.forwardRef< (({ className, ...props }, ref) => ( )); diff --git a/web/src/components/ui/table.tsx b/web/src/components/ui/table.tsx index f8f5c5400..f76078b78 100644 --- a/web/src/components/ui/table.tsx +++ b/web/src/components/ui/table.tsx @@ -27,7 +27,10 @@ const TableHeader = React.forwardRef< >(({ className, ...props }, ref) => ( )); @@ -52,7 +55,7 @@ const TableFooter = React.forwardRef< tr]:last:border-b-0', + 'border-t-0.5 border-border-button bg-muted/50 font-medium [&>tr]:last:border-b-0', className, )} {...props} @@ -67,7 +70,7 @@ const TableRow = React.forwardRef< setTheme(value ? ThemeEnum.Dark : ThemeEnum.Light) } > -
-
+
+
@@ -35,11 +38,22 @@ const ThemeSwitch = forwardRef< + > +
+ ); }); diff --git a/web/src/pages/admin/forms/role-form.tsx b/web/src/pages/admin/forms/role-form.tsx index 13b52f5ab..53703cdc9 100644 --- a/web/src/pages/admin/forms/role-form.tsx +++ b/web/src/pages/admin/forms/role-form.tsx @@ -18,12 +18,7 @@ import { import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; -import { - Tabs, - TabsContent, - TabsList, - TabsTrigger, -} from '@/components/ui/tabs-underlined'; +import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { listResources } from '@/services/admin-service'; import { PERMISSION_TYPES, formMergeDefaultValues } from '../utils'; @@ -106,12 +101,12 @@ export const CreateRoleForm = ({ - + {resourceTypes?.map((resourceType) => ( {t(`admin.resourceType.${resourceType.toLowerCase()}`)} diff --git a/web/src/pages/admin/forms/user-form.tsx b/web/src/pages/admin/forms/user-form.tsx index 144709f3f..505982d97 100644 --- a/web/src/pages/admin/forms/user-form.tsx +++ b/web/src/pages/admin/forms/user-form.tsx @@ -153,7 +153,11 @@ export const CreateUserForm = ({ {role.role_name} - ))} + )) ?? ( +
+ {t('common.noData')} +
+ )} diff --git a/web/src/pages/admin/layout.tsx b/web/src/pages/admin/layouts/navigation-layout.tsx similarity index 89% rename from web/src/pages/admin/layout.tsx rename to web/src/pages/admin/layouts/navigation-layout.tsx index 77fd75dc0..ce9b2ade7 100644 --- a/web/src/pages/admin/layout.tsx +++ b/web/src/pages/admin/layouts/navigation-layout.tsx @@ -1,10 +1,9 @@ -import { Button } from '@/components/ui/button'; -import message from '@/components/ui/message'; -import { cn } from '@/lib/utils'; -import { Routes } from '@/routes'; -import { logout } from '@/services/admin-service'; -import authorizationUtil from '@/utils/authorization-util'; +import { useMemo } from 'react'; +import { useTranslation } from 'react-i18next'; +import { NavLink, Outlet, useNavigate } from 'umi'; + import { useMutation } from '@tanstack/react-query'; + import { LucideMonitor, LucideServerCrash, @@ -12,13 +11,18 @@ import { LucideUserCog, LucideUserStar, } from 'lucide-react'; -import { useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; -import { NavLink, Outlet, useNavigate } from 'umi'; -import ThemeSwitch from './components/theme-switch'; -import { IS_ENTERPRISE } from './utils'; -const AdminLayout = () => { +import { Button } from '@/components/ui/button'; +import { cn } from '@/lib/utils'; +import { Routes } from '@/routes'; +import { logout } from '@/services/admin-service'; + +import authorizationUtil from '@/utils/authorization-util'; + +import ThemeSwitch from '../components/theme-switch'; +import { IS_ENTERPRISE } from '../utils'; + +const AdminNavigationLayout = () => { const { t } = useTranslation(); const navigate = useNavigate(); @@ -61,8 +65,6 @@ const AdminLayout = () => { mutationKey: ['adminLogout'], mutationFn: async () => { await logout(); - - message.success(t('message.logout')); authorizationUtil.removeAll(); navigate(Routes.Admin); }, @@ -90,6 +92,7 @@ const AdminLayout = () => { 'hover:bg-bg-card focus:bg-bg-card focus-visible:bg-bg-card', 'hover:text-text-primary focus:text-text-primary focus-visible:text-text-primary', 'active:text-text-primary', + 'transition-colors', { 'bg-bg-card text-text-primary': isActive, }, @@ -105,14 +108,18 @@ const AdminLayout = () => {
-
+
+ + vmm.ss.rr-nnn-commithash + +
-
+ @@ -218,10 +201,10 @@ function AdminLogin() { @@ -241,19 +224,17 @@ function AdminLogin() { - {t('login')} - + diff --git a/web/src/pages/admin/monitoring.tsx b/web/src/pages/admin/monitoring.tsx index 1106f2035..ebcab7573 100644 --- a/web/src/pages/admin/monitoring.tsx +++ b/web/src/pages/admin/monitoring.tsx @@ -3,11 +3,14 @@ import { Card, CardContent } from '@/components/ui/card'; function AdminMonitoring() { return ( - + -