Browse Source

fix: user page has wrong pagination text (#884)

Signed-off-by: ryjiang <jiangruiyi@gmail.com>
ryjiang 1 month ago
parent
commit
e4ffb1b37d

+ 34 - 57
client/src/components/grid/Grid.tsx

@@ -4,63 +4,11 @@ import Typography from '@mui/material/Typography';
 import Grid from '@mui/material/Grid';
 import Grid from '@mui/material/Grid';
 import Breadcrumbs from '@mui/material/Breadcrumbs';
 import Breadcrumbs from '@mui/material/Breadcrumbs';
 import TablePagination from '@mui/material/TablePagination';
 import TablePagination from '@mui/material/TablePagination';
-import { makeStyles } from '@mui/styles';
 import CustomToolbar from './ToolBar';
 import CustomToolbar from './ToolBar';
 import Table from './Table';
 import Table from './Table';
 import TablePaginationActions from './TablePaginationActions';
 import TablePaginationActions from './TablePaginationActions';
-import type { Theme } from '@mui/material/styles/createTheme';
 import type { AttuGridType } from './Types';
 import type { AttuGridType } from './Types';
 
 
-const userStyle = makeStyles((theme: Theme) => ({
-  wrapper: {
-    height: '100%',
-  },
-  container: {
-    flexWrap: 'nowrap',
-    flexDirection: 'column',
-  },
-  loading: {
-    height: '100%',
-    display: 'flex',
-    alignItems: 'center',
-    justifyContent: 'center',
-    padding: theme.spacing(20),
-    width: '100%',
-  },
-  tableTitle: {
-    '& .last': {
-      color: 'rgba(0, 0, 0, 0.54)',
-    },
-  },
-  pagenation: {
-    '& .MuiTablePagination-spacer': {
-      display: 'none',
-    },
-    '& .MuiTablePagination-toolbar': {
-      display: 'flex',
-      justifyContent: 'space-between',
-      paddingLeft: 8,
-    },
-    '& .MuiTablePagination-caption': {
-      position: 'absolute',
-      left: 0,
-      bottom: 0,
-      top: 0,
-      display: 'flex',
-      alignItems: 'center',
-      '& .rows': {
-        color: 'rgba(0,0,0,0.33)',
-        marginLeft: theme.spacing(1),
-      },
-    },
-  },
-  noBottomPadding: {
-    paddingBottom: '0 !important',
-    display: 'flex',
-    flexDirection: 'column',
-  },
-}));
-
 /**
 /**
  *
  *
  * @param rowCount required. totoal data count for pagination
  * @param rowCount required. totoal data count for pagination
@@ -87,7 +35,7 @@ const userStyle = makeStyles((theme: Theme) => ({
  * @returns
  * @returns
  */
  */
 const AttuGrid: FC<AttuGridType> = props => {
 const AttuGrid: FC<AttuGridType> = props => {
-  const classes = userStyle();
+  // const classes = userStyle();
   const tableRef = useRef<HTMLDivElement | null>(null);
   const tableRef = useRef<HTMLDivElement | null>(null);
 
 
   // i18n
   // i18n
@@ -209,11 +157,11 @@ const AttuGrid: FC<AttuGridType> = props => {
   return (
   return (
     <Grid
     <Grid
       container
       container
-      classes={{ root: classes.wrapper, container: classes.container }}
+      sx={{ height: '100%', flexWrap: 'nowrap', flexDirection: 'column' }}
       ref={tableRef}
       ref={tableRef}
     >
     >
       {title && (
       {title && (
-        <Grid item xs={12} className={classes.tableTitle}>
+        <Grid item xs={12} sx={{ '& .last': { color: 'rgba(0, 0, 0, 0.54)' } }}>
           <Breadcrumbs separator="›" aria-label="breadcrumb" role="breadcrumb">
           <Breadcrumbs separator="›" aria-label="breadcrumb" role="breadcrumb">
             {title.map(
             {title.map(
               (v: any, i: number) =>
               (v: any, i: number) =>
@@ -242,7 +190,15 @@ const AttuGrid: FC<AttuGridType> = props => {
         </Grid>
         </Grid>
       )}
       )}
 
 
-      <Grid item xs={12} className={classes.noBottomPadding}>
+      <Grid
+        item
+        xs={12}
+        sx={{
+          paddingBottom: '0 !important',
+          display: 'flex',
+          flexDirection: 'column',
+        }}
+      >
         <Table
         <Table
           openCheckBox={openCheckBox}
           openCheckBox={openCheckBox}
           primaryKey={primaryKey}
           primaryKey={primaryKey}
@@ -274,7 +230,28 @@ const AttuGrid: FC<AttuGridType> = props => {
             rowsPerPage={rowsPerPage}
             rowsPerPage={rowsPerPage}
             rowsPerPageOptions={[]}
             rowsPerPageOptions={[]}
             onPageChange={onPageChange}
             onPageChange={onPageChange}
-            className={classes.pagenation}
+            sx={{
+              '& .MuiTablePagination-spacer': {
+                display: 'none',
+              },
+              '& .MuiTablePagination-toolbar': {
+                display: 'flex',
+                justifyContent: 'space-between',
+                paddingLeft: 0,
+              },
+              '& .MuiTablePagination-caption': {
+                position: 'absolute',
+                left: 0,
+                bottom: 0,
+                top: 0,
+                display: 'flex',
+                alignItems: 'center',
+                '& .rows': {
+                  color: 'rgba(0,0,0,0.33)',
+                  marginLeft: 1,
+                },
+              },
+            }}
             ActionsComponent={TablePaginationActions}
             ActionsComponent={TablePaginationActions}
           />
           />
         ) : null}
         ) : null}

+ 114 - 106
client/src/components/grid/Table.tsx

@@ -5,7 +5,6 @@ import TableCell from '@mui/material/TableCell';
 import TableContainer from '@mui/material/TableContainer';
 import TableContainer from '@mui/material/TableContainer';
 import TableRow from '@mui/material/TableRow';
 import TableRow from '@mui/material/TableRow';
 import Checkbox from '@mui/material/Checkbox';
 import Checkbox from '@mui/material/Checkbox';
-import { makeStyles } from '@mui/styles';
 import Box from '@mui/material/Box';
 import Box from '@mui/material/Box';
 import Button from '@mui/material/Button';
 import Button from '@mui/material/Button';
 import Typography from '@mui/material/Typography';
 import Typography from '@mui/material/Typography';
@@ -18,81 +17,6 @@ import { useTranslation } from 'react-i18next';
 import type { Theme } from '@mui/material/styles';
 import type { Theme } from '@mui/material/styles';
 import type { TableType } from './Types';
 import type { TableType } from './Types';
 
 
-const useStyles = makeStyles((theme: Theme) => ({
-  root: {
-    width: '100%',
-    flexGrow: 1,
-    color: theme.palette.text.primary,
-    backgroundColor: theme.palette.background.paper,
-  },
-  table: {
-    minWidth: '100%',
-  },
-  tableCell: {
-    padding: theme.spacing(1, 1.5),
-  },
-  cellContainer: {
-    display: 'flex',
-    whiteSpace: 'nowrap',
-  },
-  hoverActionCell: {
-    transition: '0.2s all',
-    padding: 0,
-    width: '50px',
-    '& span': {
-      opacity: 0,
-    },
-  },
-  checkbox: {
-    borderBottom: `1px solid ${theme.palette.divider}`,
-  },
-  rowHover: {
-    '&:hover': {
-      '& td': {
-        background: 'inherit',
-      },
-
-      '& $hoverActionCell': {
-        '& span': {
-          opacity: 1,
-        },
-      },
-    },
-  },
-  selected: {
-    '& td': {
-      background: 'inherit',
-    },
-  },
-  cell: {
-    borderBottom: `1px solid ${theme.palette.divider}`,
-
-    '& p': {
-      display: 'inline-block',
-      verticalAlign: 'middle',
-      overflow: 'hidden',
-      textOverflow: 'ellipsis',
-      whiteSpace: 'nowrap',
-      maxWidth: (props: { tableCellMaxWidth: string }) =>
-        props.tableCellMaxWidth,
-      fontSize: '14px',
-      lineHeight: '20px',
-    },
-  },
-  noData: {
-    paddingTop: theme.spacing(6),
-    textAlign: 'center',
-    letterSpacing: '0.5px',
-    color: theme.palette.text.secondary,
-  },
-  copyBtn: {
-    '& svg': {
-      fontSize: '14px',
-    },
-    marginLeft: theme.spacing(0.5),
-  },
-}));
-
 const EnhancedTable: FC<TableType> = props => {
 const EnhancedTable: FC<TableType> = props => {
   let {
   let {
     selected,
     selected,
@@ -121,16 +45,24 @@ const EnhancedTable: FC<TableType> = props => {
     orderBy,
     orderBy,
     rowDecorator = () => ({}),
     rowDecorator = () => ({}),
   } = props;
   } = props;
-  const classes = useStyles({ tableCellMaxWidth });
   const { t: commonTrans } = useTranslation();
   const { t: commonTrans } = useTranslation();
 
 
   return (
   return (
-    <TableContainer className={classes.root}>
+    <TableContainer
+      sx={theme => ({
+        width: '100%',
+        flexGrow: 1,
+        color: theme.palette.text.primary,
+        backgroundColor: theme.palette.background.paper,
+      })}
+    >
       <Box height="100%">
       <Box height="100%">
         {!isLoading && (
         {!isLoading && (
           <Table
           <Table
             stickyHeader
             stickyHeader
-            className={classes.table}
+            sx={{
+              minWidth: '100%',
+            }}
             aria-labelledby="tableTitle"
             aria-labelledby="tableTitle"
             size="medium"
             size="medium"
             aria-label="enhanced table"
             aria-label="enhanced table"
@@ -165,19 +97,36 @@ const EnhancedTable: FC<TableType> = props => {
                       aria-checked={isItemSelected}
                       aria-checked={isItemSelected}
                       tabIndex={-1}
                       tabIndex={-1}
                       selected={isItemSelected && !disableSelect}
                       selected={isItemSelected && !disableSelect}
-                      classes={{
-                        hover: classes.rowHover,
-                        selected:
-                          isItemSelected && !disableSelect
-                            ? classes.selected
-                            : undefined,
-                      }}
-                      sx={rowDecorator(row)}
+                      sx={
+                        [
+                          showHoverStyle && {
+                            '&:hover': {
+                              '& td': {
+                                background: 'inherit',
+                              },
+                              '& .hoverActionCell': {
+                                '& span': {
+                                  opacity: 1,
+                                },
+                              },
+                            },
+                          },
+                          isItemSelected &&
+                            !disableSelect && {
+                              '& td': {
+                                background: 'inherit',
+                              },
+                            },
+                          rowDecorator(row),
+                        ].filter(Boolean) as any
+                      }
                     >
                     >
                       {openCheckBox && (
                       {openCheckBox && (
                         <TableCell
                         <TableCell
                           padding="checkbox"
                           padding="checkbox"
-                          className={classes.checkbox}
+                          sx={theme => ({
+                            borderBottom: `1px solid ${theme.palette.divider}`,
+                          })}
                         >
                         >
                           <Checkbox
                           <Checkbox
                             checked={isItemSelected}
                             checked={isItemSelected}
@@ -194,18 +143,44 @@ const EnhancedTable: FC<TableType> = props => {
                       {colDefinitions.map((colDef, i) => {
                       {colDefinitions.map((colDef, i) => {
                         const { actionBarConfigs = [], needCopy = false } =
                         const { actionBarConfigs = [], needCopy = false } =
                           colDef;
                           colDef;
-                        const cellStyle = colDef.getStyle
+                        const cellStyleFromDef = colDef.getStyle
                           ? colDef.getStyle(row[colDef.id])
                           ? colDef.getStyle(row[colDef.id])
                           : {};
                           : {};
                         return colDef.showActionCell ? (
                         return colDef.showActionCell ? (
                           <TableCell
                           <TableCell
-                            className={`${classes.cell} ${classes.tableCell} ${
-                              colDef.isHoverAction
-                                ? classes.hoverActionCell
-                                : ''
-                            }`}
+                            sx={
+                              [
+                                (theme: Theme) => ({
+                                  borderBottom: `1px solid ${theme.palette.divider}`,
+                                  '& p': {
+                                    display: 'inline-block',
+                                    verticalAlign: 'middle',
+                                    overflow: 'hidden',
+                                    textOverflow: 'ellipsis',
+                                    whiteSpace: 'nowrap',
+                                    maxWidth: tableCellMaxWidth,
+                                    fontSize: '14px',
+                                    lineHeight: '20px',
+                                  },
+                                }),
+                                (theme: Theme) => ({
+                                  padding: theme.spacing(1, 1.5),
+                                }),
+                                colDef.isHoverAction && {
+                                  transition: '0.2s all',
+                                  padding: 0,
+                                  width: '50px',
+                                  '& span': {
+                                    opacity: 0,
+                                  },
+                                },
+                                cellStyleFromDef,
+                              ].filter(Boolean) as any
+                            }
+                            className={
+                              colDef.isHoverAction ? 'hoverActionCell' : ''
+                            } // Keep class for targeting in rowHoverStyles
                             key={colDef.id}
                             key={colDef.id}
-                            style={cellStyle}
                           >
                           >
                             <ActionBar
                             <ActionBar
                               configs={actionBarConfigs}
                               configs={actionBarConfigs}
@@ -216,12 +191,35 @@ const EnhancedTable: FC<TableType> = props => {
                         ) : (
                         ) : (
                           <TableCell
                           <TableCell
                             key={'cell' + row[primaryKey] + i}
                             key={'cell' + row[primaryKey] + i}
-                            // padding={i === 0 ? 'none' : 'default'}
                             align={colDef.align || 'left'}
                             align={colDef.align || 'left'}
-                            className={`${classes.cell} ${classes.tableCell}`}
-                            style={cellStyle}
+                            sx={
+                              [
+                                (theme: Theme) => ({
+                                  borderBottom: `1px solid ${theme.palette.divider}`,
+                                  '& p': {
+                                    display: 'inline-block',
+                                    verticalAlign: 'middle',
+                                    overflow: 'hidden',
+                                    textOverflow: 'ellipsis',
+                                    whiteSpace: 'nowrap',
+                                    maxWidth: tableCellMaxWidth,
+                                    fontSize: '14px',
+                                    lineHeight: '20px',
+                                  },
+                                }),
+                                (theme: Theme) => ({
+                                  padding: theme.spacing(1, 1.5),
+                                }),
+                                cellStyleFromDef,
+                              ].filter(Boolean) as any
+                            }
                           >
                           >
-                            <div className={classes.cellContainer}>
+                            <Box
+                              sx={{
+                                display: 'flex',
+                                whiteSpace: 'nowrap',
+                              }}
+                            >
                               {typeof row[colDef.id] !== 'undefined' && (
                               {typeof row[colDef.id] !== 'undefined' && (
                                 <>
                                 <>
                                   {colDef.onClick ? (
                                   {colDef.onClick ? (
@@ -256,12 +254,17 @@ const EnhancedTable: FC<TableType> = props => {
                                       label={commonTrans('copy.label')}
                                       label={commonTrans('copy.label')}
                                       value={row[colDef.id]}
                                       value={row[colDef.id]}
                                       size="small"
                                       size="small"
-                                      className={classes.copyBtn}
+                                      sx={theme => ({
+                                        '& svg': {
+                                          fontSize: '14px',
+                                        },
+                                        marginLeft: theme.spacing(0.5),
+                                      })}
                                     />
                                     />
                                   )}
                                   )}
                                 </>
                                 </>
                               )}
                               )}
-                            </div>
+                            </Box>
                           </TableCell>
                           </TableCell>
                         );
                         );
                       })}
                       })}
@@ -269,9 +272,14 @@ const EnhancedTable: FC<TableType> = props => {
                   );
                   );
                 })
                 })
               ) : (
               ) : (
-                <tr>
-                  <td
-                    className={classes.noData}
+                <TableRow>
+                  <TableCell
+                    sx={theme => ({
+                      paddingTop: theme.spacing(6),
+                      textAlign: 'center',
+                      letterSpacing: '0.5px',
+                      color: theme.palette.text.secondary,
+                    })}
                     colSpan={
                     colSpan={
                       openCheckBox
                       openCheckBox
                         ? colDefinitions.length + 1
                         ? colDefinitions.length + 1
@@ -279,8 +287,8 @@ const EnhancedTable: FC<TableType> = props => {
                     }
                     }
                   >
                   >
                     {noData}
                     {noData}
-                  </td>
-                </tr>
+                  </TableCell>
+                </TableRow>
               )}
               )}
             </TableBody>
             </TableBody>
           </Table>
           </Table>

+ 1 - 1
client/src/components/layout/Wrapper.tsx

@@ -29,7 +29,7 @@ const Wrapper = ({
         width: '100%',
         width: '100%',
         height: '100%',
         height: '100%',
         position: 'relative',
         position: 'relative',
-        ...((Array.isArray(sx) ? Object.assign({}, ...sx) : sx) || {})
+        ...((Array.isArray(sx) ? Object.assign({}, ...sx) : sx) || {}),
       }}
       }}
     >
     >
       {children}
       {children}

+ 12 - 19
client/src/components/menu/SimpleMenu.tsx

@@ -3,25 +3,9 @@ import React from 'react';
 import Menu from '@mui/material/Menu';
 import Menu from '@mui/material/Menu';
 import MenuItem from '@mui/material/MenuItem';
 import MenuItem from '@mui/material/MenuItem';
 import CustomButton from '../customButton/CustomButton';
 import CustomButton from '../customButton/CustomButton';
-import { makeStyles } from '@mui/styles';
 import { generateId } from '../../utils/Common';
 import { generateId } from '../../utils/Common';
-import type { Theme } from '@mui/material/styles';
 import type { SimpleMenuType } from './Types';
 import type { SimpleMenuType } from './Types';
 
 
-const getStyles = makeStyles((theme: Theme) => ({
-  menuPaper: {
-    boxShadow: '0px 4px 24px rgba(0, 0, 0, 0.08)',
-  },
-  menuItem: {
-    minWidth: (props: { minWidth: string }) => props.minWidth,
-    padding: theme.spacing(1),
-
-    '&:hover': {
-      backgroundColor: '#f4f4f4',
-    },
-  },
-}));
-
 const SimpleMenu: FC<SimpleMenuType> = props => {
 const SimpleMenu: FC<SimpleMenuType> = props => {
   const {
   const {
     label,
     label,
@@ -32,7 +16,6 @@ const SimpleMenu: FC<SimpleMenuType> = props => {
   } = props;
   } = props;
   const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
   const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
 
 
-  const classes = getStyles({ minWidth: menuItemWidth });
   const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
   const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
     setAnchorEl(event.currentTarget);
     setAnchorEl(event.currentTarget);
   };
   };
@@ -59,7 +42,11 @@ const SimpleMenu: FC<SimpleMenuType> = props => {
         keepMounted
         keepMounted
         open={Boolean(anchorEl)}
         open={Boolean(anchorEl)}
         onClose={handleClose}
         onClose={handleClose}
-        classes={{ paper: classes.menuPaper }}
+        PaperProps={{
+          sx: {
+            boxShadow: '0px 4px 24px rgba(0, 0, 0, 0.08)',
+          },
+        }}
         // anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
         // anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
         // transformOrigin={{ vertical: 'top', horizontal: 'center' }}
         // transformOrigin={{ vertical: 'top', horizontal: 'center' }}
       >
       >
@@ -67,7 +54,13 @@ const SimpleMenu: FC<SimpleMenuType> = props => {
           {menuItems.map((v, i) =>
           {menuItems.map((v, i) =>
             typeof v.label === 'string' ? (
             typeof v.label === 'string' ? (
               <MenuItem
               <MenuItem
-                classes={{ root: classes.menuItem }}
+                sx={theme => ({
+                  minWidth: menuItemWidth,
+                  padding: theme.spacing(1),
+                  '&:hover': {
+                    backgroundColor: '#f4f4f4',
+                  },
+                })}
                 onClick={() => {
                 onClick={() => {
                   v.callback && v.callback();
                   v.callback && v.callback();
                   handleClose();
                   handleClose();

+ 2 - 0
client/src/i18n/cn/common.ts

@@ -32,6 +32,8 @@ const commonTrans = {
     action: '操作',
     action: '操作',
     noData: '无数据',
     noData: '无数据',
     rows: '行',
     rows: '行',
+    user: '用户',
+    users: '用户',
     entity: 'Entity',
     entity: 'Entity',
     entities: 'Entities',
     entities: 'Entities',
     collection: 'Collection',
     collection: 'Collection',

+ 5 - 1
client/src/i18n/en/common.ts

@@ -1,3 +1,5 @@
+import { use } from 'i18next';
+
 const commonTrans = {
 const commonTrans = {
   attu: {
   attu: {
     admin: 'Attu',
     admin: 'Attu',
@@ -33,6 +35,8 @@ const commonTrans = {
     action: 'action',
     action: 'action',
     noData: 'No Data',
     noData: 'No Data',
     rows: 'Rows',
     rows: 'Rows',
+    user: 'User',
+    users: 'Users',
     entity: 'Entity',
     entity: 'Entity',
     entities: 'Entities',
     entities: 'Entities',
     collection: 'Collection',
     collection: 'Collection',
@@ -92,4 +96,4 @@ const commonTrans = {
   noPermissionTip: `You don't have permission to access this content.`,
   noPermissionTip: `You don't have permission to access this content.`,
 };
 };
 
 
-export default commonTrans;
+export default commonTrans;

+ 47 - 25
client/src/pages/dialogs/insert/Preview.tsx

@@ -1,11 +1,10 @@
 import { FC, useCallback, useMemo } from 'react';
 import { FC, useCallback, useMemo } from 'react';
-import { Typography, Box } from '@mui/material';
+import { Typography, Box, Select, MenuItem, FormControl } from '@mui/material';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 import { InsertPreviewProps } from './Types';
 import { InsertPreviewProps } from './Types';
 import CustomSelector from '@/components/customSelector/CustomSelector';
 import CustomSelector from '@/components/customSelector/CustomSelector';
 import AttuGrid from '@/components/grid/Grid';
 import AttuGrid from '@/components/grid/Grid';
 import { transferCsvArrayToTableData } from '@/utils';
 import { transferCsvArrayToTableData } from '@/utils';
-import SimpleMenu from '@/components/menu/SimpleMenu';
 import icons from '@/components/icons/Icons';
 import icons from '@/components/icons/Icons';
 import type { Option } from '@/components/customSelector/Types';
 import type { Option } from '@/components/customSelector/Types';
 import type { ColDefinitionsType } from '@/components/grid/Types';
 import type { ColDefinitionsType } from '@/components/grid/Types';
@@ -25,7 +24,6 @@ const InsertPreview: FC<InsertPreviewProps> = ({
   handleIsContainedChange,
   handleIsContainedChange,
   tableHeads,
   tableHeads,
   setTableHeads,
   setTableHeads,
-  file,
 }) => {
 }) => {
   // Styles replaced with Box and sx below
   // Styles replaced with Box and sx below
   const { t: insertTrans } = useTranslation('insert');
   const { t: insertTrans } = useTranslation('insert');
@@ -48,29 +46,53 @@ const InsertPreview: FC<InsertPreviewProps> = ({
       tableHeads.map((head: string, index: number) => ({
       tableHeads.map((head: string, index: number) => ({
         value: head,
         value: head,
         component: (
         component: (
-          <SimpleMenu
-            label={head || insertTrans('requiredFieldName')}
-            menuItems={schemaOptions.map(schema => ({
-              label: schema.label,
-              callback: () => handleTableHeadChange(index, schema.label),
-              wrapperClass: head === schema.label ? 'menu-active' : 'menu-item',
-            }))}
-            buttonProps={{
-              sx: {
-                display: 'flex',
-                justifyContent: 'space-between',
-                minWidth: 160,
-                color: theme => theme.palette.text.secondary,
-                backgroundColor: '#fff',
-                '&:hover': { backgroundColor: '#fff' },
-              },
-              endIcon: (
-                <ArrowIcon
-                  sx={{ color: theme => theme.palette.text.secondary }}
-                />
-              ),
+          <FormControl
+            sx={{
+              m: 0.5,
+              minWidth: 120,
+              backgroundColor: theme => theme.palette.background.paper,
             }}
             }}
-          ></SimpleMenu>
+          >
+            <Select
+              value={head || ''} // Ensure value is not undefined for Select
+              onChange={event =>
+                handleTableHeadChange(index, event.target.value as string)
+              }
+              displayEmpty
+              IconComponent={ArrowIcon}
+              sx={{
+                color: theme => theme.palette.text.secondary,
+                fontSize: '0.875rem', // Smaller font size
+                '& .MuiSelect-select': {
+                  paddingRight: '28px', // Adjust for custom icon and smaller size
+                  paddingTop: '8px', // Reduce padding
+                  paddingBottom: '8px', // Reduce padding
+                },
+                '&:hover': { backgroundColor: 'transparent' }, // Mimic SimpleMenu style
+              }}
+              renderValue={selected => {
+                if (!selected) {
+                  return <em>{insertTrans('requiredFieldName')}</em>;
+                }
+                return selected;
+              }}
+            >
+              <MenuItem disabled value="">
+                <em>{insertTrans('requiredFieldName')}</em>
+              </MenuItem>
+              {schemaOptions.map(schema => (
+                <MenuItem
+                  key={schema.label}
+                  value={schema.label}
+                  className={
+                    head === schema.label ? 'menu-active' : 'menu-item'
+                  } // Keep similar class for potential existing styles
+                >
+                  {schema.label}
+                </MenuItem>
+              ))}
+            </Select>
+          </FormControl>
         ),
         ),
       })),
       })),
     [tableHeads, ArrowIcon, schemaOptions, insertTrans, handleTableHeadChange]
     [tableHeads, ArrowIcon, schemaOptions, insertTrans, handleTableHeadChange]

+ 3 - 0
client/src/pages/user/User.tsx

@@ -17,6 +17,7 @@ import UpdateUserRole from './dialogs/UpdateUserRole';
 import UpdateUser from './dialogs/UpdateUserPassDialog';
 import UpdateUser from './dialogs/UpdateUserPassDialog';
 import { ALL_ROUTER_TYPES } from '@/router/consts';
 import { ALL_ROUTER_TYPES } from '@/router/consts';
 import type { UserWithRoles } from '@server/types';
 import type { UserWithRoles } from '@server/types';
+import { getLabelDisplayedRows } from '@/pages/search/Utils';
 
 
 const Users = () => {
 const Users = () => {
   useNavigationHook(ALL_ROUTER_TYPES.USER);
   useNavigationHook(ALL_ROUTER_TYPES.USER);
@@ -34,6 +35,7 @@ const Users = () => {
   const { t: userTrans } = useTranslation('user');
   const { t: userTrans } = useTranslation('user');
   const { t: btnTrans } = useTranslation('btn');
   const { t: btnTrans } = useTranslation('btn');
   const { t: dialogTrans } = useTranslation('dialog');
   const { t: dialogTrans } = useTranslation('dialog');
+  const { t: commonTrans } = useTranslation();
 
 
   const fetchUsers = async () => {
   const fetchUsers = async () => {
     setLoading(true);
     setLoading(true);
@@ -268,6 +270,7 @@ const Users = () => {
         order={order}
         order={order}
         orderBy={orderBy}
         orderBy={orderBy}
         handleSort={handleGridSort}
         handleSort={handleGridSort}
+        labelDisplayedRows={getLabelDisplayedRows(commonTrans('grid.users'))}
       />
       />
     </Wrapper>
     </Wrapper>
   );
   );