Browse Source

ui part2

Signed-off-by: ryjiang <jiangruiyi@gmail.com>
ryjiang 11 months ago
parent
commit
61d60ac628

+ 1 - 1
client/src/components/icons/Icons.tsx

@@ -855,7 +855,7 @@ const icons: { [x in IconsType]: (props?: any) => React.ReactElement } = {
       {...props}
       {...props}
     >
     >
       <path
       <path
-        d="M4.56427 3.99988C4.58422 3.99989 4.60445 3.99989 4.62496 3.99989H5.49996C5.7761 3.99989 5.99996 4.22375 5.99996 4.49989C5.99996 4.77603 5.7761 4.99989 5.49996 4.99989H4.62496C4.02108 4.99989 3.78932 5.00213 3.60601 5.03713C2.80287 5.1905 2.19181 5.78883 2.03759 6.53312C2.00257 6.70212 1.99996 6.91739 1.99996 7.49989C1.99996 8.08239 2.00257 8.29766 2.03759 8.46666C2.19181 9.21095 2.80287 9.80928 3.60601 9.96265C3.78932 9.99765 4.02108 9.99989 4.62496 9.99989H5.49996C5.7761 9.99989 5.99996 10.2237 5.99996 10.4999C5.99996 10.776 5.7761 10.9999 5.49996 10.9999H4.62496C4.60445 10.9999 4.58422 10.9999 4.56427 10.9999C4.04159 11 3.70712 11 3.41845 10.9449C2.23814 10.7195 1.29871 9.82937 1.05839 8.66955C0.999782 8.38669 0.999848 8.05992 0.999947 7.56301C0.999951 7.54227 0.999955 7.52123 0.999955 7.49989C0.999955 7.47855 0.999951 7.45751 0.999947 7.43677C0.999848 6.93986 0.999782 6.61309 1.05839 6.33023C1.29871 5.17041 2.23814 4.28027 3.41845 4.05488C3.70712 3.99976 4.04159 3.99981 4.56427 3.99988ZM11.3939 5.03713C11.2106 5.00213 10.9788 4.99989 10.375 4.99989H9.49996C9.22381 4.99989 8.99996 4.77603 8.99996 4.49989C8.99996 4.22375 9.22381 3.99989 9.49996 3.99989H10.375C10.3955 3.99989 10.4157 3.99989 10.4356 3.99988C10.9583 3.99981 11.2928 3.99976 11.5815 4.05488C12.7618 4.28027 13.7012 5.17041 13.9415 6.33023C14.0001 6.61309 14.0001 6.93985 14 7.43676C14 7.4575 14 7.47854 14 7.49989C14 7.52124 14 7.54228 14 7.56302C14.0001 8.05992 14.0001 8.38669 13.9415 8.66955C13.7012 9.82937 12.7618 10.7195 11.5815 10.9449C11.2928 11 10.9583 11 10.4356 10.9999C10.4157 10.9999 10.3955 10.9999 10.375 10.9999H9.49996C9.22381 10.9999 8.99996 10.776 8.99996 10.4999C8.99996 10.2237 9.22381 9.99989 9.49996 9.99989H10.375C10.9788 9.99989 11.2106 9.99765 11.3939 9.96265C12.197 9.80928 12.8081 9.21095 12.9623 8.46666C12.9973 8.29766 13 8.08239 13 7.49989C13 6.91739 12.9973 6.70212 12.9623 6.53312C12.8081 5.78883 12.197 5.1905 11.3939 5.03713Z"
+        d="M4.62471 4.00001L4.56402 4.00001C4.04134 3.99993 3.70687 3.99988 3.4182 4.055C2.2379 4.28039 1.29846 5.17053 1.05815 6.33035C0.999538 6.61321 0.999604 6.93998 0.999703 7.43689L0.999711 7.50001L0.999703 7.56313C0.999604 8.06004 0.999538 8.38681 1.05815 8.66967C1.29846 9.8295 2.2379 10.7196 3.4182 10.945C3.70688 11.0001 4.04135 11.0001 4.56403 11L4.62471 11H5.49971C5.77585 11 5.99971 10.7762 5.99971 10.5C5.99971 10.2239 5.77585 10 5.49971 10H4.62471C4.02084 10 3.78907 9.99777 3.60577 9.96277C2.80262 9.8094 2.19157 9.21108 2.03735 8.46678C2.00233 8.29778 1.99971 8.08251 1.99971 7.50001C1.99971 6.91752 2.00233 6.70225 2.03735 6.53324C2.19157 5.78895 2.80262 5.19062 3.60577 5.03725C3.78907 5.00225 4.02084 5.00001 4.62471 5.00001H5.49971C5.77585 5.00001 5.99971 4.77615 5.99971 4.50001C5.99971 4.22387 5.77585 4.00001 5.49971 4.00001H4.62471ZM10.3747 5.00001C10.9786 5.00001 11.2104 5.00225 11.3937 5.03725C12.1968 5.19062 12.8079 5.78895 12.9621 6.53324C12.9971 6.70225 12.9997 6.91752 12.9997 7.50001C12.9997 8.08251 12.9971 8.29778 12.9621 8.46678C12.8079 9.21108 12.1968 9.8094 11.3937 9.96277C11.2104 9.99777 10.9786 10 10.3747 10H9.49971C9.22357 10 8.99971 10.2239 8.99971 10.5C8.99971 10.7762 9.22357 11 9.49971 11H10.3747L10.4354 11C10.9581 11.0001 11.2925 11.0001 11.5812 10.945C12.7615 10.7196 13.701 9.8295 13.9413 8.66967C13.9999 8.38681 13.9998 8.06005 13.9997 7.56314L13.9997 7.50001L13.9997 7.43688C13.9998 6.93998 13.9999 6.61321 13.9413 6.33035C13.701 5.17053 12.7615 4.28039 11.5812 4.055C11.2925 3.99988 10.9581 3.99993 10.4354 4.00001L10.3747 4.00001H9.49971C9.22357 4.00001 8.99971 4.22387 8.99971 4.50001C8.99971 4.77615 9.22357 5.00001 9.49971 5.00001H10.3747ZM5.00038 7C4.72424 7 4.50038 7.22386 4.50038 7.5C4.50038 7.77614 4.72424 8 5.00038 8H10.0004C10.2765 8 10.5004 7.77614 10.5004 7.5C10.5004 7.22386 10.2765 7 10.0004 7H5.00038Z"
         fill="currentColor"
         fill="currentColor"
         fillRule="evenodd"
         fillRule="evenodd"
         clipRule="evenodd"
         clipRule="evenodd"

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

@@ -10,3 +10,7 @@ export const LAST_TIME_HEALTHY_THRESHOLD_CPU =
   'last-time-healthy-threshold-cpu';
   'last-time-healthy-threshold-cpu';
 export const LAST_TIME_HEALTHY_THRESHOLD_MEMORY =
 export const LAST_TIME_HEALTHY_THRESHOLD_MEMORY =
   'last-time-healthy-threshold-memory';
   'last-time-healthy-threshold-memory';
+
+// new local storage keys
+export const ATTU_UI_TREE_WIDTH = 'attu.ui.tree.with';
+export const ATTU_AUTH_HISTORY = 'attu.auth.history';

+ 3 - 3
client/src/context/Data.tsx

@@ -26,7 +26,7 @@ import {
   DatabaseObject,
   DatabaseObject,
 } from '@server/types';
 } from '@server/types';
 import { WS_EVENTS, WS_EVENTS_TYPE, LOADING_STATE } from '@server/utils/Const';
 import { WS_EVENTS, WS_EVENTS_TYPE, LOADING_STATE } from '@server/utils/Const';
-import { DEFAULT_TREE_WIDTH } from '@/consts';
+import { DEFAULT_TREE_WIDTH, ATTU_UI_TREE_WIDTH } from '@/consts';
 import { checkIndexing, checkLoading } from '@server/utils/Shared';
 import { checkIndexing, checkLoading } from '@server/utils/Shared';
 
 
 export const dataContext = createContext<DataContextType>({
 export const dataContext = createContext<DataContextType>({
@@ -367,12 +367,12 @@ export const DataProvider = (props: { children: React.ReactNode }) => {
   // set UI preferences
   // set UI preferences
   const setUIPref = (pref: DataContextType['ui']) => {
   const setUIPref = (pref: DataContextType['ui']) => {
     setUI(pref);
     setUI(pref);
-    localStorage.setItem('attu.ui.tree.width', String(pref.tree.width));
+    localStorage.setItem(ATTU_UI_TREE_WIDTH, String(pref.tree.width));
   };
   };
 
 
   // load UI preferences
   // load UI preferences
   useEffect(() => {
   useEffect(() => {
-    const storedWidth = Number(localStorage.getItem('attu.ui.tree.width'));
+    const storedWidth = Number(localStorage.getItem(ATTU_UI_TREE_WIDTH));
     if (storedWidth) {
     if (storedWidth) {
       setUI(prevUI => ({
       setUI(prevUI => ({
         ...prevUI,
         ...prevUI,

+ 39 - 103
client/src/pages/connect/AuthForm.tsx

@@ -1,5 +1,5 @@
-import React, { useContext, useMemo, useState } from 'react';
-import { makeStyles, Theme, Typography, Menu } from '@material-ui/core';
+import React, { useContext, useEffect, useMemo, useState } from 'react';
+import { Typography, Menu } from '@material-ui/core';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 import CustomButton from '@/components/customButton/CustomButton';
 import CustomButton from '@/components/customButton/CustomButton';
 import CustomInput from '@/components/customInput/CustomInput';
 import CustomInput from '@/components/customInput/CustomInput';
@@ -7,70 +7,13 @@ import { useFormValidation } from '@/hooks';
 import { formatForm } from '@/utils';
 import { formatForm } from '@/utils';
 import { useNavigate } from 'react-router-dom';
 import { useNavigate } from 'react-router-dom';
 import { rootContext, authContext, dataContext } from '@/context';
 import { rootContext, authContext, dataContext } from '@/context';
-import { MILVUS_CLIENT_ID } from '@/consts';
+import { MILVUS_CLIENT_ID, ATTU_AUTH_HISTORY } from '@/consts';
 import { CustomRadio } from '@/components/customRadio/CustomRadio';
 import { CustomRadio } from '@/components/customRadio/CustomRadio';
 import Icons from '@/components/icons/Icons';
 import Icons from '@/components/icons/Icons';
 import CustomToolTip from '@/components/customToolTip/CustomToolTip';
 import CustomToolTip from '@/components/customToolTip/CustomToolTip';
-import ConnectHistory from './ConnectHistory';
 import CustomIconButton from '@/components/customButton/CustomIconButton';
 import CustomIconButton from '@/components/customButton/CustomIconButton';
-
-const useStyles = makeStyles((theme: Theme) => ({
-  wrapper: {
-    display: 'flex',
-    flexDirection: 'column',
-    padding: theme.spacing(0, 3),
-    position: 'relative',
-  },
-  titleWrapper: {
-    textAlign: 'left',
-    alignSelf: 'flex-start',
-    padding: theme.spacing(3, 0),
-    '& svg': {
-      fontSize: 15,
-      marginLeft: theme.spacing(0.5),
-    },
-  },
-  input: {
-    margin: theme.spacing(0.5, 0, 0),
-  },
-  toggle: {
-    display: 'flex',
-    width: '100%',
-    justifyContent: 'flex-start',
-  },
-  star: {
-    position: 'absolute',
-    top: -48,
-    right: -8,
-    marginTop: theme.spacing(1),
-    alignItems: 'center',
-    height: '32px',
-    lineHeight: '32px',
-    color: '#333',
-    background: '#f1f1f1',
-    padding: theme.spacing(0.5, 0, 0.5, 1),
-    fontSize: 13,
-    display: 'block',
-    width: '132px',
-    textDecoration: 'none',
-    marginRight: theme.spacing(1),
-    fontWeight: 500,
-    '&:hover': {
-      fontWeight: 'bold',
-    },
-  },
-  menu: {
-    '& ul': {
-      padding: '0',
-      maxHeight: '400px',
-      overflowY: 'auto',
-    },
-  },
-  icon: {
-    verticalAlign: '-5px',
-    marginRight: theme.spacing(1),
-  },
-}));
+import { useStyles } from './style';
+import { a } from 'vitest/dist/suite-IbNSsUWN';
 
 
 export const AuthForm = (props: any) => {
 export const AuthForm = (props: any) => {
   // styles
   // styles
@@ -94,6 +37,7 @@ export const AuthForm = (props: any) => {
   // UI states
   // UI states
   const [withPass, setWithPass] = useState(authReq.username.length > 0);
   const [withPass, setWithPass] = useState(authReq.username.length > 0);
   const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
   const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
+  const [connections, setConnections] = useState<any[]>([]);
 
 
   // form validation
   // form validation
   const checkedForm = useMemo(() => {
   const checkedForm = useMemo(() => {
@@ -101,6 +45,7 @@ export const AuthForm = (props: any) => {
   }, [authReq]);
   }, [authReq]);
   const { validation, checkIsValid } = useFormValidation(checkedForm);
   const { validation, checkIsValid } = useFormValidation(checkedForm);
 
 
+  // UI handlers
   // handle input change
   // handle input change
   const handleInputChange = (
   const handleInputChange = (
     key: 'address' | 'username' | 'password' | 'database' | 'token',
     key: 'address' | 'username' | 'password' | 'database' | 'token',
@@ -108,13 +53,12 @@ export const AuthForm = (props: any) => {
   ) => {
   ) => {
     setAuthReq(v => ({ ...v, [key]: value }));
     setAuthReq(v => ({ ...v, [key]: value }));
   };
   };
-
-  // UI handlers
-  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
+  // handle menu clicked
+  const handleMenuClick = (event: React.MouseEvent<HTMLButtonElement>) => {
     setAnchorEl(event.currentTarget);
     setAnchorEl(event.currentTarget);
   };
   };
 
 
-  //
+  // handle menu close
   const handleMenuClose = () => {
   const handleMenuClose = () => {
     setAnchorEl(null);
     setAnchorEl(null);
   };
   };
@@ -124,7 +68,7 @@ export const AuthForm = (props: any) => {
     setWithPass(val);
     setWithPass(val);
   };
   };
 
 
-  // connect
+  // handle connect
   const handleConnect = async (event: React.FormEvent) => {
   const handleConnect = async (event: React.FormEvent) => {
     event.preventDefault();
     event.preventDefault();
 
 
@@ -160,6 +104,15 @@ export const AuthForm = (props: any) => {
     return authReq.address.trim().length === 0;
     return authReq.address.trim().length === 0;
   }, [authReq.address]);
   }, [authReq.address]);
 
 
+  // load connection from localstorage
+  useEffect(() => {
+    const connections = JSON.parse(
+      window.localStorage.getItem(ATTU_AUTH_HISTORY) ||
+        '[{"url":"http://102.232.234.234:19121","database":"default","time":"2021-09-09 12:00:00"}]'
+    );
+    setConnections(connections);
+  }, []);
+
   return (
   return (
     <form onSubmit={handleConnect}>
     <form onSubmit={handleConnect}>
       <section className={classes.wrapper}>
       <section className={classes.wrapper}>
@@ -185,8 +138,8 @@ export const AuthForm = (props: any) => {
             fullWidth: true,
             fullWidth: true,
             InputProps: {
             InputProps: {
               endAdornment: (
               endAdornment: (
-                <CustomIconButton onClick={handleClick}>
-                  <Icons.dropdown />
+                <CustomIconButton onClick={handleMenuClick}>
+                  <Icons.link />
                 </CustomIconButton>
                 </CustomIconButton>
               ),
               ),
             },
             },
@@ -293,24 +246,6 @@ export const AuthForm = (props: any) => {
           </>
           </>
         )}
         )}
 
 
-        {/* <div className={classes.toggle}>
-          <CustomRadio
-            defaultChecked={withPrometheus}
-            label={attuTrans.prometheus}
-            handleChange={setWithPrometheus}
-          />
-        </div>
-        {withPrometheus &&
-          prometheusConfigs.map(v => (
-            <CustomInput
-              type="text"
-              textConfig={v}
-              checkValid={checkIsValid}
-              validInfo={validation}
-              key={v.label}
-            />
-          ))} */}
-
         <CustomButton type="submit" variant="contained" disabled={btnDisabled}>
         <CustomButton type="submit" variant="contained" disabled={btnDisabled}>
           {btnTrans('connect')}
           {btnTrans('connect')}
         </CustomButton>
         </CustomButton>
@@ -332,22 +267,23 @@ export const AuthForm = (props: any) => {
         onClose={handleMenuClose}
         onClose={handleMenuClose}
         getContentAnchorEl={null}
         getContentAnchorEl={null}
       >
       >
-        <ConnectHistory
-          data={{
-            url: 'http://102.232.234.234:19121',
-            database: 'default',
-            time: '2021-09-09 12:00:00',
-          }}
-          onClick={onConnectHistoryClicked}
-        />
-        <ConnectHistory
-          data={{
-            url: 'http://102.232.234.234:19121',
-            database: 'default2',
-            time: '2021-09-09 12:00:00',
-          }}
-          onClick={onConnectHistoryClicked}
-        />
+        {connections.map((connection, index) => (
+          <li
+            key={index}
+            className={classes.connection}
+            onClick={() => {
+              onConnectHistoryClicked(connection);
+            }}
+          >
+            <div className="url">
+              <Icons.link className="icon"></Icons.link>
+              <div className="text">
+                {connection.url}/{connection.database}
+              </div>
+            </div>
+            <div className="time">{connection.time}</div>
+          </li>
+        ))}
       </Menu>
       </Menu>
     </form>
     </form>
   );
   );

+ 0 - 79
client/src/pages/connect/ConnectHistory.tsx

@@ -1,79 +0,0 @@
-import CustomToolTip from '@/components/customToolTip/CustomToolTip';
-import Icons from '@/components/icons/Icons';
-import { makeStyles, Theme } from '@material-ui/core';
-
-type Connection = {
-  url: string;
-  database: string;
-  time: string;
-};
-
-export interface ConnectionHistoryProps {
-  data: Connection;
-  onClick: (data: Connection) => void;
-}
-
-export const style = makeStyles((theme: Theme) => ({
-  root: {
-    display: 'flex',
-    justifyContent: 'space-between',
-    fontSize: '14px',
-    width: 360,
-    padding: `0 16px`,
-    '&:hover': {
-      backgroundColor: theme.palette.action.hover,
-    },
-    cursor: 'pointer',
-  },
-  time: {
-    color: theme.palette.text.secondary,
-    fontSize: '12px',
-    padding: '12px 0',
-  },
-  url: {
-    display: 'grid',
-    gridTemplateColumns: '20px 1fr',
-    gap: 4,
-    color: theme.palette.text.primary,
-    fontSize: '14px',
-    padding: '12px 0',
-    '& .url': {
-      overflow: 'hidden',
-      textOverflow: 'ellipsis',
-      maxWidth: 200,
-      wordWrap: 'break-word',
-    },
-  },
-  icon: {
-    verticalAlign: '-3px',
-    marginRight: 8,
-    fontSize: '14px',
-  },
-}));
-
-const ConnectHistory = (props: ConnectionHistoryProps) => {
-  // props
-  const { data, onClick } = props;
-
-  // styles
-  const classes = style();
-
-  return (
-    <li
-      className={classes.root}
-      onClick={() => {
-        onClick(data);
-      }}
-    >
-      <div className={classes.url}>
-        <Icons.link className={classes.icon}></Icons.link>
-        <div className="url">
-          {data.url}/{data.database}
-        </div>
-      </div>
-      <div className={classes.time}>{data.time}</div>
-    </li>
-  );
-};
-
-export default ConnectHistory;

+ 97 - 0
client/src/pages/connect/style.ts

@@ -0,0 +1,97 @@
+import { makeStyles, Theme } from '@material-ui/core';
+
+export const useStyles = makeStyles((theme: Theme) => ({
+  wrapper: {
+    display: 'flex',
+    flexDirection: 'column',
+    padding: theme.spacing(0, 3),
+    position: 'relative',
+  },
+  titleWrapper: {
+    textAlign: 'left',
+    alignSelf: 'flex-start',
+    padding: theme.spacing(3, 0),
+    '& svg': {
+      fontSize: 15,
+      marginLeft: theme.spacing(0.5),
+    },
+  },
+  input: {
+    margin: theme.spacing(0.5, 0, 0),
+  },
+  toggle: {
+    display: 'flex',
+    width: '100%',
+    justifyContent: 'flex-start',
+  },
+  star: {
+    position: 'absolute',
+    top: -48,
+    right: -8,
+    marginTop: theme.spacing(1),
+    alignItems: 'center',
+    height: '32px',
+    lineHeight: '32px',
+    color: '#333',
+    background: '#f1f1f1',
+    padding: theme.spacing(0.5, 0, 0.5, 1),
+    fontSize: 13,
+    display: 'block',
+    width: '132px',
+    textDecoration: 'none',
+    marginRight: theme.spacing(1),
+    fontWeight: 500,
+    '&:hover': {
+      fontWeight: 'bold',
+    },
+  },
+  menu: {
+    '& ul': {
+      padding: '0',
+      maxHeight: '400px',
+      overflowY: 'auto',
+    },
+  },
+  icon: {
+    verticalAlign: '-5px',
+    marginRight: theme.spacing(1),
+  },
+  connection: {
+    display: 'flex',
+    justifyContent: 'space-between',
+    fontSize: '14px',
+    width: 360,
+    padding: `0 16px`,
+    '&:hover': {
+      backgroundColor: theme.palette.action.hover,
+    },
+    cursor: 'pointer',
+
+    '& .url': {
+      display: 'grid',
+      gridTemplateColumns: '20px 1fr',
+      gap: 4,
+      color: theme.palette.text.primary,
+      fontSize: '14px',
+      padding: '12px 0',
+      '& .text': {
+        overflow: 'hidden',
+        textOverflow: 'ellipsis',
+        maxWidth: 200,
+        wordWrap: 'break-word',
+      },
+    },
+
+    '& .icon': {
+      verticalAlign: '-3px',
+      marginRight: 8,
+      fontSize: '14px',
+    },
+
+    '& .time': {
+      color: theme.palette.text.secondary,
+      fontSize: '12px',
+      padding: '12px 0',
+    },
+  },
+}));