Browse Source

add connection history menu ui

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

+ 19 - 0
client/src/components/icons/Icons.tsx

@@ -326,6 +326,7 @@ const icons: { [x in IconsType]: (props?: any) => React.ReactElement } = {
       viewBox="0 0 400 400"
       fill="none"
       xmlns="http://www.w3.org/2000/svg"
+      {...props}
     >
       <path
         fillRule="evenodd"
@@ -834,6 +835,7 @@ const icons: { [x in IconsType]: (props?: any) => React.ReactElement } = {
       viewBox="0 0 15 15"
       fill="none"
       xmlns="http://www.w3.org/2000/svg"
+      {...props}
     >
       <path
         d="M4.85355 2.14645C5.04882 2.34171 5.04882 2.65829 4.85355 2.85355L3.70711 4H9C11.4853 4 13.5 6.01472 13.5 8.5C13.5 10.9853 11.4853 13 9 13H5C4.72386 13 4.5 12.7761 4.5 12.5C4.5 12.2239 4.72386 12 5 12H9C10.933 12 12.5 10.433 12.5 8.5C12.5 6.567 10.933 5 9 5H3.70711L4.85355 6.14645C5.04882 6.34171 5.04882 6.65829 4.85355 6.85355C4.65829 7.04882 4.34171 7.04882 4.14645 6.85355L2.14645 4.85355C1.95118 4.65829 1.95118 4.34171 2.14645 4.14645L4.14645 2.14645C4.34171 1.95118 4.65829 1.95118 4.85355 2.14645Z"
@@ -843,6 +845,23 @@ const icons: { [x in IconsType]: (props?: any) => React.ReactElement } = {
       ></path>
     </svg>
   ),
+  link: (props = {}) => (
+    <svg
+      width="15"
+      height="15"
+      viewBox="0 0 15 15"
+      fill="none"
+      xmlns="http://www.w3.org/2000/svg"
+      {...props}
+    >
+      <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"
+        fill="currentColor"
+        fillRule="evenodd"
+        clipRule="evenodd"
+      ></path>
+    </svg>
+  ),
 };
 
 export default icons;

+ 2 - 1
client/src/components/icons/Types.ts

@@ -53,4 +53,5 @@ export type IconsType =
   | 'star'
   | 'magic'
   | 'code'
-  | 'reset';
+  | 'reset'
+  | 'link';

+ 74 - 54
client/src/pages/connect/AuthForm.tsx

@@ -1,5 +1,5 @@
 import React, { useContext, useMemo, useState } from 'react';
-import { makeStyles, Theme, Typography } from '@material-ui/core';
+import { makeStyles, Theme, Typography, Menu } from '@material-ui/core';
 import { useTranslation } from 'react-i18next';
 import CustomButton from '@/components/customButton/CustomButton';
 import CustomInput from '@/components/customInput/CustomInput';
@@ -11,12 +11,13 @@ import { MILVUS_CLIENT_ID } from '@/consts';
 import { CustomRadio } from '@/components/customRadio/CustomRadio';
 import Icons from '@/components/icons/Icons';
 import CustomToolTip from '@/components/customToolTip/CustomToolTip';
+import ConnectHistory from './ConnectHistory';
+import CustomIconButton from '@/components/customButton/CustomIconButton';
 
 const useStyles = makeStyles((theme: Theme) => ({
   wrapper: {
     display: 'flex',
     flexDirection: 'column',
-    alignItems: 'flex-end',
     padding: theme.spacing(0, 3),
     position: 'relative',
   },
@@ -58,6 +59,13 @@ const useStyles = makeStyles((theme: Theme) => ({
       fontWeight: 'bold',
     },
   },
+  menu: {
+    '& ul': {
+      padding: '0',
+      maxHeight: '400px',
+      overflowY: 'auto',
+    },
+  },
   icon: {
     verticalAlign: '-5px',
     marginRight: theme.spacing(1),
@@ -85,6 +93,7 @@ export const AuthForm = (props: any) => {
 
   // UI states
   const [withPass, setWithPass] = useState(authReq.username.length > 0);
+  const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
 
   // form validation
   const checkedForm = useMemo(() => {
@@ -100,56 +109,22 @@ export const AuthForm = (props: any) => {
     setAuthReq(v => ({ ...v, [key]: value }));
   };
 
-  // const {
-  //   withPrometheus,
-  //   setWithPrometheus,
-  //   prometheusAddress,
-  //   prometheusInstance,
-  //   prometheusNamespace,
-  //   setPrometheusAddress,
-  //   setPrometheusInstance,
-  //   setPrometheusNamespace,
-  // } = useContext(prometheusContext);
-
-  // const prometheusConfigs: ITextfieldConfig[] = useMemo(
-  //   () => [
-  //     {
-  //       label: `${attuTrans.prometheusAddress}`,
-  //       key: 'prometheus_address',
-  //       onChange: setPrometheusAddress,
-  //       variant: 'filled',
-  //       className: classes.input,
-  //       placeholder: attuTrans.prometheusAddress,
-  //       fullWidth: true,
-
-  //       defaultValue: prometheusAddress,
-  //     },
-  //     {
-  //       label: `${attuTrans.prometheusNamespace}`,
-  //       key: 'prometheus_namespace',
-  //       onChange: setPrometheusNamespace,
-  //       variant: 'filled',
-  //       className: classes.input,
-  //       placeholder: attuTrans.prometheusNamespace,
-  //       fullWidth: true,
+  // UI handlers
+  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
+    setAnchorEl(event.currentTarget);
+  };
 
-  //       defaultValue: prometheusNamespace,
-  //     },
-  //     {
-  //       label: `${attuTrans.prometheusInstance}`,
-  //       key: 'prometheus_instance',
-  //       onChange: setPrometheusInstance,
-  //       variant: 'filled',
-  //       className: classes.input,
-  //       placeholder: attuTrans.prometheusInstance,
-  //       fullWidth: true,
+  //
+  const handleMenuClose = () => {
+    setAnchorEl(null);
+  };
 
-  //       defaultValue: prometheusInstance,
-  //     },
-  //   ],
-  //   []
-  // );
+  // handle auth toggle
+  const handleEnableAuth = (val: boolean) => {
+    setWithPass(val);
+  };
 
+  // connect
   const handleConnect = async (event: React.FormEvent) => {
     event.preventDefault();
 
@@ -174,15 +149,17 @@ export const AuthForm = (props: any) => {
     }
   };
 
+  // connect history clicked
+  const onConnectHistoryClicked = (connection: any) => {
+    console.log('connection', connection);
+    handleMenuClose();
+  };
+
+  // is button should be disabled
   const btnDisabled = useMemo(() => {
     return authReq.address.trim().length === 0;
   }, [authReq.address]);
 
-  // handle auth toggle
-  const handleEnableAuth = (val: boolean) => {
-    setWithPass(val);
-  };
-
   return (
     <form onSubmit={handleConnect}>
       <section className={classes.wrapper}>
@@ -194,6 +171,7 @@ export const AuthForm = (props: any) => {
             </CustomToolTip>
           </Typography>
         </div>
+
         {/* address  */}
         <CustomInput
           type="text"
@@ -205,6 +183,13 @@ export const AuthForm = (props: any) => {
             className: classes.input,
             placeholder: attuTrans.address,
             fullWidth: true,
+            InputProps: {
+              endAdornment: (
+                <CustomIconButton onClick={handleClick}>
+                  <Icons.dropdown />
+                </CustomIconButton>
+              ),
+            },
             validations: [
               {
                 rule: 'require',
@@ -219,6 +204,7 @@ export const AuthForm = (props: any) => {
           validInfo={validation}
           key={attuTrans.address}
         />
+
         {/* db  */}
         <CustomInput
           type="text"
@@ -329,6 +315,40 @@ export const AuthForm = (props: any) => {
           {btnTrans('connect')}
         </CustomButton>
       </section>
+
+      <Menu
+        anchorEl={anchorEl}
+        keepMounted
+        className={classes.menu}
+        anchorOrigin={{
+          vertical: 'bottom',
+          horizontal: 'right',
+        }}
+        transformOrigin={{
+          vertical: 'top',
+          horizontal: 'right',
+        }}
+        open={Boolean(anchorEl)}
+        onClose={handleMenuClose}
+        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}
+        />
+      </Menu>
     </form>
   );
 };

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

@@ -0,0 +1,79 @@
+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;