AuthForm.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. import React, { useContext, useMemo, useState } from 'react';
  2. import { makeStyles, Theme, Typography } from '@material-ui/core';
  3. import { useTranslation } from 'react-i18next';
  4. import CustomButton from '@/components/customButton/CustomButton';
  5. import CustomInput from '@/components/customInput/CustomInput';
  6. import icons from '@/components/icons/Icons';
  7. import { ITextfieldConfig } from '@/components/customInput/Types';
  8. import { useFormValidation } from '@/hooks';
  9. import { formatForm } from '@/utils';
  10. import { MilvusHttp } from '@/http';
  11. import { useNavigate } from 'react-router-dom';
  12. import { rootContext, authContext, prometheusContext } from '@/context';
  13. import { MILVUS_ADDRESS, LAST_TIME_ADDRESS, MILVUS_URL } from '@/consts';
  14. import { CustomRadio } from '@/components/customRadio/CustomRadio';
  15. const useStyles = makeStyles((theme: Theme) => ({
  16. wrapper: {
  17. display: 'flex',
  18. flexDirection: 'column',
  19. alignItems: 'flex-end',
  20. padding: theme.spacing(0, 3),
  21. },
  22. titleWrapper: {
  23. display: 'flex',
  24. alignItems: 'center',
  25. padding: theme.spacing(3),
  26. margin: '0 auto',
  27. flexDirection: 'column',
  28. '& .title': {
  29. margin: 0,
  30. color: '#323232',
  31. fontWeight: 'bold',
  32. },
  33. },
  34. logo: {
  35. width: '42px',
  36. height: 'auto',
  37. marginBottom: theme.spacing(1),
  38. display: 'block',
  39. },
  40. input: {
  41. margin: theme.spacing(0.5, 0, 0),
  42. },
  43. sslWrapper: {
  44. display: 'flex',
  45. width: '100%',
  46. justifyContent: 'flex-start',
  47. },
  48. }));
  49. export const AuthForm = (props: any) => {
  50. const navigate = useNavigate();
  51. const classes = useStyles();
  52. const { openSnackBar } = useContext(rootContext);
  53. const { setAddress, setIsAuth } = useContext(authContext);
  54. const Logo = icons.zilliz;
  55. const { t: commonTrans } = useTranslation();
  56. const attuTrans = commonTrans('attu');
  57. const { t: btnTrans } = useTranslation('btn');
  58. const { t: warningTrans } = useTranslation('warning');
  59. const { t: successTrans } = useTranslation('success');
  60. const [form, setForm] = useState({
  61. address: window.localStorage.getItem(LAST_TIME_ADDRESS) || MILVUS_URL,
  62. username: '',
  63. password: '',
  64. ssl: false,
  65. });
  66. const checkedForm = useMemo(() => {
  67. return formatForm(form);
  68. }, [form]);
  69. const { validation, checkIsValid } = useFormValidation(checkedForm);
  70. const handleInputChange = (
  71. key: 'address' | 'username' | 'password',
  72. value: string | boolean
  73. ) => {
  74. setForm(v => ({ ...v, [key]: value }));
  75. };
  76. const inputConfigs: ITextfieldConfig[] = useMemo(() => {
  77. const noAuthConfigs: ITextfieldConfig[] = [
  78. {
  79. label: attuTrans.address,
  80. key: 'address',
  81. onChange: (val: string) => handleInputChange('address', val),
  82. variant: 'filled',
  83. className: classes.input,
  84. placeholder: attuTrans.address,
  85. fullWidth: true,
  86. validations: [
  87. {
  88. rule: 'require',
  89. errorText: warningTrans('required', { name: attuTrans.address }),
  90. },
  91. ],
  92. defaultValue: form.address,
  93. },
  94. ];
  95. return [
  96. ...noAuthConfigs,
  97. {
  98. label: `Milvus ${attuTrans.username} ${attuTrans.optional}`,
  99. key: 'username',
  100. onChange: (value: string) => handleInputChange('username', value),
  101. variant: 'filled',
  102. className: classes.input,
  103. placeholder: attuTrans.username,
  104. fullWidth: true,
  105. defaultValue: form.username,
  106. },
  107. {
  108. label: `Milvus ${attuTrans.password} ${attuTrans.optional}`,
  109. key: 'password',
  110. onChange: (value: string) => handleInputChange('password', value),
  111. variant: 'filled',
  112. className: classes.input,
  113. placeholder: attuTrans.password,
  114. fullWidth: true,
  115. type: 'password',
  116. defaultValue: form.username,
  117. },
  118. ];
  119. }, [form, attuTrans, warningTrans, classes.input]);
  120. const {
  121. withPrometheus,
  122. setWithPrometheus,
  123. prometheusAddress,
  124. prometheusInstance,
  125. prometheusNamespace,
  126. setPrometheusAddress,
  127. setPrometheusInstance,
  128. setPrometheusNamespace,
  129. } = useContext(prometheusContext);
  130. const prometheusConfigs: ITextfieldConfig[] = useMemo(
  131. () => [
  132. {
  133. label: `${attuTrans.prometheusAddress}`,
  134. key: 'prometheus_address',
  135. onChange: setPrometheusAddress,
  136. variant: 'filled',
  137. className: classes.input,
  138. placeholder: attuTrans.prometheusAddress,
  139. fullWidth: true,
  140. defaultValue: prometheusAddress,
  141. },
  142. {
  143. label: `${attuTrans.prometheusNamespace}`,
  144. key: 'prometheus_namespace',
  145. onChange: setPrometheusNamespace,
  146. variant: 'filled',
  147. className: classes.input,
  148. placeholder: attuTrans.prometheusNamespace,
  149. fullWidth: true,
  150. defaultValue: prometheusNamespace,
  151. },
  152. {
  153. label: `${attuTrans.prometheusInstance}`,
  154. key: 'prometheus_instance',
  155. onChange: setPrometheusInstance,
  156. variant: 'filled',
  157. className: classes.input,
  158. placeholder: attuTrans.prometheusInstance,
  159. fullWidth: true,
  160. defaultValue: prometheusInstance,
  161. },
  162. ],
  163. []
  164. );
  165. const handleConnect = async (event: React.FormEvent) => {
  166. event.preventDefault();
  167. const address = form.address;
  168. const data = { ...form, address };
  169. await MilvusHttp.connect(data);
  170. setIsAuth(true);
  171. setAddress(address);
  172. openSnackBar(successTrans('connect'));
  173. window.localStorage.setItem(MILVUS_ADDRESS, address);
  174. // store address for next time using
  175. window.localStorage.setItem(LAST_TIME_ADDRESS, address);
  176. navigate('/');
  177. };
  178. const btnDisabled = useMemo(() => {
  179. return form.address.trim().length === 0;
  180. }, [form.address]);
  181. return (
  182. <form onSubmit={handleConnect}>
  183. <section className={classes.wrapper}>
  184. <div className={classes.titleWrapper}>
  185. <Logo classes={{ root: classes.logo }} />
  186. <Typography variant="h2" className="title">
  187. {attuTrans.admin}
  188. </Typography>
  189. </div>
  190. {inputConfigs.map(v => (
  191. <CustomInput
  192. type="text"
  193. textConfig={v}
  194. checkValid={checkIsValid}
  195. validInfo={validation}
  196. key={v.label}
  197. />
  198. ))}
  199. <div className={classes.sslWrapper}>
  200. <CustomRadio
  201. defaultChecked={withPrometheus}
  202. label={attuTrans.prometheus}
  203. handleChange={setWithPrometheus}
  204. />
  205. </div>
  206. {withPrometheus &&
  207. prometheusConfigs.map(v => (
  208. <CustomInput
  209. type="text"
  210. textConfig={v}
  211. checkValid={checkIsValid}
  212. validInfo={validation}
  213. key={v.label}
  214. />
  215. ))}
  216. <CustomButton type="submit" variant="contained" disabled={btnDisabled}>
  217. {btnTrans('connect')}
  218. </CustomButton>
  219. </section>
  220. </form>
  221. );
  222. };