Explorar el Código

Merge pull request #42 from Tumao727/feature/delete-index

add delete index
nameczz hace 3 años
padre
commit
795837b64b

+ 1 - 1
client/public/index.html

@@ -30,7 +30,7 @@
       work correctly both with client-side routing and a non-root public URL.
       Learn how to configure a non-root public URL by running `npm run build`.
     -->
-    <title>Milvus Admin</title>
+    <title>Milvus Insight</title>
   </head>
 
   <body>

+ 11 - 1
client/src/http/Index.ts

@@ -1,8 +1,10 @@
 import {
   IndexCreateParam,
+  IndexManageParam,
   IndexView,
   ParamPair,
 } from '../pages/structure/Types';
+import { ManageRequestMethods } from '../types/Common';
 import { IndexState } from '../types/Milvus';
 import BaseModel from './BaseModel';
 
@@ -40,13 +42,21 @@ export class IndexHttp extends BaseModel implements IndexView {
 
   static async createIndex(param: IndexCreateParam) {
     const path = this.BASE_URL;
+    const type: ManageRequestMethods = ManageRequestMethods.CREATE;
 
     return super.create({
       path,
-      data: { ...param },
+      data: { ...param, type },
     });
   }
 
+  static async deleteIndex(param: IndexManageParam) {
+    const path = this.BASE_URL;
+    const type: ManageRequestMethods = ManageRequestMethods.DELETE;
+
+    return super.batchDelete({ path, data: { ...param, type } });
+  }
+
   get _indexType() {
     return this.params.find(p => p.key === 'index_type')?.value || '';
   }

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

@@ -7,6 +7,8 @@ const indexTrans = {
   metric: 'Metric Type',
 
   createSuccess: 'Creating index successfully',
+  deleteWarning:
+    'You are trying to delete an index. This action cannot be undone.',
 };
 
 export default indexTrans;

+ 2 - 0
client/src/i18n/en/index.ts

@@ -7,6 +7,8 @@ const indexTrans = {
 
   metric: 'Metric Type',
   createSuccess: 'Creating index successfully',
+  deleteWarning:
+    'You are trying to delete an index. This action cannot be undone.',
 };
 
 export default indexTrans;

+ 3 - 3
client/src/pages/collections/Collection.tsx

@@ -25,7 +25,7 @@ const Collection = () => {
   const history = useHistory();
   const location = useLocation();
 
-  const { t } = useTranslation('collection');
+  const { t: collectionTrans } = useTranslation('collection');
 
   const activeTabIndex = useMemo(() => {
     const { activeIndex } = location.search
@@ -41,11 +41,11 @@ const Collection = () => {
 
   const tabs: ITab[] = [
     {
-      label: t('partitionTab'),
+      label: collectionTrans('partitionTab'),
       component: <Partitions collectionName={collectionName} />,
     },
     {
-      label: t('structureTab'),
+      label: collectionTrans('structureTab'),
       component: <Structure collectionName={collectionName} />,
     },
   ];

+ 24 - 16
client/src/pages/collections/Collections.tsx

@@ -58,7 +58,7 @@ const Collections = () => {
 
   const { setDialog, handleCloseDialog, openSnackBar } =
     useContext(rootContext);
-  const { t } = useTranslation('collection');
+  const { t: collectionTrans } = useTranslation('collection');
   const { t: btnTrans } = useTranslation('btn');
   const { t: dialogTrans } = useTranslation('dialog');
   const { t: successTrans } = useTranslation('success');
@@ -118,20 +118,24 @@ const Collections = () => {
     );
     await CollectionHttp.createCollection(data);
     handleCloseDialog();
-    openSnackBar(successTrans('create', { name: t('collection') }));
+    openSnackBar(
+      successTrans('create', { name: collectionTrans('collection') })
+    );
     fetchData();
   };
 
   const handleRelease = async (data: CollectionView) => {
     const res = await CollectionHttp.releaseCollection(data._name);
-    openSnackBar(successTrans('release', { name: t('collection') }));
+    openSnackBar(
+      successTrans('release', { name: collectionTrans('collection') })
+    );
     fetchData();
     return res;
   };
 
   const handleLoad = async (data: CollectionView) => {
     const res = await CollectionHttp.loadCollection(data._name);
-    openSnackBar(successTrans('load', { name: t('collection') }));
+    openSnackBar(successTrans('load', { name: collectionTrans('collection') }));
     fetchData();
     return res;
   };
@@ -140,7 +144,9 @@ const Collections = () => {
     for (const item of selectedCollections) {
       await CollectionHttp.deleteCollection(item._name);
     }
-    openSnackBar(successTrans('delete', { name: t('collection') }));
+    openSnackBar(
+      successTrans('delete', { name: collectionTrans('collection') })
+    );
     fetchData();
     handleCloseDialog();
     setSelectedCollections([]);
@@ -148,7 +154,7 @@ const Collections = () => {
 
   const toolbarConfigs: ToolBarConfig[] = [
     {
-      label: t('create'),
+      label: collectionTrans('create'),
       onClick: () => {
         setDialog({
           open: true,
@@ -172,15 +178,17 @@ const Collections = () => {
             component: (
               <DeleteTemplate
                 label={btnTrans('delete')}
-                title={dialogTrans('deleteTitle', { type: t('collection') })}
-                text={t('deleteWarning')}
+                title={dialogTrans('deleteTitle', {
+                  type: collectionTrans('collection'),
+                })}
+                text={collectionTrans('deleteWarning')}
                 handleDelete={handleDelete}
               />
             ),
           },
         });
       },
-      label: t('delete'),
+      label: collectionTrans('delete'),
       icon: 'delete',
       disabled: data => data.length === 0,
     },
@@ -191,19 +199,19 @@ const Collections = () => {
       id: '_id',
       align: 'left',
       disablePadding: true,
-      label: t('id'),
+      label: collectionTrans('id'),
     },
     {
       id: 'nameElement',
       align: 'left',
       disablePadding: true,
-      label: t('name'),
+      label: collectionTrans('name'),
     },
     {
       id: 'statusElement',
       align: 'left',
       disablePadding: false,
-      label: t('status'),
+      label: collectionTrans('status'),
     },
     {
       id: '_rowCount',
@@ -211,8 +219,8 @@ const Collections = () => {
       disablePadding: false,
       label: (
         <span className="flex-center">
-          {t('rowCount')}
-          <CustomToolTip title={t('tooltip')}>
+          {collectionTrans('rowCount')}
+          <CustomToolTip title={collectionTrans('tooltip')}>
             <InfoIcon classes={{ root: classes.icon }} />
           </CustomToolTip>
         </span>
@@ -222,7 +230,7 @@ const Collections = () => {
       id: '_desc',
       align: 'left',
       disablePadding: false,
-      label: t('desc'),
+      label: collectionTrans('desc'),
     },
     {
       id: 'indexCreatingElement',
@@ -291,7 +299,7 @@ const Collections = () => {
           <EmptyCard
             wrapperClass={`page-empty-card ${classes.emptyWrapper}`}
             icon={<CollectionIcon />}
-            text={t('noData')}
+            text={collectionTrans('noData')}
           />
         </>
       )}

+ 9 - 7
client/src/pages/collections/Create.tsx

@@ -42,7 +42,7 @@ const useStyles = makeStyles((theme: Theme) => ({
 const CreateCollection: FC<CollectionCreateProps> = ({ handleCreate }) => {
   const classes = useStyles();
   const { handleCloseDialog } = useContext(rootContext);
-  const { t } = useTranslation('collection');
+  const { t: collectionTrans } = useTranslation('collection');
   const { t: btnTrans } = useTranslation('btn');
   const { t: warningTrans } = useTranslation('warning');
 
@@ -105,7 +105,7 @@ const CreateCollection: FC<CollectionCreateProps> = ({ handleCreate }) => {
 
   const generalInfoConfigs: ITextfieldConfig[] = [
     {
-      label: t('name'),
+      label: collectionTrans('name'),
       key: 'collection_name',
       value: form.collection_name,
       onChange: (value: string) => handleInputChange('collection_name', value),
@@ -113,13 +113,15 @@ const CreateCollection: FC<CollectionCreateProps> = ({ handleCreate }) => {
       validations: [
         {
           rule: 'require',
-          errorText: warningTrans('required', { name: t('name') }),
+          errorText: warningTrans('required', {
+            name: collectionTrans('name'),
+          }),
         },
       ],
       className: classes.input,
     },
     {
-      label: t('description'),
+      label: collectionTrans('description'),
       key: 'description',
       value: form.description,
       onChange: (value: string) => handleInputChange('description', value),
@@ -148,7 +150,7 @@ const CreateCollection: FC<CollectionCreateProps> = ({ handleCreate }) => {
 
   return (
     <DialogTemplate
-      title={t('createTitle')}
+      title={collectionTrans('createTitle')}
       handleCancel={handleCloseDialog}
       confirmLabel={btnTrans('create')}
       handleConfirm={handleCreateCollection}
@@ -156,7 +158,7 @@ const CreateCollection: FC<CollectionCreateProps> = ({ handleCreate }) => {
     >
       <form>
         <fieldset className={classes.fieldset}>
-          <legend>{t('general')}</legend>
+          <legend>{collectionTrans('general')}</legend>
           {generalInfoConfigs.map(config => (
             <CustomInput
               key={config.key}
@@ -169,7 +171,7 @@ const CreateCollection: FC<CollectionCreateProps> = ({ handleCreate }) => {
         </fieldset>
 
         <fieldset className={classes.fieldset}>
-          <legend>{t('structure')}</legend>
+          <legend>{collectionTrans('structure')}</legend>
           <CreateFields
             fields={fields}
             setFields={setFields}

+ 2 - 2
client/src/pages/connect/Connect.tsx

@@ -48,9 +48,9 @@ const Connect = () => {
   const { setAddress } = useContext(authContext);
   const { openSnackBar } = useContext(rootContext);
   const classes = useStyles();
-  const { t } = useTranslation();
+  const { t: commonTrans } = useTranslation();
   const { t: warningTrans } = useTranslation('warning');
-  const milvusTrans: { [key in string]: string } = t('milvus');
+  const milvusTrans: { [key in string]: string } = commonTrans('milvus');
   const { t: btnTrans } = useTranslation('btn');
   const { t: successTrans } = useTranslation('success');
 

+ 10 - 6
client/src/pages/overview/Overview.tsx

@@ -28,24 +28,26 @@ const useStyles = makeStyles((theme: Theme) => ({
 const Overview = () => {
   useNavigationHook(ALL_ROUTER_TYPES.OVERVIEW);
   const classes = useStyles();
-  const { t } = useTranslation('overview');
+  const { t: overviewTrans } = useTranslation('overview');
   const { t: collectionTrans } = useTranslation('collection');
 
   const mockStatistics: StatisticsCardProps = {
     data: [
       {
-        label: t('load'),
+        label: overviewTrans('load'),
         value: formatNumber(4337),
         valueColor: '#07d197',
       },
       {
-        label: t('all'),
+        label: overviewTrans('all'),
         value: formatNumber(30000),
         valueColor: '#06aff2',
       },
       {
-        label: t('data'),
-        value: t('rows', { number: formatNumber(209379100) }) as string,
+        label: overviewTrans('data'),
+        value: overviewTrans('rows', {
+          number: formatNumber(209379100),
+        }) as string,
         valueColor: '#0689d2',
       },
     ],
@@ -94,7 +96,9 @@ const Overview = () => {
   return (
     <section className="page-wrapper">
       <StatisticsCard data={mockStatistics.data} />
-      <Typography className={classes.collectionTitle}>{t('load')}</Typography>
+      <Typography className={classes.collectionTitle}>
+        {overviewTrans('load')}
+      </Typography>
       {mockCollections.length > 0 ? (
         <div className={classes.cardsWrapper}>
           {mockCollections.map(collection => (

+ 3 - 3
client/src/pages/overview/collectionCard/CollectionCard.tsx

@@ -60,7 +60,7 @@ const CollectionCard: FC<CollectionCardProps> = ({
   const RightArrowIcon = icons.rightArrow;
   const InfoIcon = icons.info;
   const ReleaseIcon = icons.release;
-  const { t } = useTranslation('collection');
+  const { t: collectionTrans } = useTranslation('collection');
   const { t: btnTrans } = useTranslation('btn');
 
   const handleRelease = () => {};
@@ -79,8 +79,8 @@ const CollectionCard: FC<CollectionCardProps> = ({
         <RightArrowIcon classes={{ root: classes.icon }} />
       </Link>
       <div className={classes.content}>
-        <Typography>{t('rowCount')}</Typography>
-        <CustomToolTip title={t('tooltip')} placement="bottom">
+        <Typography>{collectionTrans('rowCount')}</Typography>
+        <CustomToolTip title={collectionTrans('tooltip')} placement="bottom">
           <InfoIcon classes={{ root: classes.icon }} />
         </CustomToolTip>
         <Typography className={classes.rowCount}>{rowCount}</Typography>

+ 5 - 5
client/src/pages/partitions/Create.tsx

@@ -18,7 +18,7 @@ const CreatePartition: FC<PartitionCreateProps> = ({
   handleCreate,
   handleClose,
 }) => {
-  const { t } = useTranslation('partition');
+  const { t: partitionTrans } = useTranslation('partition');
   const { t: btnTrans } = useTranslation('btn');
   const { t: warningTrans } = useTranslation('warning');
 
@@ -38,7 +38,7 @@ const CreatePartition: FC<PartitionCreateProps> = ({
   };
 
   const nameInputConfig: ITextfieldConfig = {
-    label: t('name'),
+    label: partitionTrans('name'),
     variant: 'filled',
     key: 'name',
     fullWidth: true,
@@ -47,11 +47,11 @@ const CreatePartition: FC<PartitionCreateProps> = ({
     validations: [
       {
         rule: 'require',
-        errorText: warningTrans('required', { name: t('name') }),
+        errorText: warningTrans('required', { name: partitionTrans('name') }),
       },
       {
         rule: 'partitionName',
-        errorText: t('nameWarning'),
+        errorText: partitionTrans('nameWarning'),
       },
     ],
   };
@@ -62,7 +62,7 @@ const CreatePartition: FC<PartitionCreateProps> = ({
 
   return (
     <DialogTemplate
-      title={t('createTitle')}
+      title={partitionTrans('createTitle')}
       handleCancel={handleClose}
       confirmLabel={btnTrans('create')}
       handleConfirm={handleCreatePartition}

+ 4 - 2
client/src/pages/structure/CreateForm.tsx

@@ -44,7 +44,7 @@ const CreateForm = (
     metricOptions,
   } = props;
 
-  const { t } = useTranslation();
+  const { t: commonTrans } = useTranslation();
   const { t: indexTrans } = useTranslation('index');
   const { t: warningTrans } = useTranslation('warning');
 
@@ -162,7 +162,9 @@ const CreateForm = (
         classes={{ root: classes.select }}
       />
 
-      <Typography className={classes.paramTitle}>{t('param')}</Typography>
+      <Typography className={classes.paramTitle}>
+        {commonTrans('param')}
+      </Typography>
       <CustomSelector
         label={indexTrans('metric')}
         value={formValue.metric_type}

+ 45 - 10
client/src/pages/structure/IndexTypeElement.tsx

@@ -3,7 +3,12 @@ import Chip from '@material-ui/core/Chip';
 import CustomButton from '../../components/customButton/CustomButton';
 import { IndexHttp } from '../../http/Index';
 import { IndexState } from '../../types/Milvus';
-import { FieldView, IndexCreateParam, ParamPair } from './Types';
+import {
+  FieldView,
+  IndexCreateParam,
+  IndexManageParam,
+  ParamPair,
+} from './Types';
 import StatusIcon from '../../components/status/StatusIcon';
 import { ChildrenStatusType } from '../../components/status/Types';
 import { useTranslation } from 'react-i18next';
@@ -11,7 +16,7 @@ import { makeStyles, Theme } from '@material-ui/core';
 import icons from '../../components/icons/Icons';
 import { rootContext } from '../../context/Root';
 import CreateIndex from './Create';
-import { ManageRequestMethods } from '../../types/Common';
+import DeleteTemplate from '../../components/customDialog/DeleteDialogTemplate';
 
 const useStyles = makeStyles((theme: Theme) => ({
   item: {
@@ -31,12 +36,16 @@ const useStyles = makeStyles((theme: Theme) => ({
 const IndexTypeElement: FC<{
   data: FieldView;
   collectionName: string;
-  createCb: (collectionName: string) => void;
-}> = ({ data, collectionName, createCb }) => {
+  cb: (collectionName: string) => void;
+}> = ({ data, collectionName, cb }) => {
   const classes = useStyles();
 
   const [status, setStatus] = useState<string>('');
-  const { t } = useTranslation('index');
+
+  const { t: indexTrans } = useTranslation('index');
+  const { t: btnTrans } = useTranslation('btn');
+  const { t: dialogTrans } = useTranslation('dialog');
+  const { t: successTrans } = useTranslation('success');
 
   const { setDialog, handleCloseDialog, openSnackBar } =
     useContext(rootContext);
@@ -60,15 +69,14 @@ const IndexTypeElement: FC<{
 
   const requestCreateIndex = async (params: ParamPair[]) => {
     const indexCreateParam: IndexCreateParam = {
-      type: ManageRequestMethods.CREATE,
       collection_name: collectionName,
       field_name: data._fieldName,
       extra_params: params,
     };
     await IndexHttp.createIndex(indexCreateParam);
     handleCloseDialog();
-    openSnackBar(t('createSuccess'));
-    createCb(collectionName);
+    openSnackBar(indexTrans('createSuccess'));
+    cb(collectionName);
   };
 
   const handleCreate = () => {
@@ -88,7 +96,34 @@ const IndexTypeElement: FC<{
     });
   };
 
-  const handleDelete = () => {};
+  const requestDeleteIndex = async () => {
+    const indexDeleteParam: IndexManageParam = {
+      collection_name: collectionName,
+      field_name: data._fieldName,
+    };
+
+    await IndexHttp.deleteIndex(indexDeleteParam);
+    handleCloseDialog();
+    openSnackBar(successTrans('delete', { name: indexTrans('index') }));
+    cb(collectionName);
+  };
+
+  const handleDelete = () => {
+    setDialog({
+      open: true,
+      type: 'custom',
+      params: {
+        component: (
+          <DeleteTemplate
+            label={btnTrans('delete')}
+            title={dialogTrans('deleteTitle', { type: indexTrans('index') })}
+            text={indexTrans('deleteWarning')}
+            handleDelete={requestDeleteIndex}
+          />
+        ),
+      },
+    });
+  };
 
   const generateElement = () => {
     if (
@@ -107,7 +142,7 @@ const IndexTypeElement: FC<{
             onClick={handleCreate}
           >
             <AddIcon />
-            {t('create')}
+            {indexTrans('create')}
           </CustomButton>
         );
       }

+ 1 - 1
client/src/pages/structure/Structure.tsx

@@ -130,7 +130,7 @@ const Structure: FC<{
               <IndexTypeElement
                 data={f}
                 collectionName={collectionName}
-                createCb={fetchFields}
+                cb={fetchFields}
               />
             ),
           })

+ 4 - 2
client/src/pages/structure/Types.ts

@@ -48,10 +48,12 @@ export type IndexType =
   | 'HNSW'
   | 'ANNOY';
 
-export interface IndexCreateParam {
-  type: ManageRequestMethods;
+export interface IndexManageParam {
   collection_name: string;
   field_name: string;
+}
+
+export interface IndexCreateParam extends IndexManageParam {
   extra_params: ParamPair[];
 }
 

+ 1 - 1
server/package.json

@@ -30,7 +30,7 @@
     "@nestjs/swagger": "^4.8.0",
     "@types/passport-jwt": "^3.0.5",
     "@types/passport-local": "^1.0.33",
-    "@zilliz/milvus-sdk-node-dev": "^0.1.2",
+    "@zilliz/milvus-sdk-node-dev": "^0.1.4",
     "class-transformer": "^0.4.0",
     "class-validator": "^0.13.1",
     "passport": "^0.4.1",

+ 4 - 4
server/yarn.lock

@@ -1287,10 +1287,10 @@
   resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
   integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
 
-"@zilliz/milvus-sdk-node-dev@^0.1.2":
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/@zilliz/milvus-sdk-node-dev/-/milvus-sdk-node-dev-0.1.2.tgz#be5d546afec4e6a87732beadce2bd8f3261dac58"
-  integrity sha512-WScOEWG0Y9va5JBRoQsh1vfH9W0LOjl5HIZVwP/vcT7Kh0pC1E4N6iwaEpnSkne055D9SxJA7FhN23udrHTrMQ==
+"@zilliz/milvus-sdk-node-dev@^0.1.4":
+  version "0.1.4"
+  resolved "https://registry.yarnpkg.com/@zilliz/milvus-sdk-node-dev/-/milvus-sdk-node-dev-0.1.4.tgz#858e83b0ba0a309cbdf0b87e313b3b41de0052a4"
+  integrity sha512-4REU6TxqjsIZ7a7mL1M19IPg3oBBfE9kJmC7XUmcFz1+F2fYWpl7Iw4R8g69trpzUNnaFIBgwjAnSb0oVrRLeQ==
   dependencies:
     "@grpc/grpc-js" "^1.2.12"
     "@grpc/proto-loader" "^0.6.0"