Create.tsx 5.0 KB

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