Procházet zdrojové kódy

add partitin list ui

tumao před 4 roky
rodič
revize
ef6bc4fea2

+ 1 - 0
client/src/components/customTabList/CustomTabList.tsx

@@ -23,6 +23,7 @@ const useStyles = makeStyles((theme: Theme) => ({
   },
   tabPanel: {
     flexGrow: 1,
+    marginTop: theme.spacing(2),
   },
 }));
 

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

@@ -20,7 +20,7 @@ const useStyles = makeStyles(theme => ({
     // minHeight: '29vh',
     width: '100%',
     flexGrow: 1,
-    flexBasis: 0,
+    // flexBasis: 0,
 
     // change scrollbar style
     '&::-webkit-scrollbar': {

+ 4 - 8
client/src/hooks/Navigation.ts

@@ -1,6 +1,6 @@
 import { useContext, useEffect } from 'react';
 import { useTranslation } from 'react-i18next';
-import { useParams } from 'react-router';
+// import { useParams } from 'react-router-dom';
 import { navContext } from '../context/Navigation';
 import { ALL_ROUTER_TYPES, NavInfo } from '../router/Types';
 
@@ -12,11 +12,7 @@ export const useNavigationHook = (
 ) => {
   const { t } = useTranslation('nav');
   const { setNavInfo } = useContext(navContext);
-
-  const { collectionId = '' } =
-    useParams<{
-      collectionId?: string;
-    }>();
+  const { collectionName } = extraParam || { collectionName: '' };
 
   useEffect(() => {
     switch (type) {
@@ -38,7 +34,7 @@ export const useNavigationHook = (
       }
       case ALL_ROUTER_TYPES.COLLECTION_DETAIL: {
         const navInfo: NavInfo = {
-          navTitle: extraParam?.collectionName as string,
+          navTitle: collectionName,
           backPath: '/collections',
         };
         setNavInfo(navInfo);
@@ -55,5 +51,5 @@ export const useNavigationHook = (
       default:
         break;
     }
-  }, [type, extraParam, t, setNavInfo, collectionId]);
+  }, [type, t, setNavInfo, collectionName]);
 };

+ 4 - 0
client/src/i18n/cn/collection.ts

@@ -43,6 +43,10 @@ const collectionTrans = {
   // delete dialog
   deleteWarning:
     'You are trying to delete a collection with data. This action cannot be undone.',
+
+  // collection tabs
+  partitionTab: 'Partitions',
+  structureTab: 'Structure',
 };
 
 export default collectionTrans;

+ 12 - 0
client/src/i18n/cn/partition.ts

@@ -0,0 +1,12 @@
+const partitionTrans = {
+  create: 'Create Partition',
+  delete: 'Delete partition',
+
+  id: 'ID',
+  name: 'Name',
+  status: 'Status',
+  rowCount: 'Row Count',
+  tooltip: 'data in one row',
+};
+
+export default partitionTrans;

+ 4 - 0
client/src/i18n/en/collection.ts

@@ -43,6 +43,10 @@ const collectionTrans = {
   // delete dialog
   deleteWarning:
     'You are trying to delete a collection with data. This action cannot be undone.',
+
+  // collection tabs
+  partitionTab: 'Partitions',
+  structureTab: 'Structure',
 };
 
 export default collectionTrans;

+ 12 - 0
client/src/i18n/en/partition.ts

@@ -0,0 +1,12 @@
+const partitionTrans = {
+  create: 'Create Partition',
+  delete: 'Delete partition',
+
+  id: 'ID',
+  name: 'Name',
+  status: 'Status',
+  rowCount: 'Row Count',
+  tooltip: 'data in one row',
+};
+
+export default partitionTrans;

+ 4 - 0
client/src/i18n/index.ts

@@ -15,6 +15,8 @@ import collectionCn from './cn/collection';
 import collectionEn from './en/collection';
 import dialogCn from './cn/dialog';
 import dialogEn from './en/dialog';
+import partitionCn from './cn/partition';
+import partitionEn from './en/partition';
 
 export const resources = {
   cn: {
@@ -25,6 +27,7 @@ export const resources = {
     overview: overviewCn,
     collection: collectionCn,
     dialog: dialogCn,
+    partition: partitionCn,
   },
   en: {
     translation: commonEn,
@@ -34,6 +37,7 @@ export const resources = {
     overview: overviewEn,
     collection: collectionEn,
     dialog: dialogEn,
+    partition: partitionEn,
   },
 };
 

+ 83 - 0
client/src/pages/collections/Collection.tsx

@@ -0,0 +1,83 @@
+import { useTranslation } from 'react-i18next';
+import { useNavigationHook } from '../../hooks/Navigation';
+import { ALL_ROUTER_TYPES } from '../../router/Types';
+import CustomTabList from '../../components/customTabList/CustomTabList';
+import { ITab } from '../../components/customTabList/Types';
+import Partitions from '../partitions/partitions';
+import { useHistory, useLocation, useParams } from 'react-router-dom';
+import { useEffect, useMemo, useState } from 'react';
+import { PartitionView } from '../partitions/Types';
+import { parseLocationSearch } from '../../utils/Format';
+import { StatusEnum } from '../../components/status/Types';
+import Status from '../../components/status/Status';
+import { formatNumber } from '../../utils/Common';
+
+const Collection = () => {
+  const { collectionName = '' } =
+    useParams<{
+      collectionName: string;
+    }>();
+
+  useNavigationHook(ALL_ROUTER_TYPES.COLLECTION_DETAIL, { collectionName });
+  const [partitions, setPartitions] = useState<PartitionView[]>([]);
+  const [loading, setLoading] = useState<boolean>(false);
+
+  const history = useHistory();
+  const location = useLocation();
+
+  const { t } = useTranslation('collection');
+
+  enum TAB_EMUM {
+    'partition',
+    'structure',
+  }
+
+  const activeTabIndex = useMemo(() => {
+    const { activeIndex } = location.search
+      ? parseLocationSearch(location.search)
+      : { activeIndex: TAB_EMUM.partition };
+    return Number(activeIndex);
+  }, [location, TAB_EMUM]);
+
+  const handleTabChange = (activeIndex: number) => {
+    const path = location.pathname;
+    history.push(`${path}?activeIndex=${activeIndex}`);
+  };
+
+  useEffect(() => {
+    const mockPartitions: PartitionView[] = [
+      {
+        id: '1',
+        name: 'partition',
+        status: StatusEnum.unloaded,
+        statusElement: <Status status={StatusEnum.unloaded} />,
+        rowCount: formatNumber(11223),
+      },
+    ];
+
+    setPartitions(mockPartitions);
+  }, []);
+
+  const tabs: ITab[] = [
+    {
+      label: t('partitionTab'),
+      component: <Partitions data={partitions} loading={loading} />,
+    },
+    {
+      label: t('structureTab'),
+      component: <section>structure section</section>,
+    },
+  ];
+
+  return (
+    <section className="page-wrapper">
+      <CustomTabList
+        tabs={tabs}
+        activeIndex={activeTabIndex}
+        handleTabChange={handleTabChange}
+      />
+    </section>
+  );
+};
+
+export default Collection;

+ 17 - 5
client/src/pages/collections/Collections.tsx

@@ -17,6 +17,7 @@ import CustomToolTip from '../../components/customToolTip/CustomToolTip';
 import { rootContext } from '../../context/Root';
 import CreateCollection from './Create';
 import DeleteTemplate from '../../components/customDialog/DeleteDialogTemplate';
+import { useHistory } from 'react-router-dom';
 
 const useStyles = makeStyles((theme: Theme) => ({
   emptyWrapper: {
@@ -50,6 +51,7 @@ const Collections = () => {
     CollectionView[]
   >([]);
 
+  const history = useHistory();
   const { setDialog, handleCloseDialog } = useContext(rootContext);
   const { t } = useTranslation('collection');
   const { t: btnTrans } = useTranslation('btn');
@@ -68,7 +70,12 @@ const Collections = () => {
       {
         name: 'collection',
         nameElement: (
-          <Link href="/overview" underline="always" color="textPrimary">
+          <Link
+            component="button"
+            onClick={() => history.push(`/collection/collection`)}
+            underline="always"
+            color="textPrimary"
+          >
             collection
           </Link>
         ),
@@ -80,10 +87,15 @@ const Collections = () => {
         indexCreatingElement: <StatusIcon type="creating" />,
       },
       {
-        name: 'collection 2',
+        name: 'collection_2',
         nameElement: (
-          <Link href="/overview" underline="always" color="textPrimary">
-            collection 2
+          <Link
+            component="button"
+            onClick={() => history.push(`/collection/collection_2`)}
+            underline="always"
+            color="textPrimary"
+          >
+            collection_2
           </Link>
         ),
         id: 'c2',
@@ -95,7 +107,7 @@ const Collections = () => {
       },
     ];
     setCollections(mockCollections);
-  }, []);
+  }, [history]);
 
   const handleCreateCollection = (param: CollectionCreateParam) => {
     handleCloseDialog();

+ 10 - 0
client/src/pages/partitions/Types.ts

@@ -0,0 +1,10 @@
+import { ReactElement } from 'react';
+import { StatusEnum } from '../../components/status/Types';
+
+export interface PartitionView {
+  id: string;
+  name: string;
+  status: StatusEnum;
+  statusElement: ReactElement;
+  rowCount: string;
+}

+ 119 - 0
client/src/pages/partitions/partitions.tsx

@@ -0,0 +1,119 @@
+import { makeStyles, Theme } from '@material-ui/core';
+import { FC, useState } from 'react';
+import { PartitionView } from './Types';
+import MilvusGrid from '../../components/grid';
+import { ColDefinitionsType, ToolBarConfig } from '../../components/grid/Types';
+import { useTranslation } from 'react-i18next';
+import { usePaginationHook } from '../../hooks/Pagination';
+import icons from '../../components/icons/Icons';
+import CustomToolTip from '../../components/customToolTip/CustomToolTip';
+
+const useStyles = makeStyles((theme: Theme) => ({
+  wrapper: {},
+  icon: {
+    fontSize: '20px',
+    marginLeft: theme.spacing(0.5),
+  },
+}));
+
+const Partitions: FC<{ data: PartitionView[]; loading: boolean }> = ({
+  data,
+  loading,
+}) => {
+  const classes = useStyles();
+  const { t } = useTranslation('partition');
+  const InfoIcon = icons.info;
+  console.log('==== data', data, 'loading', loading);
+
+  const {
+    pageSize,
+    currentPage,
+    handleCurrentPage,
+    // offset,
+    total,
+    // setTotal
+  } = usePaginationHook();
+
+  const [selectedPartitions, setSelectedPartitions] = useState<PartitionView[]>(
+    []
+  );
+
+  const toolbarConfigs: ToolBarConfig[] = [
+    {
+      label: t('create'),
+      onClick: () => {},
+      icon: 'add',
+    },
+    {
+      type: 'iconBtn',
+      onClick: () => {},
+      label: t('delete'),
+      icon: 'delete',
+    },
+  ];
+
+  const colDefinitions: ColDefinitionsType[] = [
+    {
+      id: 'id',
+      align: 'left',
+      disablePadding: true,
+      label: t('id'),
+    },
+    {
+      id: 'name',
+      align: 'left',
+      disablePadding: false,
+      label: t('name'),
+    },
+    {
+      id: 'statusElement',
+      align: 'left',
+      disablePadding: false,
+      label: t('status'),
+    },
+    {
+      id: 'rowCount',
+      align: 'left',
+      disablePadding: false,
+      label: (
+        <span className="flex-center">
+          {t('rowCount')}
+          <CustomToolTip title={t('tooltip')}>
+            <InfoIcon classes={{ root: classes.icon }} />
+          </CustomToolTip>
+        </span>
+      ),
+    },
+  ];
+
+  const handleSelectChange = (value: PartitionView[]) => {
+    setSelectedPartitions(value);
+  };
+
+  const handlePageChange = (e: any, page: number) => {
+    handleCurrentPage(page);
+    setSelectedPartitions([]);
+  };
+
+  return (
+    <section className={classes.wrapper}>
+      <MilvusGrid
+        toolbarConfigs={toolbarConfigs}
+        colDefinitions={colDefinitions}
+        rows={data}
+        rowCount={total}
+        primaryKey="id"
+        openCheckBox={true}
+        showHoverStyle={true}
+        selected={selectedPartitions}
+        setSelected={handleSelectChange}
+        page={currentPage}
+        onChangePage={handlePageChange}
+        rowsPerPage={pageSize}
+        isLoading={loading}
+      />
+    </section>
+  );
+};
+
+export default Partitions;

+ 8 - 1
client/src/router/Config.ts

@@ -1,9 +1,11 @@
+import Collection from '../pages/collections/Collection';
 import Collections from '../pages/collections/Collections';
 import Connect from '../pages/connect/Connect';
 // import Console from '../pages/console/Console';
 import Overview from '../pages/overview/Overview';
+import { RouterConfigType } from './Types';
 
-const RouterConfig = [
+const RouterConfig: RouterConfigType[] = [
   {
     path: '/',
     component: Overview,
@@ -19,6 +21,11 @@ const RouterConfig = [
     component: Collections,
     auth: true,
   },
+  {
+    path: '/collection/:collectionName',
+    component: Collection,
+    auth: true,
+  },
   // {
   //   path: '/console',
   //   component: Console,

+ 6 - 0
client/src/router/Types.ts

@@ -13,3 +13,9 @@ export type NavInfo = {
   navTitle: string;
   backPath: string;
 };
+
+export type RouterConfigType = {
+  path: string;
+  component: () => JSX.Element;
+  auth: boolean;
+};