Browse Source

Merge pull request #223 from nameczz/dev

Impore table sort
ryjiang 3 years ago
parent
commit
32cc5cb208

+ 0 - 19
client/src/components/__test__/grid/Grid.spec.tsx

@@ -91,25 +91,6 @@ describe('Test Grid index', () => {
     expect(titleNodes[1].textContent).toEqual(title[1]);
     expect(titleNodes[1].textContent).toEqual(title[1]);
   });
   });
 
 
-  it('Test SearchForm', () => {
-    const SearchForm = () => <div id="search-form"></div>;
-    act(() => {
-      render(
-        <MilvusGrid
-          primaryKey="id"
-          rows={[]}
-          colDefinitions={[]}
-          rowCount={0}
-          toolbarConfigs={[]}
-          searchForm={<SearchForm />}
-        />,
-        container
-      );
-    });
-
-    expect(container.querySelectorAll('#search-form').length).toEqual(1);
-  });
-
   it('Test Toolbar ', () => {
   it('Test Toolbar ', () => {
     const ToolbarConfig: ToolBarConfig[] = [
     const ToolbarConfig: ToolBarConfig[] = [
       {
       {

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

@@ -20,12 +20,7 @@ const userStyle = makeStyles(theme => ({
     padding: theme.spacing(20),
     padding: theme.spacing(20),
     width: '100%',
     width: '100%',
   },
   },
-  titleIcon: {
-    verticalAlign: '-3px',
-    '& svg': {
-      fill: '#32363c',
-    },
-  },
+
   tableTitle: {
   tableTitle: {
     '& .last': {
     '& .last': {
       color: 'rgba(0, 0, 0, 0.54)',
       color: 'rgba(0, 0, 0, 0.54)',
@@ -71,6 +66,31 @@ const userStyle = makeStyles(theme => ({
   },
   },
 }));
 }));
 
 
+/**
+ *
+ * @param rowCount required. totoal data count for pagination
+ * @param rowsPerPage per page for pagination, default is 10
+ * @param primaryKey required. The unique column for your data. use for checkbox and render key.
+ * @param onChangePage handle page change
+ * @param labelDisplayedRows Custom pagination label function, return string;
+ * @param page current page for pagination
+ * @param showToolbar control toolbar display. default is false
+ * @param rows table data you want to render
+ * @param colDefinitions Define how to render table heder.
+ * @param isLoading table loading status
+ * @param title  Render breadcrumbs
+ * @param openCheckBox control checkbox display. default is true
+ * @param disableSelect disable table row select. default false
+ * @param noData when table is empty, what tip we need to show.
+ * @param showHoverStyle control table row hover style display
+ * @param headEditable if true, user can edit header.
+ * @param editHeads Only headEditable is true will render editHeads
+ * @param tableCellMaxWidth Define table cell max width, default is 300
+ * @param handlesort how to sort table, if it's undefined, then you can not sort table
+ * @param order 'desc' | 'asc'. sort direction
+ * @param order order by which table field
+ * @returns
+ */
 const MilvusGrid: FC<MilvusGridType> = props => {
 const MilvusGrid: FC<MilvusGridType> = props => {
   const classes = userStyle();
   const classes = userStyle();
 
 
@@ -79,8 +99,8 @@ const MilvusGrid: FC<MilvusGridType> = props => {
   const gridTrans = commonTrans('grid');
   const gridTrans = commonTrans('grid');
 
 
   const {
   const {
-    rowCount = 10,
-    rowsPerPage = 5,
+    rowCount = 20,
+    rowsPerPage = 10,
     primaryKey = 'id',
     primaryKey = 'id',
     showToolbar = false,
     showToolbar = false,
     toolbarConfigs = [],
     toolbarConfigs = [],
@@ -91,14 +111,11 @@ const MilvusGrid: FC<MilvusGridType> = props => {
       console.log('nextPageNum', nextPageNum);
       console.log('nextPageNum', nextPageNum);
     },
     },
     labelDisplayedRows,
     labelDisplayedRows,
-    // pageUnit = 'item',
     page = 0,
     page = 0,
     rows = [],
     rows = [],
     colDefinitions = [],
     colDefinitions = [],
     isLoading = false,
     isLoading = false,
     title,
     title,
-    // titleIcon = <CollectionIcon />,
-    searchForm,
     openCheckBox = true,
     openCheckBox = true,
     disableSelect = false,
     disableSelect = false,
     noData = gridTrans.noData,
     noData = gridTrans.noData,
@@ -109,6 +126,9 @@ const MilvusGrid: FC<MilvusGridType> = props => {
     setSelected = () => {},
     setSelected = () => {},
     setRowsPerPage = () => {},
     setRowsPerPage = () => {},
     tableCellMaxWidth,
     tableCellMaxWidth,
+    handleSort,
+    order,
+    orderBy,
   } = props;
   } = props;
 
 
   const _isSelected = (row: { [x: string]: any }) => {
   const _isSelected = (row: { [x: string]: any }) => {
@@ -136,16 +156,6 @@ const MilvusGrid: FC<MilvusGridType> = props => {
     setSelected([]);
     setSelected([]);
   };
   };
 
 
-  // const defaultLabelRows = ({ from = 0, to = 0, count = 0 }) => {
-  //   const plural = pageUnit.charAt(pageUnit.length - 1) === 'y' ? 'ies' : 's';
-  //   const formatUnit =
-  //     pageUnit.charAt(pageUnit.length - 1) === 'y'
-  //       ? pageUnit.slice(0, pageUnit.length - 1)
-  //       : pageUnit;
-  //   const unit = count > 1 ? `${formatUnit}${plural}` : pageUnit;
-  //   return `${count} ${unit}`;
-  // };
-
   const defaultLabelRows = ({ from = 0, to = 0, count = 0 }) => {
   const defaultLabelRows = ({ from = 0, to = 0, count = 0 }) => {
     return (
     return (
       <>
       <>
@@ -184,12 +194,6 @@ const MilvusGrid: FC<MilvusGridType> = props => {
         </Grid>
         </Grid>
       )}
       )}
 
 
-      {searchForm && (
-        <Grid item xs={12}>
-          {searchForm}
-        </Grid>
-      )}
-
       {(showToolbar || toolbarConfigs.length > 0) && (
       {(showToolbar || toolbarConfigs.length > 0) && (
         <Grid item>
         <Grid item>
           <CustomToolbar
           <CustomToolbar
@@ -217,6 +221,9 @@ const MilvusGrid: FC<MilvusGridType> = props => {
           headEditable={headEditable}
           headEditable={headEditable}
           editHeads={editHeads}
           editHeads={editHeads}
           tableCellMaxWidth={tableCellMaxWidth}
           tableCellMaxWidth={tableCellMaxWidth}
+          handleSort={handleSort}
+          order={order}
+          orderBy={orderBy}
         ></Table>
         ></Table>
         {rowCount ? (
         {rowCount ? (
           <TablePagination
           <TablePagination

+ 108 - 138
client/src/components/grid/Table.tsx

@@ -11,7 +11,6 @@ import { TableType } from './Types';
 import { Box, Button, Typography } from '@material-ui/core';
 import { Box, Button, Typography } from '@material-ui/core';
 import EnhancedTableHead from './TableHead';
 import EnhancedTableHead from './TableHead';
 import EditableTableHead from './TableEditableHead';
 import EditableTableHead from './TableEditableHead';
-import { stableSort, getComparator } from './Utils';
 import ActionBar from './ActionBar';
 import ActionBar from './ActionBar';
 import LoadingTable from './LoadingTable';
 import LoadingTable from './LoadingTable';
 import CopyButton from '../advancedSearch/CopyButton';
 import CopyButton from '../advancedSearch/CopyButton';
@@ -129,11 +128,11 @@ const EnhancedTable: FC<TableType> = props => {
     editHeads = [],
     editHeads = [],
     // if table cell max width not be passed, table row will use 300px as default
     // if table cell max width not be passed, table row will use 300px as default
     tableCellMaxWidth = '300px',
     tableCellMaxWidth = '300px',
+    handleSort,
+    order,
+    orderBy,
   } = props;
   } = props;
   const classes = useStyles({ tableCellMaxWidth });
   const classes = useStyles({ tableCellMaxWidth });
-  const [order, setOrder] = React.useState('asc');
-  const [orderBy, setOrderBy] = React.useState<string>('');
-  const [tableMouseStatus, setTableMouseStatus] = React.useState<boolean[]>([]);
   const [loadingRowCount, setLoadingRowCount] = useState<number>(0);
   const [loadingRowCount, setLoadingRowCount] = useState<number>(0);
 
 
   const containerRef = useRef(null);
   const containerRef = useRef(null);
@@ -141,12 +140,6 @@ const EnhancedTable: FC<TableType> = props => {
   const { t: commonTrans } = useTranslation();
   const { t: commonTrans } = useTranslation();
   const copyTrans = commonTrans('copy');
   const copyTrans = commonTrans('copy');
 
 
-  const handleRequestSort = (event: any, property: string) => {
-    const isAsc = orderBy === property && order === 'asc';
-    setOrder(isAsc ? 'desc' : 'asc');
-    setOrderBy(property);
-  };
-
   useEffect(() => {
   useEffect(() => {
     const height: number = (containerRef.current as any)!.offsetHeight;
     const height: number = (containerRef.current as any)!.offsetHeight;
     // table header 57px, loading row 40px
     // table header 57px, loading row 40px
@@ -190,7 +183,7 @@ const EnhancedTable: FC<TableType> = props => {
               order={order}
               order={order}
               orderBy={orderBy}
               orderBy={orderBy}
               onSelectAllClick={onSelectedAll}
               onSelectAllClick={onSelectedAll}
-              onRequestSort={handleRequestSort}
+              handleSort={handleSort}
               rowCount={rows.length}
               rowCount={rows.length}
               openCheckBox={openCheckBox}
               openCheckBox={openCheckBox}
             />
             />
@@ -200,139 +193,116 @@ const EnhancedTable: FC<TableType> = props => {
           {!isLoading && (
           {!isLoading && (
             <TableBody>
             <TableBody>
               {rows && rows.length ? (
               {rows && rows.length ? (
-                stableSort(rows, getComparator(order, orderBy)).map(
-                  (row, index) => {
-                    const isItemSelected = isSelected(row);
-                    const labelId = `enhanced-table-checkbox-${index}`;
+                rows.map((row, index) => {
+                  const isItemSelected = isSelected(row);
+                  const labelId = `enhanced-table-checkbox-${index}`;
 
 
-                    const handleMouseEnter = () => {
-                      setTableMouseStatus(v => {
-                        const copy = [...v];
-                        copy[index] = true;
-                        return copy;
-                      });
-                    };
-                    const handleMouseLeave = () =>
-                      setTableMouseStatus(v => {
-                        const copy = [...v];
-                        copy[index] = false;
-                        return copy;
-                      });
+                  return (
+                    <TableRow
+                      hover={showHoverStyle}
+                      key={'row' + row[primaryKey] + index}
+                      onClick={event => onSelected(event, row)}
+                      role="checkbox"
+                      aria-checked={isItemSelected}
+                      tabIndex={-1}
+                      selected={isItemSelected && !disableSelect}
+                      classes={{
+                        hover: classes.rowHover,
+                      }}
+                    >
+                      {openCheckBox && (
+                        <TableCell
+                          padding="checkbox"
+                          className={classes.checkbox}
+                        >
+                          <Checkbox
+                            checked={isItemSelected}
+                            color="primary"
+                            inputProps={{ 'aria-labelledby': labelId }}
+                          />
+                        </TableCell>
+                      )}
 
 
-                    return (
-                      <TableRow
-                        hover={showHoverStyle}
-                        key={'row' + row[primaryKey] + index}
-                        onClick={event => onSelected(event, row)}
-                        role="checkbox"
-                        aria-checked={isItemSelected}
-                        tabIndex={-1}
-                        selected={isItemSelected && !disableSelect}
-                        classes={{
-                          hover: classes.rowHover,
-                        }}
-                        onMouseEnter={handleMouseEnter}
-                        onMouseLeave={handleMouseLeave}
-                      >
-                        {openCheckBox && (
+                      {colDefinitions.map((colDef, i) => {
+                        const { actionBarConfigs = [], needCopy = false } =
+                          colDef;
+                        const cellStyle = colDef.getStyle
+                          ? colDef.getStyle(row[colDef.id])
+                          : {};
+                        return colDef.showActionCell ? (
                           <TableCell
                           <TableCell
-                            padding="checkbox"
-                            className={classes.checkbox}
+                            className={`${classes.cell} ${classes.tableCell} ${
+                              colDef.isHoverAction
+                                ? classes.hoverActionCell
+                                : ''
+                            }`}
+                            key="manage"
+                            style={cellStyle}
                           >
                           >
-                            <Checkbox
-                              checked={isItemSelected}
-                              color="primary"
-                              inputProps={{ 'aria-labelledby': labelId }}
-                            />
+                            <ActionBar
+                              configs={actionBarConfigs}
+                              isHoverType={colDef.isHoverAction}
+                              row={row}
+                            ></ActionBar>
                           </TableCell>
                           </TableCell>
-                        )}
-
-                        {colDefinitions.map((colDef, i) => {
-                          const { actionBarConfigs = [], needCopy = false } =
-                            colDef;
-                          const cellStyle = colDef.getStyle
-                            ? colDef.getStyle(row[colDef.id])
-                            : {};
-                          return colDef.showActionCell ? (
-                            <TableCell
-                              className={`${classes.cell} ${
-                                classes.tableCell
-                              } ${
-                                colDef.isHoverAction
-                                  ? classes.hoverActionCell
-                                  : ''
-                              }`}
-                              key="manage"
-                              style={cellStyle}
-                            >
-                              <ActionBar
-                                showLabel={tableMouseStatus[index]}
-                                configs={actionBarConfigs}
-                                isHoverType={colDef.isHoverAction}
-                                row={row}
-                              ></ActionBar>
-                            </TableCell>
-                          ) : (
-                            <TableCell
-                              key={'cell' + row[primaryKey] + i}
-                              // padding={i === 0 ? 'none' : 'default'}
-                              align={colDef.align || 'left'}
-                              className={`${classes.cell} ${classes.tableCell}`}
-                              style={cellStyle}
-                            >
-                              {row[colDef.id] &&
-                              typeof row[colDef.id] === 'string' ? (
-                                <Typography title={row[colDef.id]}>
-                                  {colDef.onClick ? (
-                                    <Button
-                                      color="primary"
-                                      data-data={row[colDef.id]}
-                                      data-index={index}
-                                      onClick={e => {
-                                        colDef.onClick &&
-                                          colDef.onClick(e, row);
-                                      }}
-                                    >
-                                      {row[colDef.id]}
-                                    </Button>
-                                  ) : (
-                                    row[colDef.id]
-                                  )}
-                                </Typography>
-                              ) : (
-                                <>
-                                  {colDef.onClick ? (
-                                    <Button
-                                      color="primary"
-                                      data-data={row[colDef.id]}
-                                      data-index={index}
-                                      onClick={e => {
-                                        colDef.onClick &&
-                                          colDef.onClick(e, row);
-                                      }}
-                                    >
-                                      {row[colDef.id]}
-                                    </Button>
-                                  ) : (
-                                    row[colDef.id]
-                                  )}
-                                </>
-                              )}
+                        ) : (
+                          <TableCell
+                            key={'cell' + row[primaryKey] + i}
+                            // padding={i === 0 ? 'none' : 'default'}
+                            align={colDef.align || 'left'}
+                            className={`${classes.cell} ${classes.tableCell}`}
+                            style={cellStyle}
+                          >
+                            {row[colDef.id] &&
+                            typeof row[colDef.id] === 'string' ? (
+                              <Typography title={row[colDef.id]}>
+                                {colDef.onClick ? (
+                                  <Button
+                                    color="primary"
+                                    data-data={row[colDef.id]}
+                                    data-index={index}
+                                    onClick={e => {
+                                      colDef.onClick && colDef.onClick(e, row);
+                                    }}
+                                  >
+                                    {row[colDef.id]}
+                                  </Button>
+                                ) : (
+                                  row[colDef.id]
+                                )}
+                              </Typography>
+                            ) : (
+                              <>
+                                {colDef.onClick ? (
+                                  <Button
+                                    color="primary"
+                                    data-data={row[colDef.id]}
+                                    data-index={index}
+                                    onClick={e => {
+                                      colDef.onClick && colDef.onClick(e, row);
+                                    }}
+                                  >
+                                    {row[colDef.id]}
+                                  </Button>
+                                ) : (
+                                  row[colDef.id]
+                                )}
+                              </>
+                            )}
 
 
-                              {needCopy && row[colDef.id] && (
-                                <CopyButton
-                                  label={copyTrans.label}
-                                  value={row[colDef.id]}
-                                  className={classes.copyBtn}
-                                />
-                              )}
-                            </TableCell>
-                          );
-                        })}
-                      </TableRow>
-                    );
-                  }
-                )
+                            {needCopy && row[colDef.id] && (
+                              <CopyButton
+                                label={copyTrans.label}
+                                value={row[colDef.id]}
+                                className={classes.copyBtn}
+                              />
+                            )}
+                          </TableCell>
+                        );
+                      })}
+                    </TableRow>
+                  );
+                })
               ) : (
               ) : (
                 <tr>
                 <tr>
                   <td
                   <td

+ 3 - 3
client/src/components/grid/TableHead.tsx

@@ -46,12 +46,12 @@ const EnhancedTableHead: FC<TableHeadType> = props => {
     numSelected,
     numSelected,
     rowCount,
     rowCount,
     colDefinitions = [],
     colDefinitions = [],
-    onRequestSort,
+    handleSort,
     openCheckBox,
     openCheckBox,
   } = props;
   } = props;
   const classes = useStyles();
   const classes = useStyles();
   const createSortHandler = (property: string) => (event: React.MouseEvent) => {
   const createSortHandler = (property: string) => (event: React.MouseEvent) => {
-    onRequestSort(event, property);
+    handleSort && handleSort(event, property);
   };
   };
 
 
   return (
   return (
@@ -79,7 +79,7 @@ const EnhancedTableHead: FC<TableHeadType> = props => {
             }
             }
             className={classes.tableCell}
             className={classes.tableCell}
           >
           >
-            {headCell.label && !headCell.notSort ? (
+            {headCell.label && handleSort && !headCell.notSort ? (
               <TableSortLabel
               <TableSortLabel
                 active={orderBy === (headCell.sortBy || headCell.id)}
                 active={orderBy === (headCell.sortBy || headCell.id)}
                 direction={
                 direction={

+ 12 - 8
client/src/components/grid/Types.ts

@@ -1,6 +1,6 @@
 import { IconsType } from '../icons/Types';
 import { IconsType } from '../icons/Types';
 import { SearchType } from '../customInput/Types';
 import { SearchType } from '../customInput/Types';
-import { ReactElement } from 'react';
+import React, { ReactElement } from 'react';
 
 
 export type IconConfigType = {
 export type IconConfigType = {
   [x: string]: JSX.Element;
   [x: string]: JSX.Element;
@@ -8,6 +8,8 @@ export type IconConfigType = {
 
 
 export type ColorType = 'default' | 'inherit' | 'primary' | 'secondary';
 export type ColorType = 'default' | 'inherit' | 'primary' | 'secondary';
 
 
+export type SortDirection = 'asc' | 'desc';
+
 /**
 /**
  * selected: selected data in table checkbox
  * selected: selected data in table checkbox
  */
  */
@@ -47,12 +49,12 @@ export type ToolBarConfig = Partial<TableSwitchType> &
 
 
 export type TableHeadType = {
 export type TableHeadType = {
   onSelectAllClick: (e: React.ChangeEvent) => void;
   onSelectAllClick: (e: React.ChangeEvent) => void;
-  order: any;
-  orderBy: string;
+  order?: SortDirection;
+  orderBy?: string;
   numSelected: number;
   numSelected: number;
   rowCount: number;
   rowCount: number;
   colDefinitions: ColDefinitionsType[];
   colDefinitions: ColDefinitionsType[];
-  onRequestSort: (e: any, p: string) => void;
+  handleSort?: (e: any, p: string) => void;
   openCheckBox?: boolean;
   openCheckBox?: boolean;
 };
 };
 
 
@@ -83,6 +85,9 @@ export type TableType = {
   editHeads: EditableHeads[];
   editHeads: EditableHeads[];
   // with unit like '20px'
   // with unit like '20px'
   tableCellMaxWidth?: string;
   tableCellMaxWidth?: string;
+  handleSort?: (e: any, orderBy: string) => void;
+  order?: SortDirection;
+  orderBy?: string;
 };
 };
 
 
 export type ColDefinitionsType = {
 export type ColDefinitionsType = {
@@ -123,10 +128,7 @@ export type MilvusGridType = ToolBarType & {
   colDefinitions: ColDefinitionsType[];
   colDefinitions: ColDefinitionsType[];
   isLoading?: boolean;
   isLoading?: boolean;
   title?: string[];
   title?: string[];
-  searchForm?: React.ReactNode;
   openCheckBox?: boolean;
   openCheckBox?: boolean;
-  titleIcon?: React.ReactNode;
-  pageUnit?: string;
   disableSelect?: boolean;
   disableSelect?: boolean;
   noData?: string;
   noData?: string;
   showHoverStyle?: boolean;
   showHoverStyle?: boolean;
@@ -134,12 +136,14 @@ export type MilvusGridType = ToolBarType & {
   editHeads?: EditableHeads[];
   editHeads?: EditableHeads[];
   // with unit like '20px'
   // with unit like '20px'
   tableCellMaxWidth?: string;
   tableCellMaxWidth?: string;
+  handleSort?: (e: any, orderBy: string) => void;
+  order?: SortDirection;
+  orderBy?: string;
 };
 };
 
 
 export type ActionBarType = {
 export type ActionBarType = {
   configs: ActionBarConfig[];
   configs: ActionBarConfig[];
   row: any;
   row: any;
-  showLabel?: boolean;
   isHoverType?: boolean;
   isHoverType?: boolean;
 };
 };
 
 

+ 17 - 2
client/src/hooks/Pagination.ts

@@ -1,18 +1,25 @@
 import { useMemo, useState } from 'react';
 import { useMemo, useState } from 'react';
+import { stableSort, getComparator } from '../utils/Sort';
 
 
 export const usePaginationHook = (list: any[]) => {
 export const usePaginationHook = (list: any[]) => {
   const [currentPage, setCurrentPage] = useState(0);
   const [currentPage, setCurrentPage] = useState(0);
   const [pageSize, setPageSize] = useState(10);
   const [pageSize, setPageSize] = useState(10);
+  const [orderBy, setOrderBy] = useState('');
+  const [order, setOrder] = useState<'asc' | 'desc'>('asc');
 
 
   const total = list.length;
   const total = list.length;
   const { data, offset } = useMemo(() => {
   const { data, offset } = useMemo(() => {
     const offset = pageSize * currentPage;
     const offset = pageSize * currentPage;
-    const data = list.slice(offset, offset + pageSize);
+    // only when user click sort, orderBy will have value
+    const sortList = orderBy
+      ? stableSort(list, getComparator(order || 'asc', orderBy))
+      : list;
+    const data = sortList.slice(offset, offset + pageSize);
     return {
     return {
       offset,
       offset,
       data,
       data,
     };
     };
-  }, [list, currentPage, pageSize]);
+  }, [pageSize, currentPage, orderBy, list, order]);
 
 
   const handleCurrentPage = (page: number) => {
   const handleCurrentPage = (page: number) => {
     setCurrentPage(page);
     setCurrentPage(page);
@@ -21,6 +28,11 @@ export const usePaginationHook = (list: any[]) => {
   const handlePageSize = (size: number) => {
   const handlePageSize = (size: number) => {
     setPageSize(size);
     setPageSize(size);
   };
   };
+  const handleGridSort = (e: any, property: string) => {
+    const isAsc = orderBy === property && order === 'asc';
+    setOrder(isAsc ? 'desc' : 'asc');
+    setOrderBy(property);
+  };
 
 
   return {
   return {
     offset,
     offset,
@@ -30,5 +42,8 @@ export const usePaginationHook = (list: any[]) => {
     handleCurrentPage,
     handleCurrentPage,
     total,
     total,
     data,
     data,
+    handleGridSort,
+    orderBy,
+    order,
   };
   };
 };
 };

+ 7 - 0
client/src/pages/collections/Collections.tsx

@@ -66,6 +66,7 @@ const Collections = () => {
   const { handleAction } = useLoadAndReleaseDialogHook({ type: 'collection' });
   const { handleAction } = useLoadAndReleaseDialogHook({ type: 'collection' });
   const { handleInsertDialog } = useInsertDialogHook();
   const { handleInsertDialog } = useInsertDialogHook();
   const [collections, setCollections] = useState<CollectionView[]>([]);
   const [collections, setCollections] = useState<CollectionView[]>([]);
+
   const [searchedCollections, setSearchedCollections] = useState<
   const [searchedCollections, setSearchedCollections] = useState<
     CollectionView[]
     CollectionView[]
   >([]);
   >([]);
@@ -76,6 +77,9 @@ const Collections = () => {
     handleCurrentPage,
     handleCurrentPage,
     total,
     total,
     data: collectionList,
     data: collectionList,
+    handleGridSort,
+    order,
+    orderBy,
   } = usePaginationHook(searchedCollections);
   } = usePaginationHook(searchedCollections);
   const [loading, setLoading] = useState<boolean>(true);
   const [loading, setLoading] = useState<boolean>(true);
   const [selectedCollections, setSelectedCollections] = useState<
   const [selectedCollections, setSelectedCollections] = useState<
@@ -433,6 +437,9 @@ const Collections = () => {
           rowsPerPage={pageSize}
           rowsPerPage={pageSize}
           setRowsPerPage={handlePageSize}
           setRowsPerPage={handlePageSize}
           isLoading={loading}
           isLoading={loading}
+          handleSort={handleGridSort}
+          order={order}
+          orderBy={orderBy}
         />
         />
       ) : (
       ) : (
         <>
         <>

+ 6 - 0
client/src/pages/partitions/Partitions.tsx

@@ -76,6 +76,9 @@ const Partitions: FC<{
     handleCurrentPage,
     handleCurrentPage,
     total,
     total,
     data: partitionList,
     data: partitionList,
+    order,
+    orderBy,
+    handleGridSort,
   } = usePaginationHook(searchedPartitions);
   } = usePaginationHook(searchedPartitions);
   const [loading, setLoading] = useState<boolean>(true);
   const [loading, setLoading] = useState<boolean>(true);
   const { setDialog, handleCloseDialog, openSnackBar } =
   const { setDialog, handleCloseDialog, openSnackBar } =
@@ -396,6 +399,9 @@ const Partitions: FC<{
         rowsPerPage={pageSize}
         rowsPerPage={pageSize}
         setRowsPerPage={handlePageSize}
         setRowsPerPage={handlePageSize}
         isLoading={loading}
         isLoading={loading}
+        order={order}
+        orderBy={orderBy}
+        handleSort={handleGridSort}
       />
       />
     </section>
     </section>
   );
   );

+ 6 - 0
client/src/pages/schema/Schema.tsx

@@ -69,6 +69,9 @@ const Schema: FC<{
     handleCurrentPage,
     handleCurrentPage,
     total,
     total,
     data: schemaList,
     data: schemaList,
+    order,
+    orderBy,
+    handleGridSort,
   } = usePaginationHook(fields);
   } = usePaginationHook(fields);
 
 
   const fetchSchemaListWithIndex = async (
   const fetchSchemaListWithIndex = async (
@@ -220,6 +223,9 @@ const Schema: FC<{
         setRowsPerPage={handlePageSize}
         setRowsPerPage={handlePageSize}
         isLoading={loading}
         isLoading={loading}
         openCheckBox={false}
         openCheckBox={false}
+        order={order}
+        orderBy={orderBy}
+        handleSort={handleGridSort}
       />
       />
     </section>
     </section>
   );
   );

+ 9 - 2
client/src/pages/seach/VectorSearch.tsx

@@ -58,8 +58,9 @@ const VectorSearch = () => {
   // search params disable state
   // search params disable state
   const [paramDisabled, setParamDisabled] = useState<boolean>(true);
   const [paramDisabled, setParamDisabled] = useState<boolean>(true);
   // use null as init value before search, empty array means no results
   // use null as init value before search, empty array means no results
-  const [searchResult, setSearchResult] =
-    useState<SearchResultView[] | null>(null);
+  const [searchResult, setSearchResult] = useState<SearchResultView[] | null>(
+    null
+  );
   // default topK is 100
   // default topK is 100
   const [topK, setTopK] = useState<number>(100);
   const [topK, setTopK] = useState<number>(100);
   const [expression, setExpression] = useState<string>('');
   const [expression, setExpression] = useState<string>('');
@@ -72,6 +73,9 @@ const VectorSearch = () => {
     handleCurrentPage,
     handleCurrentPage,
     total,
     total,
     data: result,
     data: result,
+    order,
+    orderBy,
+    handleGridSort,
   } = usePaginationHook(searchResult || []);
   } = usePaginationHook(searchResult || []);
 
 
   const collectionOptions: Option[] = useMemo(
   const collectionOptions: Option[] = useMemo(
@@ -482,6 +486,9 @@ const VectorSearch = () => {
           setRowsPerPage={handlePageSize}
           setRowsPerPage={handlePageSize}
           openCheckBox={false}
           openCheckBox={false}
           isLoading={tableLoading}
           isLoading={tableLoading}
+          orderBy={orderBy}
+          order={order}
+          handleSort={handleGridSort}
         />
         />
       ) : (
       ) : (
         <EmptyCard
         <EmptyCard

+ 0 - 0
client/src/components/grid/Utils.ts → client/src/utils/Sort.ts


+ 1 - 1
server/generate-csv.ts

@@ -18,7 +18,7 @@ const generateVector = (dimension) => {
   return JSON.stringify(vectors);
   return JSON.stringify(vectors);
 };
 };
 
 
-while (records.length < 100000) {
+while (records.length < 3000) {
   const value = generateVector(4);
   const value = generateVector(4);
   records.push({ vector: value });
   records.push({ vector: value });
 }
 }

+ 3 - 1
server/src/collections/collections.service.ts

@@ -13,7 +13,7 @@ import {
 } from '@zilliz/milvus2-sdk-node/dist/milvus/types';
 } from '@zilliz/milvus2-sdk-node/dist/milvus/types';
 import { throwErrorFromSDK } from '../utils/Error';
 import { throwErrorFromSDK } from '../utils/Error';
 import { findKeyValue } from '../utils/Helper';
 import { findKeyValue } from '../utils/Helper';
-import { LOADING_STATE, ROW_COUNT } from '../utils/Const';
+import { ROW_COUNT } from '../utils/Const';
 import {
 import {
   ShowCollectionsReq,
   ShowCollectionsReq,
   ShowCollectionsType,
   ShowCollectionsType,
@@ -141,6 +141,8 @@ export class CollectionsService {
         });
         });
       }
       }
     }
     }
+    // add default sort - Descending order
+    data.sort((a, b) => b.createdTime - a.createdTime);
     return data;
     return data;
   }
   }