Create.tsx 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. import { makeStyles, Theme } from '@material-ui/core';
  2. import { FC, useContext, useMemo, useState } from 'react';
  3. import { useTranslation } from 'react-i18next';
  4. import DialogTemplate from '../../components/customDialog/DialogTemplate';
  5. import CustomInput from '../../components/customInput/CustomInput';
  6. import { ITextfieldConfig } from '../../components/customInput/Types';
  7. import { rootContext } from '../../context/Root';
  8. import { useFormValidation } from '../../hooks/Form';
  9. import { formatForm } from '../../utils/Form';
  10. import { TypeEnum } from '../../utils/Validation';
  11. import CreateFields from './CreateFields';
  12. import {
  13. CollectionCreateParam,
  14. CollectionCreateProps,
  15. DataTypeEnum,
  16. Field,
  17. } from './Types';
  18. const useStyles = makeStyles((theme: Theme) => ({
  19. fieldset: {
  20. width: '100%',
  21. display: 'flex',
  22. justifyContent: 'space-between',
  23. alignItems: 'center',
  24. '&:last-child': {
  25. flexDirection: 'column',
  26. alignItems: 'flex-start',
  27. },
  28. '& legend': {
  29. marginBottom: theme.spacing(2),
  30. color: `#82838e`,
  31. lineHeight: '20px',
  32. fontSize: '14px',
  33. },
  34. },
  35. input: {
  36. width: '48%',
  37. },
  38. }));
  39. const CreateCollection: FC<CollectionCreateProps> = ({ handleCreate }) => {
  40. const classes = useStyles();
  41. const { handleCloseDialog } = useContext(rootContext);
  42. const { t: collectionTrans } = useTranslation('collection');
  43. const { t: btnTrans } = useTranslation('btn');
  44. const { t: warningTrans } = useTranslation('warning');
  45. const [form, setForm] = useState({
  46. collection_name: '',
  47. description: '',
  48. autoID: true,
  49. });
  50. const [fields, setFields] = useState<Field[]>([
  51. {
  52. data_type: DataTypeEnum.Int64,
  53. is_primary_key: true,
  54. name: null, // we need hide helpertext at first time, so we use null to detect user enter input or not.
  55. description: '',
  56. isDefault: true,
  57. id: '1',
  58. },
  59. {
  60. data_type: DataTypeEnum.FloatVector,
  61. is_primary_key: false,
  62. name: null,
  63. dimension: '128',
  64. description: '',
  65. isDefault: true,
  66. id: '2',
  67. },
  68. ]);
  69. const [fieldsValidation, setFieldsValidation] = useState<
  70. {
  71. [x: string]: string | boolean;
  72. }[]
  73. >([
  74. { id: '1', name: false },
  75. { id: '2', name: false, dimension: true },
  76. ]);
  77. const allFieldsValid = useMemo(() => {
  78. return fieldsValidation.every(v => Object.keys(v).every(key => !!v[key]));
  79. }, [fieldsValidation]);
  80. const checkedForm = useMemo(() => {
  81. const { collection_name } = form;
  82. return formatForm({ collection_name });
  83. }, [form]);
  84. const { validation, checkIsValid, disabled } = useFormValidation(checkedForm);
  85. const changeIsAutoID = (value: boolean) => {
  86. setForm({
  87. ...form,
  88. autoID: value,
  89. });
  90. };
  91. const handleInputChange = (key: string, value: string) => {
  92. setForm(v => ({ ...v, [key]: value }));
  93. };
  94. const generalInfoConfigs: ITextfieldConfig[] = [
  95. {
  96. label: collectionTrans('name'),
  97. key: 'collection_name',
  98. value: form.collection_name,
  99. onChange: (value: string) => handleInputChange('collection_name', value),
  100. variant: 'filled',
  101. validations: [
  102. // cannot be empty
  103. {
  104. rule: 'require',
  105. errorText: warningTrans('required', {
  106. name: collectionTrans('name'),
  107. }),
  108. },
  109. // length <= 255
  110. {
  111. rule: 'range',
  112. extraParam: {
  113. max: 255,
  114. type: 'string',
  115. },
  116. errorText: collectionTrans('nameLengthWarning'),
  117. },
  118. // name can only be combined with letters, number or underscores
  119. {
  120. rule: 'collectionName',
  121. errorText: collectionTrans('nameContentWarning'),
  122. },
  123. // name can not start with number
  124. {
  125. rule: 'firstCharacter',
  126. extraParam: {
  127. invalidTypes: [TypeEnum.number],
  128. },
  129. errorText: collectionTrans('nameFirstLetterWarning'),
  130. },
  131. ],
  132. className: classes.input,
  133. },
  134. {
  135. label: collectionTrans('description'),
  136. key: 'description',
  137. value: form.description,
  138. onChange: (value: string) => handleInputChange('description', value),
  139. variant: 'filled',
  140. validations: [],
  141. className: classes.input,
  142. },
  143. ];
  144. const handleCreateCollection = () => {
  145. const vectorType = [DataTypeEnum.BinaryVector, DataTypeEnum.FloatVector];
  146. const param: CollectionCreateParam = {
  147. ...form,
  148. fields: fields.map(v => {
  149. return {
  150. name: v.name,
  151. description: v.description,
  152. is_primary_key: v.is_primary_key,
  153. data_type: v.data_type,
  154. dimension: vectorType.includes(v.data_type) ? v.dimension : undefined,
  155. };
  156. }),
  157. };
  158. handleCreate(param);
  159. };
  160. return (
  161. <DialogTemplate
  162. title={collectionTrans('createTitle')}
  163. handleCancel={handleCloseDialog}
  164. confirmLabel={btnTrans('create')}
  165. handleConfirm={handleCreateCollection}
  166. confirmDisabled={disabled || !allFieldsValid}
  167. >
  168. <form>
  169. <fieldset className={classes.fieldset}>
  170. <legend>{collectionTrans('general')}</legend>
  171. {generalInfoConfigs.map(config => (
  172. <CustomInput
  173. key={config.key}
  174. type="text"
  175. textConfig={config}
  176. checkValid={checkIsValid}
  177. validInfo={validation}
  178. />
  179. ))}
  180. </fieldset>
  181. <fieldset className={classes.fieldset}>
  182. <legend>{collectionTrans('schema')}</legend>
  183. <CreateFields
  184. fields={fields}
  185. setFields={setFields}
  186. setFieldsValidation={setFieldsValidation}
  187. autoID={form.autoID}
  188. setAutoID={changeIsAutoID}
  189. />
  190. </fieldset>
  191. </form>
  192. </DialogTemplate>
  193. );
  194. };
  195. export default CreateCollection;