Bläddra i källkod

Fix grid page height and width jittering (#554)

* make column fixed width

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

* fix grids

Signed-off-by: ryjiang <jiangruiyi@gmail.com>

---------

Signed-off-by: ryjiang <jiangruiyi@gmail.com>
ryjiang 1 år sedan
förälder
incheckning
199bcce033

+ 0 - 1
client/src/components/grid/Table.tsx

@@ -28,7 +28,6 @@ const useStyles = makeStyles(theme => ({
   },
   table: {
     minWidth: '100%',
-    minHeight: 57,
   },
   tableCell: {
     background: theme.palette.common.white,

+ 40 - 35
client/src/components/grid/TableHead.tsx

@@ -78,44 +78,49 @@ const EnhancedTableHead: FC<TableHeadType> = props => {
           </TableCell>
         )}
 
-        {colDefinitions.map(headCell => (
-          <TableCell
-            key={headCell.id + headCell.label}
-            align={headCell.align || 'left'}
-            padding={headCell.disablePadding ? 'none' : 'normal'}
-            sortDirection={
-              orderBy === (headCell.sortBy || headCell.id) ? order : false
-            }
-            className={classes.tableCell}
-            role="cell"
-          >
-            {headCell.label && handleSort && !headCell.notSort ? (
-              <TableSortLabel
-                active={orderBy === (headCell.sortBy || headCell.id)}
-                direction={
-                  orderBy === (headCell.sortBy || headCell.id) ? order : 'asc'
-                }
-                onClick={createSortHandler(headCell.sortBy || headCell.id)}
-              >
+        {colDefinitions.map(headCell => {
+          const cellStyle = headCell.getStyle ? headCell.getStyle(headCell) : {};
+
+          return (
+            <TableCell
+              key={headCell.id + headCell.label}
+              align={headCell.align || 'left'}
+              padding={headCell.disablePadding ? 'none' : 'normal'}
+              sortDirection={
+                orderBy === (headCell.sortBy || headCell.id) ? order : false
+              }
+              style={cellStyle}
+              className={classes.tableCell}
+              role="cell"
+            >
+              {headCell.label && handleSort && !headCell.notSort ? (
+                <TableSortLabel
+                  active={orderBy === (headCell.sortBy || headCell.id)}
+                  direction={
+                    orderBy === (headCell.sortBy || headCell.id) ? order : 'asc'
+                  }
+                  onClick={createSortHandler(headCell.sortBy || headCell.id)}
+                >
+                  <Typography variant="body1" className={classes.tableHeader}>
+                    {headCell.label}
+                  </Typography>
+
+                  {orderBy === (headCell.sortBy || headCell.id) ? (
+                    <Typography className={classes.visuallyHidden}>
+                      {order === 'desc'
+                        ? 'sorted descending'
+                        : 'sorted ascending'}
+                    </Typography>
+                  ) : null}
+                </TableSortLabel>
+              ) : (
                 <Typography variant="body1" className={classes.tableHeader}>
                   {headCell.label}
                 </Typography>
-
-                {orderBy === (headCell.sortBy || headCell.id) ? (
-                  <Typography className={classes.visuallyHidden}>
-                    {order === 'desc'
-                      ? 'sorted descending'
-                      : 'sorted ascending'}
-                  </Typography>
-                ) : null}
-              </TableSortLabel>
-            ) : (
-              <Typography variant="body1" className={classes.tableHeader}>
-                {headCell.label}
-              </Typography>
-            )}
-          </TableCell>
-        ))}
+              )}
+            </TableCell>
+          );
+        })}
       </TableRow>
     </TableHead>
   );

+ 18 - 0
client/src/pages/databases/collections/Collections.tsx

@@ -356,6 +356,9 @@ const Collections = () => {
           </Link>
         );
       },
+      getStyle: () => {
+        return { minWidth: '200px' };
+      },
       label: collectionTrans('name'),
     },
     {
@@ -373,6 +376,9 @@ const Collections = () => {
           />
         );
       },
+      getStyle: () => {
+        return { minWidth: '130px' };
+      },
     },
     {
       id: 'rowCount',
@@ -390,6 +396,9 @@ const Collections = () => {
       formatter(v) {
         return formatNumber(v.rowCount);
       },
+      getStyle: () => {
+        return { minWidth: '150px' };
+      },
     },
     {
       id: 'description',
@@ -403,6 +412,9 @@ const Collections = () => {
       formatter(v) {
         return v.description || '--';
       },
+      getStyle: () => {
+        return { minWidth: '150px' };
+      },
     },
     {
       id: 'createdTime',
@@ -412,6 +424,9 @@ const Collections = () => {
       formatter(data) {
         return new Date(data.createdTime).toLocaleString();
       },
+      getStyle: () => {
+        return { minWidth: '165px' };
+      },
     },
     {
       id: 'import',
@@ -464,6 +479,9 @@ const Collections = () => {
       formatter(v) {
         return <Aliases aliases={v.aliases} collection={v} />;
       },
+      getStyle: () => {
+        return { minWidth: '120px' };
+      },
     });
   }
 

+ 10 - 1
client/src/pages/databases/collections/data/CollectionData.tsx

@@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
 import { rootContext, dataContext } from '@/context';
 import { DataService } from '@/http';
 import { useQuery } from '@/hooks';
-import { saveCsvAs } from '@/utils';
+import { saveCsvAs, getColumnWidth } from '@/utils';
 import icons from '@/components/icons/Icons';
 import CustomButton from '@/components/customButton/CustomButton';
 import AttuGrid from '@/components/grid/Grid';
@@ -415,6 +415,15 @@ const CollectionData = (props: CollectionDataProps) => {
                       return cellData;
                   }
                 },
+                field: i,
+                getStyle: d => {
+                  if (!d.field) {
+                    return {};
+                  }
+                  return {
+                    minWidth: getColumnWidth(d.field),
+                  };
+                },
                 label:
                   i.name === DYNAMIC_FIELD
                     ? searchTrans('dynamicFields')

+ 10 - 0
client/src/pages/databases/collections/properties/Properties.tsx

@@ -180,6 +180,11 @@ const Properties = (props: PropertiesProps) => {
       disablePadding: false,
       label: t('property'),
       needCopy: true,
+      getStyle: () => {
+        return {
+          minWidth: 150,
+        };
+      },
     },
     {
       id: 'value',
@@ -193,6 +198,11 @@ const Properties = (props: PropertiesProps) => {
           return obj.type === 'number' ? formatNumber(obj.value) : obj.value;
         }
       },
+      getStyle: () => {
+        return {
+          minWidth: 450,
+        };
+      },
     },
   ];
 

+ 34 - 7
client/src/pages/databases/collections/search/Search.tsx

@@ -29,6 +29,7 @@ import {
   saveCsvAs,
   buildSearchParams,
   buildSearchCode,
+  getColumnWidth,
 } from '@/utils';
 import SearchParams from '../../../search/SearchParams';
 import {
@@ -244,13 +245,38 @@ const Search = (props: CollectionDataProps) => {
             const invalidItems = primaryKeyField === 'id' ? [] : ['id'];
             return !invalidItems.includes(item);
           })
-          .map(key => ({
-            id: key,
-            align: 'left',
-            disablePadding: false,
-            label: key === DYNAMIC_FIELD ? searchTrans('dynamicFields') : key,
-            needCopy: key !== 'score',
-          }))
+          .map(key => {
+            // find the field
+            const field = searchParams.collection.schema!.scalarFields.find(
+              f => f.name === key
+            );
+            return {
+              id: key,
+              align: 'left',
+              disablePadding: false,
+              label: key === DYNAMIC_FIELD ? searchTrans('dynamicFields') : key,
+              needCopy: key !== 'score',
+              field: field,
+              getStyle: d => {
+                if (d.id === 'score') {
+                  return {
+                    minWidth: 180,
+                  };
+                }
+                if (d.id === DYNAMIC_FIELD) {
+                  return {
+                    minWidth: 180,
+                  };
+                }
+                if (!d.field) {
+                  return {};
+                }
+                return {
+                  minWidth: getColumnWidth(d.field),
+                };
+              },
+            };
+          })
       : [];
   }, [JSON.stringify({ searchParams, outputFields })]);
 
@@ -516,6 +542,7 @@ const Search = (props: CollectionDataProps) => {
                 rowCount={total}
                 primaryKey="rank"
                 page={currentPage}
+                tableHeaderHeight={46}
                 rowHeight={39}
                 onPageChange={handlePageChange}
                 rowsPerPage={pageSize}

+ 30 - 0
client/src/pages/databases/collections/segments/Segments.tsx

@@ -111,6 +111,11 @@ const Segments = () => {
       disablePadding: false,
       needCopy: true,
       label: collectionTrans('segmentID'),
+      getStyle: () => {
+        return {
+          minWidth: 190,
+        };
+      },
     },
     {
       id: 'partitionID',
@@ -118,18 +123,33 @@ const Segments = () => {
       disablePadding: false,
       needCopy: true,
       label: collectionTrans('partitionID'),
+      getStyle: () => {
+        return {
+          minWidth: 190,
+        };
+      },
     },
     {
       id: 'state',
       align: 'left',
       disablePadding: false,
       label: collectionTrans('segPState'),
+      getStyle: () => {
+        return {
+          minWidth: 200,
+        };
+      },
     },
     {
       id: 'num_rows',
       align: 'left',
       disablePadding: false,
       label: collectionTrans('num_rows'),
+      getStyle: () => {
+        return {
+          minWidth: 100,
+        };
+      },
     },
     {
       id: 'q_nodeIds',
@@ -139,12 +159,22 @@ const Segments = () => {
       formatter(data, cellData, cellIndex) {
         return cellData.join(',');
       },
+      getStyle: () => {
+        return {
+          minWidth: 140,
+        };
+      },
     },
     {
       id: 'q_state',
       align: 'left',
       disablePadding: false,
       label: collectionTrans('q_state'),
+      getStyle: () => {
+        return {
+          minWidth: 200,
+        };
+      },
     },
     // {
     //   id: 'q_index_name',

+ 31 - 0
client/src/utils/Format.ts

@@ -11,6 +11,7 @@ import {
 } from '@/pages/databases/collections/Types';
 import { FieldObject } from '@server/types';
 import { generateVector } from './';
+import { get } from 'http';
 
 /**
  * transform large capacity to capacity in b.
@@ -306,3 +307,33 @@ export const VectorStrToObject = {
   [DataTypeStringEnum.BFloat16Vector]: arrayFormatter,
   [DataTypeStringEnum.SparseFloatVector]: sparseVectorFormatter,
 };
+
+export const getColumnWidth = (field: FieldObject): number => {
+  switch (field.data_type) {
+    case DataTypeStringEnum.Int64:
+    case DataTypeStringEnum.Int32:
+    case DataTypeStringEnum.Int16:
+    case DataTypeStringEnum.Int8:
+      return 200;
+    case DataTypeStringEnum.Float:
+      return 200;
+
+    case DataTypeStringEnum.VarChar:
+      const varCharWidth = field.maxLength * 10;
+      return varCharWidth > 350 ? 350 : varCharWidth; 
+
+    case DataTypeStringEnum.Bool:
+      return 80;
+
+    case DataTypeStringEnum.Array:
+      const width =
+        getColumnWidth({
+          ...field,
+          data_type: field.element_type as any,
+        }) * field.maxCapacity;
+      return width > 350 ? 350 : width;
+
+    default:
+      return 350;
+  }
+};