diff --git a/client/src/components/customTabList/RouteTabList.tsx b/client/src/components/customTabList/RouteTabList.tsx
new file mode 100644
index 00000000..ca955f7b
--- /dev/null
+++ b/client/src/components/customTabList/RouteTabList.tsx
@@ -0,0 +1,116 @@
+import { Box, makeStyles, Tab, Tabs, Theme } from '@material-ui/core';
+import { FC, useState } from 'react';
+import { useNavigate, useLocation } from 'react-router-dom';
+import { ITabListProps, ITabPanel } from './Types';
+
+const useStyles = makeStyles((theme: Theme) => ({
+ wrapper: {
+ display: 'flex',
+ flexDirection: 'column',
+ flexBasis: 0,
+ flexGrow: 1,
+ '& .MuiTab-wrapper': {
+ textTransform: 'capitalize',
+ fontWeight: 'bold',
+ color: '#323232',
+ },
+ },
+ tab: {
+ height: theme.spacing(0.5),
+ backgroundColor: theme.palette.primary.main,
+ },
+ tabContainer: {
+ borderBottom: '1px solid #e9e9ed',
+ },
+ tabContent: {
+ minWidth: 0,
+ marginRight: theme.spacing(3),
+ },
+ tabPanel: {
+ flexBasis: 0,
+ flexGrow: 1,
+ marginTop: theme.spacing(2),
+ overflow: 'hidden',
+ },
+}));
+
+const TabPanel = (props: ITabPanel) => {
+ const { children, value, index, className = '', ...other } = props;
+
+ return (
+
+ {value === index && {children}}
+
+ );
+};
+
+const a11yProps = (index: number) => {
+ return {
+ id: `tab-${index}`,
+ 'aria-controls': `tabpanel-${index}`,
+ };
+};
+
+const RouteTabList: FC = props => {
+ const { tabs, activeIndex = 0, wrapperClass = '' } = props;
+ const classes = useStyles();
+ const [value, setValue] = useState(activeIndex);
+ const navigate = useNavigate();
+ const location = useLocation();
+
+ const handleChange = (event: any, newValue: any) => {
+ setValue(newValue);
+ const newPath =
+ location.pathname.split('/').slice(0, -1).join('/') +
+ '/' +
+ tabs[newValue].path;
+
+ navigate(`${newPath}`);
+ };
+
+ return (
+
+ }}
+ value={value}
+ onChange={handleChange}
+ aria-label="tabs"
+ >
+ {tabs.map((tab, index) => (
+
+ ))}
+
+
+ {tabs.map((tab, index) => (
+
+ {tab.component}
+
+ ))}
+
+ );
+};
+
+export default RouteTabList;
diff --git a/client/src/components/customTabList/Types.ts b/client/src/components/customTabList/Types.ts
index 21cb9fcf..fec17720 100644
--- a/client/src/components/customTabList/Types.ts
+++ b/client/src/components/customTabList/Types.ts
@@ -3,12 +3,13 @@ import { ReactElement } from 'react';
export interface ITab {
label: string;
component: ReactElement;
+ path?: string;
}
export interface ITabListProps {
tabs: ITab[];
activeIndex?: number;
- handleTabChange?: (index: number) => void;
+ handleTabChange?:(index:number) => void;
wrapperClass?: string;
}
diff --git a/client/src/pages/collections/Collection.tsx b/client/src/pages/collections/Collection.tsx
index b5d16c99..d00c75e2 100644
--- a/client/src/pages/collections/Collection.tsx
+++ b/client/src/pages/collections/Collection.tsx
@@ -1,19 +1,17 @@
-import { useMemo, useContext } from 'react';
-import { useNavigate, useLocation, useParams } from 'react-router-dom';
+import { useContext } from 'react';
+import { useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { makeStyles, Theme } from '@material-ui/core';
import { authContext } from '@/context';
import { useNavigationHook } from '@/hooks';
import { ALL_ROUTER_TYPES } from '@/router/Types';
-import CustomTabList from '@/components/customTabList/CustomTabList';
+import RouteTabList from '@/components/customTabList/RouteTabList';
import { ITab } from '@/components/customTabList/Types';
import Partitions from '../partitions/Partitions';
-import { parseLocationSearch } from '@/utils';
import Schema from '../schema/Schema';
import Query from '../query/Query';
import Preview from '../preview/Preview';
import Segments from '../segments/Segments';
-import { TAB_ENUM } from './Types';
const useStyles = makeStyles((theme: Theme) => ({
wrapper: {
@@ -38,49 +36,40 @@ const Collection = () => {
const classes = useStyles();
const { isManaged } = useContext(authContext);
- const { collectionName = '' } = useParams<{
+ const { collectionName = '', tab = '' } = useParams<{
collectionName: string;
+ tab: string;
}>();
useNavigationHook(ALL_ROUTER_TYPES.COLLECTION_DETAIL, { collectionName });
- const navigate = useNavigate();
- const location = useLocation();
-
const { t: collectionTrans } = useTranslation('collection');
- const activeTabIndex = useMemo(() => {
- const { activeIndex } = location.search
- ? parseLocationSearch(location.search)
- : { activeIndex: TAB_ENUM.schema };
- return Number(activeIndex);
- }, [location]);
-
- const handleTabChange = (activeIndex: number) => {
- const path = location.pathname;
- navigate(`${path}?activeIndex=${activeIndex}`);
- };
-
const tabs: ITab[] = [
{
label: collectionTrans('schemaTab'),
- component: ,
+ component: ,
+ path: `schema`,
},
{
label: collectionTrans('partitionTab'),
- component: ,
+ component: ,
+ path: `partitions`,
},
{
label: collectionTrans('previewTab'),
- component: ,
+ component: ,
+ path: `preview`,
},
{
label: collectionTrans('queryTab'),
- component: ,
+ component: ,
+ path: `query`,
},
{
label: collectionTrans('segmentsTab'),
- component: ,
+ component: ,
+ path: `segments`,
},
];
@@ -89,13 +78,14 @@ const Collection = () => {
tabs.splice(1, 1);
}
+ const activeTab = tabs.findIndex(t => t.path === tab);
+
return (
);
diff --git a/client/src/pages/collections/Collections.tsx b/client/src/pages/collections/Collections.tsx
index 44076bc4..1fe8cdf4 100644
--- a/client/src/pages/collections/Collections.tsx
+++ b/client/src/pages/collections/Collections.tsx
@@ -151,7 +151,7 @@ const Collections = () => {
Object.assign(v, {
nameElement: (
diff --git a/client/src/pages/overview/collectionCard/CollectionCard.tsx b/client/src/pages/overview/collectionCard/CollectionCard.tsx
index d8802f60..63b97e67 100644
--- a/client/src/pages/overview/collectionCard/CollectionCard.tsx
+++ b/client/src/pages/overview/collectionCard/CollectionCard.tsx
@@ -154,7 +154,7 @@ const CollectionCard: FC = ({
-
+
{collectionName}
diff --git a/client/src/pages/partitions/Partitions.tsx b/client/src/pages/partitions/Partitions.tsx
index 0c5c8857..7b736f0f 100644
--- a/client/src/pages/partitions/Partitions.tsx
+++ b/client/src/pages/partitions/Partitions.tsx
@@ -1,6 +1,6 @@
import { makeStyles, Theme } from '@material-ui/core';
-import { FC, useContext, useEffect, useState } from 'react';
-import { useSearchParams } from 'react-router-dom';
+import { useContext, useEffect, useState } from 'react';
+import { useSearchParams, useParams } from 'react-router-dom';
import Highlighter from 'react-highlight-words';
import AttuGrid from '@/components/grid/Grid';
import { ColDefinitionsType, ToolBarConfig } from '@/components/grid/Types';
@@ -31,11 +31,9 @@ const useStyles = makeStyles((theme: Theme) => ({
}));
let timer: NodeJS.Timeout | null = null;
-// get init search value from url
-// const { search = '' } = parseLocationSearch(window.location.search);
-const Partitions: FC<{
- collectionName: string;
-}> = ({ collectionName }) => {
+
+const Partitions = () => {
+ const { collectionName = '' } = useParams<{ collectionName: string }>();
const classes = useStyles();
const { t } = useTranslation('partition');
const { t: successTrans } = useTranslation('success');
@@ -67,8 +65,7 @@ const Partitions: FC<{
handleGridSort,
} = usePaginationHook(searchedPartitions);
const [loading, setLoading] = useState(true);
- const { setDialog, handleCloseDialog, openSnackBar } =
- useContext(rootContext);
+ const { setDialog, openSnackBar } = useContext(rootContext);
const fetchPartitions = async (collectionName: string) => {
try {
diff --git a/client/src/pages/preview/Preview.tsx b/client/src/pages/preview/Preview.tsx
index fabfe245..50773603 100644
--- a/client/src/pages/preview/Preview.tsx
+++ b/client/src/pages/preview/Preview.tsx
@@ -1,6 +1,7 @@
-import { FC, useEffect, useState } from 'react';
+import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import AttuGrid from '@/components/grid/Grid';
+import { useParams } from 'react-router-dom';
import { Collection, MilvusIndex } from '@/http';
import { usePaginationHook, useSearchResult } from '@/hooks';
import { generateVector } from '@/utils';
@@ -15,9 +16,8 @@ import { ToolBarConfig } from '@/components/grid/Types';
import CustomToolBar from '@/components/grid/ToolBar';
import { getQueryStyles } from '../query/Styles';
-const Preview: FC<{
- collectionName: string;
-}> = ({ collectionName }) => {
+const Preview = () => {
+ const { collectionName } = useParams<{ collectionName: string }>();
const [fields, setFields] = useState([]);
const [tableLoading, setTableLoading] = useState();
const [queryResult, setQueryResult] = useState();
@@ -140,7 +140,7 @@ const Preview: FC<{
type: 'button',
btnVariant: 'text',
onClick: () => {
- loadData(collectionName);
+ loadData(collectionName!);
},
label: btnTrans('refresh'),
},
diff --git a/client/src/pages/query/Query.tsx b/client/src/pages/query/Query.tsx
index 262036d2..d8e939be 100644
--- a/client/src/pages/query/Query.tsx
+++ b/client/src/pages/query/Query.tsx
@@ -1,6 +1,7 @@
-import { FC, useEffect, useState, useRef, useContext } from 'react';
+import { useEffect, useState, useRef, useContext } from 'react';
import { TextField } from '@material-ui/core';
import { useTranslation } from 'react-i18next';
+import { useParams } from 'react-router-dom';
import { rootContext } from '@/context';
import { Collection, DataService } from '@/http';
import { usePaginationHook, useSearchResult } from '@/hooks';
@@ -22,9 +23,8 @@ import {
} from '@/consts';
import CustomSelector from '@/components/customSelector/CustomSelector';
-const Query: FC<{
- collectionName: string;
-}> = ({ collectionName }) => {
+const Query = () => {
+ const { collectionName } = useParams<{ collectionName: string }>();
const [fields, setFields] = useState([]);
const [expression, setExpression] = useState('');
const [tableLoading, setTableLoading] = useState();
@@ -122,7 +122,7 @@ const Query: FC<{
return;
}
try {
- const res = await Collection.queryData(collectionName, {
+ const res = await Collection.queryData(collectionName!, {
expr: expr,
output_fields: fields.map(i => i.name),
offset: 0,
@@ -145,7 +145,7 @@ const Query: FC<{
};
const handleDelete = async () => {
- await DataService.deleteEntities(collectionName, {
+ await DataService.deleteEntities(collectionName!, {
expr: `${primaryKey.value} in [${selectedData
.map(v =>
primaryKey.type === DataTypeStringEnum.VarChar
diff --git a/client/src/pages/schema/Schema.tsx b/client/src/pages/schema/Schema.tsx
index e31bf0fa..55b99f25 100644
--- a/client/src/pages/schema/Schema.tsx
+++ b/client/src/pages/schema/Schema.tsx
@@ -1,5 +1,6 @@
import { makeStyles, Theme, Typography, Chip } from '@material-ui/core';
-import { FC, useCallback, useEffect, useState } from 'react';
+import { useCallback, useEffect, useState } from 'react';
+import { useParams } from 'react-router-dom';
import AttuGrid from '@/components/grid/Grid';
import { ColDefinitionsType } from '@/components/grid/Types';
import { useTranslation } from 'react-i18next';
@@ -58,9 +59,8 @@ const useStyles = makeStyles((theme: Theme) => ({
},
}));
-const Schema: FC<{
- collectionName: string;
-}> = ({ collectionName }) => {
+const Schema = () => {
+ const { collectionName = '' } = useParams<{ collectionName: string }>();
const classes = useStyles();
const { t: collectionTrans } = useTranslation('collection');
const { t: indexTrans } = useTranslation('index');
@@ -187,7 +187,7 @@ const Schema: FC<{
id: 'indexName',
align: 'left',
disablePadding: true,
- label: indexTrans('indexName')
+ label: indexTrans('indexName'),
},
{
id: '_indexTypeElement',
diff --git a/client/src/pages/segments/Segments.tsx b/client/src/pages/segments/Segments.tsx
index 9d8432a7..30a0f930 100644
--- a/client/src/pages/segments/Segments.tsx
+++ b/client/src/pages/segments/Segments.tsx
@@ -1,5 +1,6 @@
-import { useEffect, useState, FC, useContext } from 'react';
+import { useEffect, useState, useContext } from 'react';
import { useTranslation } from 'react-i18next';
+import { useParams } from 'react-router-dom';
import { Segement } from '@/http';
import { usePaginationHook } from '@/hooks';
import { rootContext } from '@/context';
@@ -12,9 +13,8 @@ import FlushDialog from '@/pages/dialogs/FlushDialog';
import { getQueryStyles } from '../query/Styles';
import { Segment } from './Types';
-const Segments: FC<{
- collectionName: string;
-}> = ({ collectionName }) => {
+const Segments = () => {
+ const { collectionName = '' } = useParams<{ collectionName: string }>();
const classes = getQueryStyles();
const { setDialog } = useContext(rootContext);
@@ -58,7 +58,7 @@ const Segments: FC<{
fetchSegments();
},
label: btnTrans('refresh'),
- icon: 'refresh'
+ icon: 'refresh',
},
{
type: 'button',
diff --git a/client/src/pages/user/Users.tsx b/client/src/pages/user/Users.tsx
index d30e504f..429591b2 100644
--- a/client/src/pages/user/Users.tsx
+++ b/client/src/pages/user/Users.tsx
@@ -1,15 +1,12 @@
-import { useMemo } from 'react';
-import { useNavigate, useLocation } from 'react-router-dom';
+import { useLocation } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { makeStyles, Theme } from '@material-ui/core';
import { useNavigationHook } from '@/hooks';
import { ALL_ROUTER_TYPES } from '@/router/Types';
-import CustomTabList from '@/components/customTabList/CustomTabList';
+import RouteTabList from '@/components/customTabList/RouteTabList';
import { ITab } from '@/components/customTabList/Types';
-import { parseLocationSearch } from '@/utils';
import User from './User';
import Roles from './Roles';
-import { TAB_ENUM } from './Types';
const useStyles = makeStyles((theme: Theme) => ({
wrapper: {
@@ -34,41 +31,32 @@ const Users = () => {
const classes = useStyles();
useNavigationHook(ALL_ROUTER_TYPES.USER);
- const navigate = useNavigate();
const location = useLocation();
+ const currentPath = location.pathname.slice(1);
const { t: userTrans } = useTranslation('user');
- const activeTabIndex = useMemo(() => {
- const { activeIndex } = location.search
- ? parseLocationSearch(location.search)
- : { activeIndex: TAB_ENUM.schema };
- return Number(activeIndex);
- }, [location]);
-
- const handleTabChange = (activeIndex: number) => {
- const path = location.pathname;
- navigate(`${path}?activeIndex=${activeIndex}`);
- };
-
const tabs: ITab[] = [
{
label: userTrans('users'),
component: ,
+ path: 'users',
},
{
label: userTrans('roles'),
component: ,
+ path: 'roles',
},
];
+ const activeTabIndex = tabs.findIndex(t => t.path === currentPath);
+
return (
);
diff --git a/client/src/router/Router.tsx b/client/src/router/Router.tsx
index 82b62354..20941f6d 100644
--- a/client/src/router/Router.tsx
+++ b/client/src/router/Router.tsx
@@ -22,11 +22,17 @@ const RouterComponent = () => {
} />
} />
} />
+ }
+ />
+
} />
} />
{!isManaged && (
<>
} />
+ } />
} />
>
)}