Browse Source

Merge branch 'main' of github.com:zilliztech/attu

ryjiang 1 year ago
parent
commit
5c3cc674c6

+ 4 - 2
client/src/components/layout/GlobalEffect.tsx

@@ -1,7 +1,7 @@
 import React, { useContext } from 'react';
 import React, { useContext } from 'react';
 import axiosInstance from '@/http/Axios';
 import axiosInstance from '@/http/Axios';
 import { rootContext, authContext } from '@/context';
 import { rootContext, authContext } from '@/context';
-import { MILVUS_ADDRESS } from '@/consts';
+import { MILVUS_ADDRESS, LOGIN_USERNAME } from '@/consts';
 import { HTTP_STATUS_CODE } from '@server/utils/Const';
 import { HTTP_STATUS_CODE } from '@server/utils/Const';
 
 
 let axiosResInterceptor: number | null = null;
 let axiosResInterceptor: number | null = null;
@@ -9,7 +9,7 @@ let axiosResInterceptor: number | null = null;
 // we only take side effect here, nothing else
 // we only take side effect here, nothing else
 const GlobalEffect = (props: { children: React.ReactNode }) => {
 const GlobalEffect = (props: { children: React.ReactNode }) => {
   const { openSnackBar } = useContext(rootContext);
   const { openSnackBar } = useContext(rootContext);
-  const { setIsAuth, setAddress } = useContext(authContext);
+  const { setIsAuth, setAddress, setUsername } = useContext(authContext);
 
 
   // catch axios error here
   // catch axios error here
   if (axiosResInterceptor === null) {
   if (axiosResInterceptor === null) {
@@ -27,7 +27,9 @@ const GlobalEffect = (props: { children: React.ReactNode }) => {
         const reset = () => {
         const reset = () => {
           setIsAuth(false);
           setIsAuth(false);
           setAddress('');
           setAddress('');
+          setUsername('');
           window.localStorage.removeItem(MILVUS_ADDRESS);
           window.localStorage.removeItem(MILVUS_ADDRESS);
+          window.localStorage.removeItem(LOGIN_USERNAME);
         };
         };
         switch (response.status) {
         switch (response.status) {
           case HTTP_STATUS_CODE.UNAUTHORIZED:
           case HTTP_STATUS_CODE.UNAUTHORIZED:

+ 18 - 3
client/src/components/layout/Header.tsx

@@ -1,10 +1,17 @@
 import { FC, useContext } from 'react';
 import { FC, useContext } from 'react';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
-import { makeStyles, Theme, createStyles, Typography } from '@material-ui/core';
+import {
+  makeStyles,
+  Theme,
+  createStyles,
+  Typography,
+  Tooltip,
+} from '@material-ui/core';
+import AccountCircleIcon from '@material-ui/icons/AccountCircle';
 import { useNavigate } from 'react-router-dom';
 import { useNavigate } from 'react-router-dom';
 import { navContext, dataContext, authContext } from '@/context';
 import { navContext, dataContext, authContext } from '@/context';
 import { MilvusHttp } from '@/http';
 import { MilvusHttp } from '@/http';
-import { MILVUS_ADDRESS } from '@/consts';
+import { MILVUS_ADDRESS, LOGIN_USERNAME } from '@/consts';
 import CustomSelector from '@/components/customSelector/CustomSelector';
 import CustomSelector from '@/components/customSelector/CustomSelector';
 import icons from '../icons/Icons';
 import icons from '../icons/Icons';
 import { HeaderType } from './Types';
 import { HeaderType } from './Types';
@@ -65,7 +72,8 @@ const Header: FC<HeaderType> = props => {
   const classes = useStyles();
   const classes = useStyles();
   const { navInfo } = useContext(navContext);
   const { navInfo } = useContext(navContext);
   const { database, databases, setDatabase } = useContext(dataContext);
   const { database, databases, setDatabase } = useContext(dataContext);
-  const { address, setAddress, setIsAuth } = useContext(authContext);
+  const { address, setAddress, username, setUsername, setIsAuth } =
+    useContext(authContext);
   const navigate = useNavigate();
   const navigate = useNavigate();
 
 
   const { t: commonTrans } = useTranslation();
   const { t: commonTrans } = useTranslation();
@@ -80,9 +88,11 @@ const Header: FC<HeaderType> = props => {
 
 
   const handleLogout = async () => {
   const handleLogout = async () => {
     setAddress('');
     setAddress('');
+    setUsername('');
     setIsAuth(false);
     setIsAuth(false);
     await MilvusHttp.closeConnection();
     await MilvusHttp.closeConnection();
     window.localStorage.removeItem(MILVUS_ADDRESS);
     window.localStorage.removeItem(MILVUS_ADDRESS);
+    window.localStorage.removeItem(LOGIN_USERNAME);
     // make sure we clear state in all pages
     // make sure we clear state in all pages
     // navigate(0);
     // navigate(0);
   };
   };
@@ -127,6 +137,11 @@ const Header: FC<HeaderType> = props => {
             <Typography className="address">{address}</Typography>
             <Typography className="address">{address}</Typography>
             <Typography className="status">{statusTrans.running}</Typography>
             <Typography className="status">{statusTrans.running}</Typography>
           </div>
           </div>
+          {username && (
+            <Tooltip title={username}>
+              <AccountCircleIcon classes={{ root: classes.icon }} />
+            </Tooltip>
+          )}
           <LogoutIcon classes={{ root: classes.icon }} onClick={handleLogout} />
           <LogoutIcon classes={{ root: classes.icon }} onClick={handleLogout} />
         </div>
         </div>
       </div>
       </div>

+ 1 - 0
client/src/consts/Localstorage.ts

@@ -1,5 +1,6 @@
 export const SESSION = 'CLOUD_SESSION';
 export const SESSION = 'CLOUD_SESSION';
 export const MILVUS_ADDRESS = 'milvus-address';
 export const MILVUS_ADDRESS = 'milvus-address';
+export const LOGIN_USERNAME = 'login-username';
 export const LAST_TIME_ADDRESS = 'last-time-address';
 export const LAST_TIME_ADDRESS = 'last-time-address';
 export const LAST_TIME_DATABASE = 'last-time-database';
 export const LAST_TIME_DATABASE = 'last-time-database';
 
 

+ 17 - 3
client/src/context/Auth.tsx

@@ -1,13 +1,15 @@
 import { createContext, useEffect, useState } from 'react';
 import { createContext, useEffect, useState } from 'react';
-import { MILVUS_ADDRESS } from '@/consts';
+import { MILVUS_ADDRESS, LOGIN_USERNAME } from '@/consts';
 import { MilvusHttp } from '@/http';
 import { MilvusHttp } from '@/http';
 import { AuthContextType } from './Types';
 import { AuthContextType } from './Types';
 
 
 export const authContext = createContext<AuthContextType>({
 export const authContext = createContext<AuthContextType>({
   isAuth: false,
   isAuth: false,
   address: '',
   address: '',
+  username: '',
   isManaged: false,
   isManaged: false,
   setAddress: () => {},
   setAddress: () => {},
+  setUsername: () => {},
   setIsAuth: () => {},
   setIsAuth: () => {},
 });
 });
 
 
@@ -17,6 +19,10 @@ export const AuthProvider = (props: { children: React.ReactNode }) => {
   const [address, setAddress] = useState<string>(
   const [address, setAddress] = useState<string>(
     window.localStorage.getItem(MILVUS_ADDRESS) || ''
     window.localStorage.getItem(MILVUS_ADDRESS) || ''
   );
   );
+  // get login username from local storage
+  const [username, setUsername] = useState<string>(
+    window.localStorage.getItem(LOGIN_USERNAME) || ''
+  );
   const [isAuth, setIsAuth] = useState<boolean>(address !== '');
   const [isAuth, setIsAuth] = useState<boolean>(address !== '');
   // const isAuth = useMemo(() => !!address, [address]);
   // const isAuth = useMemo(() => !!address, [address]);
 
 
@@ -33,20 +39,28 @@ export const AuthProvider = (props: { children: React.ReactNode }) => {
       if (!res.connected) {
       if (!res.connected) {
         window.localStorage.removeItem(MILVUS_ADDRESS);
         window.localStorage.removeItem(MILVUS_ADDRESS);
       }
       }
+
+      const username = window.localStorage.getItem(LOGIN_USERNAME) || '';
+      if (!username) {
+        return;
+      }
+      setUsername(username);
     };
     };
     check();
     check();
-  }, [setAddress]);
+  }, [setAddress, setUsername]);
 
 
   useEffect(() => {
   useEffect(() => {
     document.title = address ? `${address} - Attu` : 'Attu';
     document.title = address ? `${address} - Attu` : 'Attu';
-  }, [address]);
+  }, [address, username]);
 
 
   return (
   return (
     <Provider
     <Provider
       value={{
       value={{
         isAuth,
         isAuth,
         address,
         address,
+        username,
         setAddress,
         setAddress,
+        setUsername,
         setIsAuth,
         setIsAuth,
         isManaged: address.includes('vectordb.zillizcloud.com'),
         isManaged: address.includes('vectordb.zillizcloud.com'),
       }}
       }}

+ 2 - 0
client/src/context/Types.ts

@@ -57,8 +57,10 @@ export type OpenSnackBarType = (
 export type AuthContextType = {
 export type AuthContextType = {
   isAuth: boolean;
   isAuth: boolean;
   address: string;
   address: string;
+  username: string;
   isManaged: boolean;
   isManaged: boolean;
   setAddress: Dispatch<SetStateAction<string>>;
   setAddress: Dispatch<SetStateAction<string>>;
+  setUsername: Dispatch<SetStateAction<string>>;
   setIsAuth: Dispatch<SetStateAction<boolean>>;
   setIsAuth: Dispatch<SetStateAction<boolean>>;
 };
 };
 
 

+ 4 - 1
client/src/pages/connect/AuthForm.tsx

@@ -17,6 +17,7 @@ import {
 } from '@/context';
 } from '@/context';
 import {
 import {
   MILVUS_ADDRESS,
   MILVUS_ADDRESS,
+  LOGIN_USERNAME,
   LAST_TIME_ADDRESS,
   LAST_TIME_ADDRESS,
   MILVUS_URL,
   MILVUS_URL,
   LAST_TIME_DATABASE,
   LAST_TIME_DATABASE,
@@ -63,7 +64,7 @@ export const AuthForm = (props: any) => {
   const classes = useStyles();
   const classes = useStyles();
 
 
   const { openSnackBar } = useContext(rootContext);
   const { openSnackBar } = useContext(rootContext);
-  const { setAddress, setIsAuth } = useContext(authContext);
+  const { setAddress, setUsername, setIsAuth } = useContext(authContext);
   const { setDatabase } = useContext(dataContext);
   const { setDatabase } = useContext(dataContext);
 
 
   const Logo = icons.zilliz;
   const Logo = icons.zilliz;
@@ -206,10 +207,12 @@ export const AuthForm = (props: any) => {
 
 
     setIsAuth(true);
     setIsAuth(true);
     setAddress(form.address);
     setAddress(form.address);
+    setUsername(form.username);
     setDatabase(result.database);
     setDatabase(result.database);
 
 
     openSnackBar(successTrans('connect'));
     openSnackBar(successTrans('connect'));
     window.localStorage.setItem(MILVUS_ADDRESS, form.address);
     window.localStorage.setItem(MILVUS_ADDRESS, form.address);
+    window.localStorage.setItem(LOGIN_USERNAME, form.username);
     // store address for next time using
     // store address for next time using
     window.localStorage.setItem(LAST_TIME_ADDRESS, form.address);
     window.localStorage.setItem(LAST_TIME_ADDRESS, form.address);
     window.localStorage.setItem(LAST_TIME_DATABASE, form.database);
     window.localStorage.setItem(LAST_TIME_DATABASE, form.database);