Browse Source

add create index action in status action

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

+ 5 - 4
client/src/components/status/Types.ts

@@ -1,12 +1,13 @@
 import { LOADING_STATE } from '@/consts';
-import { SchemaObject } from '@server/types';
+import { CollectionObject } from '@server/types';
+import React from 'react';
 
 export type StatusActionType = {
   status: LOADING_STATE;
   percentage?: string | number;
   action?: Function;
-  schema: SchemaObject;
   onIndexCreate?: Function;
+  showExtraAction?: boolean;
+  collection: CollectionObject;
+  createIndexElement?: React.ReactNode;
 };
-
-// @todo need rename

+ 1 - 0
client/src/i18n/cn/button.ts

@@ -33,6 +33,7 @@ const btnTrans = {
   copyJson: '复制为JSON',
   star: '给我一颗小星星',
   applyFilter: '应用过滤器',
+  createIndex: '创建索引',
 
   // tips
   loadColTooltip: '加载Collection',

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

@@ -133,6 +133,7 @@ const collectionTrans = {
   clickToLoad: '点击加载collection。',
   clickToRelease: '点击释放collection。',
   clickToSearch: '点击执行向量搜索。',
+  clickToCreateVectorIndex: '点击创建向量索引。',
   collectionIsLoading: 'colleciton正在加载...',
 };
 

+ 1 - 0
client/src/i18n/en/button.ts

@@ -33,6 +33,7 @@ const btnTrans = {
   copyJson: 'Copy as JSON',
   star: 'Give me a Star',
   applyFilter: 'Apply Filters',
+  createIndex: 'Create Index',
 
   // tips
   loadColTooltip: 'Load Collection',

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

@@ -131,6 +131,7 @@ const collectionTrans = {
   clickToLoad: 'Click to load the collection.',
   clickToRelease: 'Click to release the collection.',
   clickToSearch: 'Click to execute vector search.',
+  clickToCreateVectorIndex: 'Click to create an vector index.',
   collectionIsLoading: 'The collection is loading...',
 };
 

+ 1 - 15
client/src/pages/databases/collections/Collections.tsx

@@ -368,21 +368,7 @@ const Collections = () => {
           <StatusAction
             status={v.status}
             percentage={v.loadedPercentage}
-            schema={v.schema}
-            action={() => {
-              setDialog({
-                open: true,
-                type: 'custom',
-                params: {
-                  component:
-                    v.status === LOADING_STATE.UNLOADED ? (
-                      <LoadCollectionDialog collection={v} />
-                    ) : (
-                      <ReleaseCollectionDialog collection={v} />
-                    ),
-                },
-              });
-            }}
+            collection={v}
           />
         );
       },

+ 42 - 18
client/src/pages/databases/collections/StatusAction.tsx

@@ -1,4 +1,4 @@
-import { FC, useMemo, MouseEvent } from 'react';
+import { FC, useMemo, MouseEvent, useContext } from 'react';
 import { StatusActionType } from '@/components/status/Types';
 import { useTranslation } from 'react-i18next';
 import {
@@ -9,12 +9,15 @@ import {
   useTheme,
   Chip,
 } from '@material-ui/core';
+import { rootContext } from '@/context';
 import { LOADING_STATE } from '@/consts';
 import StatusIcon, { LoadingType } from '@/components/status/StatusIcon';
 import Icons from '@/components/icons/Icons';
 import CustomToolTip from '@/components/customToolTip/CustomToolTip';
 import CustomButton from '@/components/customButton/CustomButton';
 import { useNavigate } from 'react-router-dom';
+import LoadCollectionDialog from '@/pages/dialogs/LoadCollectionDialog';
+import ReleaseCollectionDialog from '@/pages/dialogs/ReleaseCollectionDialog';
 
 const useStyles = makeStyles((theme: Theme) =>
   createStyles({
@@ -77,12 +80,13 @@ const useStyles = makeStyles((theme: Theme) =>
 const StatusAction: FC<StatusActionType> = props => {
   const theme = useTheme();
   const navigate = useNavigate();
+  const { setDialog } = useContext(rootContext);
 
   const classes = useStyles({ color: theme.palette.primary.main });
   const ReleaseIcon = Icons.release;
   const LoadIcon = Icons.load;
 
-  const { status, percentage = 0, schema, action = () => {} } = props;
+  const { status, percentage = 0, collection, action = () => {} } = props;
   const { t: commonTrans } = useTranslation();
   const { t: collectionTrans } = useTranslation('collection');
   const { t: btnTrans } = useTranslation('btn');
@@ -132,7 +136,7 @@ const StatusAction: FC<StatusActionType> = props => {
     }
   }, [status, statusTrans, percentage]);
 
-  const noIndex = schema && !schema.hasVectorIndex;
+  const noIndex = collection.schema && !collection.schema.hasVectorIndex;
   const noVectorIndexTooltip = collectionTrans('noVectorIndexTooltip');
   const noIndexIcon = (
     <div className={`${classes.circle} ${classes.noIndex}`}></div>
@@ -151,7 +155,18 @@ const StatusAction: FC<StatusActionType> = props => {
           onDelete={() => action()}
           onClick={(e: MouseEvent<HTMLDivElement>) => {
             e.stopPropagation();
-            action();
+            setDialog({
+              open: true,
+              type: 'custom',
+              params: {
+                component:
+                  collection.status === LOADING_STATE.UNLOADED ? (
+                    <LoadCollectionDialog collection={collection} />
+                  ) : (
+                    <ReleaseCollectionDialog collection={collection} />
+                  ),
+              },
+            });
           }}
           disabled={noIndex}
           deleteIcon={deleteIcon}
@@ -159,20 +174,29 @@ const StatusAction: FC<StatusActionType> = props => {
           icon={noIndex ? noIndexIcon : icon}
         />
       </CustomToolTip>
-      {status === LOADING_STATE.LOADED && (
-        <CustomButton
-          startIcon={<Icons.navSearch />}
-          className={classes.extraBtn}
-          tooltip={collectionTrans('clickToSearch')}
-          onClick={() => {
-            navigate({
-              pathname: '/search',
-              search: `?collectionName=${schema.name}`,
-            });
-          }}
-        >
-          {btnTrans('vectorSearch')}
-        </CustomButton>
+
+      {props.showExtraAction && collection.schema && (
+        <>
+          {status === LOADING_STATE.LOADED && (
+            <CustomButton
+              startIcon={<Icons.navSearch />}
+              className={classes.extraBtn}
+              tooltip={collectionTrans('clickToSearch')}
+              onClick={() => {
+                navigate({
+                  pathname: '/search',
+                  search: `?collectionName=${collection.schema.name}`,
+                });
+              }}
+            >
+              {btnTrans('vectorSearch')}
+            </CustomButton>
+          )}
+
+          {collection.schema &&
+            !collection.schema.hasVectorIndex &&
+            props.createIndexElement}
+        </>
       )}
     </div>
   );

+ 15 - 12
client/src/pages/databases/collections/overview/IndexTypeElement.tsx

@@ -4,13 +4,14 @@ import Chip from '@material-ui/core/Chip';
 import { makeStyles, Theme, Tooltip } from '@material-ui/core';
 import { IndexCreateParam, IndexExtraParam, IndexManageParam } from './Types';
 import { rootContext, dataContext } from '@/context';
-import icons from '@/components/icons/Icons';
+import Icons from '@/components/icons/Icons';
 import DeleteTemplate from '@/components/customDialog/DeleteDialogTemplate';
 import StatusIcon, { LoadingType } from '@/components/status/StatusIcon';
 import { IndexState } from '@/types/Milvus';
 import { NONE_INDEXABLE_DATA_TYPES, DataTypeStringEnum } from '@/consts';
 import CreateIndex from './Create';
 import { FieldObject } from '@server/types';
+import CustomButton from '@/components/customButton/CustomButton';
 
 const useStyles = makeStyles((theme: Theme) => ({
   wrapper: {
@@ -25,7 +26,7 @@ const useStyles = makeStyles((theme: Theme) => ({
     alignItems: 'center',
     whiteSpace: 'nowrap',
     color: theme.palette.primary.main,
-
+    height: 24,
     '&:hover': {
       cursor: 'pointer',
     },
@@ -68,16 +69,14 @@ const IndexTypeElement: FC<{
   const classes = useStyles();
   // set empty string as default status
   const { t: indexTrans } = useTranslation('index');
-  const { t: btnTrans } = useTranslation('btn');
   const { t: dialogTrans } = useTranslation('dialog');
   const { t: successTrans } = useTranslation('success');
+  const { t: collectionTrans } = useTranslation('collection');
+  const { t: btnTrans } = useTranslation('btn');
 
   const { setDialog, handleCloseDialog, openSnackBar } =
     useContext(rootContext);
 
-  const AddIcon = icons.add;
-  const DeleteIcon = icons.delete;
-
   const requestCreateIndex = async (
     params: IndexExtraParam,
     index_name: string
@@ -95,7 +94,7 @@ const IndexTypeElement: FC<{
     cb && (await cb(collectionName));
   };
 
-  const handleCreate = (e: MouseEvent<HTMLDivElement>) => {
+  const handleCreate = (e: MouseEvent<HTMLButtonElement>) => {
     e.stopPropagation();
 
     setDialog({
@@ -158,10 +157,14 @@ const IndexTypeElement: FC<{
 
     if (!field.index) {
       return (
-        <div role="button" onClick={handleCreate} className={`${classes.btn}`}>
-          <AddIcon classes={{ root: classes.addIcon }} />
-          {indexTrans('create')}
-        </div>
+        <CustomButton
+          startIcon={<Icons.add />}
+          className={classes.btn}
+          tooltip={collectionTrans('clickToCreateVectorIndex')}
+          onClick={e => handleCreate(e)}
+        >
+          {btnTrans('createIndex')}
+        </CustomButton>
       );
     }
     // indexType example: FLAT
@@ -175,7 +178,7 @@ const IndexTypeElement: FC<{
           <Chip
             label={field.index.indexType}
             classes={{ root: classes.chip, label: classes.chipLabel }}
-            deleteIcon={<DeleteIcon classes={{ root: 'icon' }} />}
+            deleteIcon={<Icons.delete classes={{ root: 'icon' }} />}
             onDelete={handleDelete}
             disabled={disabled}
             onClick={(e: MouseEvent<HTMLDivElement>) => {

+ 17 - 20
client/src/pages/databases/collections/overview/Overview.tsx

@@ -12,14 +12,12 @@ import { ColDefinitionsType } from '@/components/grid/Types';
 import { useTranslation } from 'react-i18next';
 import Icons from '@/components/icons/Icons';
 import { formatFieldType } from '@/utils';
-import { rootContext, dataContext } from '@/context';
+import { dataContext } from '@/context';
 import IndexTypeElement from './IndexTypeElement';
 import { getLabelDisplayedRows } from '@/pages/search/Utils';
-import { LOADING_STATE } from '@/consts';
-import LoadCollectionDialog from '@/pages/dialogs/LoadCollectionDialog';
-import ReleaseCollectionDialog from '@/pages/dialogs/ReleaseCollectionDialog';
 import StatusAction from '@/pages/databases/collections/StatusAction';
 import CustomToolTip from '@/components/customToolTip/CustomToolTip';
+import { FieldObject } from '@server/types';
 
 const useStyles = makeStyles((theme: Theme) => ({
   wrapper: {
@@ -118,7 +116,6 @@ const useStyles = makeStyles((theme: Theme) => ({
 }));
 
 const Overview = () => {
-  const { setDialog } = useContext(rootContext);
   const { fetchCollection, collections, loading } = useContext(dataContext);
   const { collectionName = '' } = useParams<{ collectionName: string }>();
   const classes = useStyles();
@@ -281,21 +278,21 @@ const Overview = () => {
               <StatusAction
                 status={collection.status}
                 percentage={collection.loadedPercentage}
-                schema={collection.schema!}
-                action={() => {
-                  setDialog({
-                    open: true,
-                    type: 'custom',
-                    params: {
-                      component:
-                        collection.status === LOADING_STATE.UNLOADED ? (
-                          <LoadCollectionDialog collection={collection} />
-                        ) : (
-                          <ReleaseCollectionDialog collection={collection} />
-                        ),
-                    },
-                  });
-                }}
+                collection={collection}
+                showExtraAction={true}
+                createIndexElement={
+                  <IndexTypeElement
+                    field={
+                      (collection.schema &&
+                        collection.schema.vectorFields[0]) ||
+                      ({} as FieldObject)
+                    }
+                    collectionName={collectionName}
+                    cb={async () => {
+                      await fetchCollection(collectionName);
+                    }}
+                  />
+                }
               />
             </div>
           </section>