diff --git a/client/src/assets/icons/compact.svg b/client/src/assets/icons/compact.svg new file mode 100644 index 00000000..192eaa86 --- /dev/null +++ b/client/src/assets/icons/compact.svg @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/client/src/components/icons/Icons.tsx b/client/src/components/icons/Icons.tsx index 2aec22e9..78b1022e 100644 --- a/client/src/components/icons/Icons.tsx +++ b/client/src/components/icons/Icons.tsx @@ -42,6 +42,7 @@ import { ReactComponent as VectorSearchIcon } from '../../assets/icons/nav-searc import { ReactComponent as SearchEmptyIcon } from '../../assets/icons/search.svg'; import { ReactComponent as CopyIcon } from '../../assets/icons/copy.svg'; import { ReactComponent as SystemIcon } from '../../assets/icons/system.svg'; +import { ReactComponent as Compact } from '../../assets/icons/compact.svg'; const icons: { [x in IconsType]: (props?: any) => React.ReactElement } = { search: (props = {}) => , @@ -196,6 +197,9 @@ const icons: { [x in IconsType]: (props?: any) => React.ReactElement } = { ), + compact: (props = {}) => ( + + ), }; export default icons; diff --git a/client/src/components/icons/Types.ts b/client/src/components/icons/Types.ts index 198487d5..d0f63f55 100644 --- a/client/src/components/icons/Types.ts +++ b/client/src/components/icons/Types.ts @@ -41,4 +41,5 @@ export type IconsType = | 'source' | 'edit' | 'database' - | 'uploadFile'; + | 'uploadFile' + | 'compact'; diff --git a/client/src/http/Collection.ts b/client/src/http/Collection.ts index 50bdb916..b13eab92 100644 --- a/client/src/http/Collection.ts +++ b/client/src/http/Collection.ts @@ -159,6 +159,12 @@ export class CollectionHttp extends BaseModel implements CollectionView { }); } + static compact(collectionName: string) { + return super.update({ + path: `${this.COLLECTIONS_URL}/${collectionName}/compact`, + }); + } + get _autoId() { return this.autoID; } @@ -227,4 +233,5 @@ export class CollectionHttp extends BaseModel implements CollectionView { get _replicas(): Replica[] { return this.replicas; } + } diff --git a/client/src/i18n/en/collection.ts b/client/src/i18n/en/collection.ts index 1f938303..b5e966bb 100644 --- a/client/src/i18n/en/collection.ts +++ b/client/src/i18n/en/collection.ts @@ -48,7 +48,7 @@ const collectionTrans = { vectorFieldName: 'Vector Field', autoId: 'Auto ID', autoIdToggleTip: - 'Whether the primary key is automatically generated by Milvus, only suppport INT64.', + 'Whether the primary key is automatically generated by Milvus, only support INT64.', vectorType: 'Type', idType: 'Type', dimension: 'Dimension', @@ -62,7 +62,7 @@ const collectionTrans = { 'Name first character must be underscore or character(a~z, A~Z)', partitionKey: 'Partition Key', partitionKeyTooltip: - ' Milvus will store entities in a partition according to the values in the partition key field. Only one Int64 or VarChar field is suppported.', + ' Milvus will store entities in a partition according to the values in the partition key field. Only one Int64 or VarChar field is supported.', // load dialog loadTitle: 'Load Collection', @@ -102,8 +102,8 @@ const collectionTrans = { newColNamePlaceholder: 'New Collection Name', newNameInfo: 'Only numbers, letters, and underscores are allowed.', - // segement - segements: 'Segments', + // segment + segments: 'Segments', segPState: 'Persistent Segment State', partitionID: 'Partition ID', segmentID: 'Segment ID', @@ -113,6 +113,9 @@ const collectionTrans = { q_indexID: 'Index ID', q_state: 'Query Segment State', q_mem_size: 'Memory Size', + compact: 'Compact', + compactDialogInfo: `Compaction is a process that optimizes storage and query performance by organizing segments. Learn more

Please note that this operation may take some time to complete, especially for large datasets. We recommend running compaction during periods of lower system activity or during scheduled maintenance to minimize disruption. + `, }; export default collectionTrans; diff --git a/client/src/i18n/en/dialog.ts b/client/src/i18n/en/dialog.ts index 91d5971c..02578662 100644 --- a/client/src/i18n/en/dialog.ts +++ b/client/src/i18n/en/dialog.ts @@ -5,6 +5,7 @@ const dialogTrans = { renameTitle: `Rename {{type}}`, releaseTitle: `Release {{type}}`, createAlias: `Create alias for {{type}}`, + compact: `Compact collection {{type}}`, loadTitle: `Load {{type}}`, loadContent: `You are trying to load a {{type}} with data. Only loaded {{type}} can be searched.`, diff --git a/client/src/pages/dialogs/CompactDialog.tsx b/client/src/pages/dialogs/CompactDialog.tsx new file mode 100644 index 00000000..db19a428 --- /dev/null +++ b/client/src/pages/dialogs/CompactDialog.tsx @@ -0,0 +1,60 @@ +import { FC, useContext } from 'react'; +import { Typography, makeStyles, Theme } from '@material-ui/core'; +import { useTranslation } from 'react-i18next'; +import { rootContext } from '@/context'; +import DialogTemplate from '@/components/customDialog/DialogTemplate'; +import { CompactDialogProps } from './Types'; +import { CollectionHttp } from '@/http'; + +const useStyles = makeStyles((theme: Theme) => ({ + desc: { + margin: '8px 0 16px 0', + maxWidth: '500px' + }, + dialog: {}, +})); + +const CompactDialog: FC = props => { + const { cb, collectionName } = props; + + const classes = useStyles(); + + const { handleCloseDialog } = useContext(rootContext); + const { t: dialogTrans } = useTranslation('dialog'); + const { t: warningTrans } = useTranslation('warning'); + const { t: collectionTrans } = useTranslation('collection'); + const { t: btnTrans } = useTranslation('btn'); + + const handleConfirm = async () => { + const res = await CollectionHttp.compact(collectionName); + console.log('compact', res); + + handleCloseDialog(); + cb && cb(); + }; + + const disabled = false; + + return ( + + + + + } + confirmLabel={btnTrans('confirm')} + handleConfirm={handleConfirm} + confirmDisabled={disabled} + /> + ); +}; + +export default CompactDialog; diff --git a/client/src/pages/dialogs/Types.ts b/client/src/pages/dialogs/Types.ts index e3886ca0..9b9ae80d 100644 --- a/client/src/pages/dialogs/Types.ts +++ b/client/src/pages/dialogs/Types.ts @@ -17,6 +17,13 @@ export interface PartitionCreateProps { collectionName: string; } +interface CollectionDialogBaseProps { + collectionName: string; + cb?: () => void; +} + +export interface CompactDialogProps extends CollectionDialogBaseProps {} + export interface CreateAliasProps { collectionName: string; cb?: () => void; diff --git a/client/src/pages/segments/Segments.tsx b/client/src/pages/segments/Segments.tsx index 610bd434..1f532814 100644 --- a/client/src/pages/segments/Segments.tsx +++ b/client/src/pages/segments/Segments.tsx @@ -1,11 +1,13 @@ -import { useEffect, useState, FC } from 'react'; +import { useEffect, useState, FC, useContext } from 'react'; import { useTranslation } from 'react-i18next'; import { CollectionHttp } from '@/http'; import { usePaginationHook } from '@/hooks'; +import { rootContext } from '@/context'; import AttuGrid from '@/components/grid/Grid'; import { ColDefinitionsType } from '@/components/grid/Types'; import { ToolBarConfig } from '@/components/grid/Types'; import CustomToolBar from '@/components/grid/ToolBar'; +import CompactDialog from '@/pages/dialogs/CompactDialog'; import { getQueryStyles } from '../query/Styles'; import { Segment } from './Types'; @@ -13,7 +15,9 @@ const Segments: FC<{ collectionName: string; }> = ({ collectionName }) => { const classes = getQueryStyles(); - const [segments, setSegements] = useState([]); + const { setDialog } = useContext(rootContext); + + const [segments, setSegments] = useState([]); const { t: collectionTrans } = useTranslation('collection'); const [loading, setLoading] = useState(true); @@ -35,10 +39,14 @@ const Segments: FC<{ }; }); - setSegements(combinedArray); + setSegments(combinedArray); setLoading(false); }; + const onCompactExecuted = async () => { + await fetchSegments(); + }; + const toolbarConfigs: ToolBarConfig[] = [ { type: 'iconBtn', @@ -48,6 +56,25 @@ const Segments: FC<{ label: collectionTrans('refresh'), icon: 'refresh', }, + { + type: 'iconBtn', + onClick: () => { + setDialog({ + open: true, + type: 'custom', + params: { + component: ( + + ), + }, + }); + }, + label: collectionTrans('compact'), + icon: 'compact', + }, ]; const colDefinitions: ColDefinitionsType[] = [