123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- import {
- makeStyles,
- Theme,
- Checkbox,
- FormControlLabel,
- } from '@material-ui/core';
- import { FC, useContext, useMemo, useState, ChangeEvent } from 'react';
- import { useTranslation } from 'react-i18next';
- import DialogTemplate from '@/components/customDialog/DialogTemplate';
- import CustomInput from '@/components/customInput/CustomInput';
- import CustomSelector from '@/components/customSelector/CustomSelector';
- import { ITextfieldConfig } from '@/components/customInput/Types';
- import { rootContext } from '@/context';
- import { useFormValidation } from '@/hooks';
- import { formatForm, TypeEnum } from '@/utils';
- import { DataTypeEnum, ConsistencyLevelEnum, DEFAULT_ATTU_DIM } from '@/consts';
- import CreateFields from '../collections/CreateFields';
- import { CollectionHttp } from '@/http';
- import {
- CollectionCreateParam,
- CollectionCreateProps,
- Field,
- } from '../collections/Types';
- import { CONSISTENCY_LEVEL_OPTIONS } from '../collections/Constants';
- const useStyles = makeStyles((theme: Theme) => ({
- fieldset: {
- width: '100%',
- display: 'flex',
- alignItems: 'center',
- marginBottom: '16px',
- '&:nth-last-child(3)': {
- flexDirection: 'column',
- alignItems: 'flex-start',
- marginBottom: '0',
- },
- '& legend': {
- marginBottom: theme.spacing(1),
- color: theme.palette.attuGrey.dark,
- lineHeight: '20px',
- fontSize: '14px',
- },
- },
- input: {
- width: '100%',
- },
- select: {
- width: '160px',
- '&:first-child': {
- marginLeft: 0,
- },
- },
- dialog: {
- minWidth: '100%',
- },
- }));
- const CreateCollectionDialog: FC<CollectionCreateProps> = ({ onCreate }) => {
- const classes = useStyles();
- const { handleCloseDialog } = useContext(rootContext);
- const { t: collectionTrans } = useTranslation('collection');
- const { t: btnTrans } = useTranslation('btn');
- const { t: warningTrans } = useTranslation('warning');
- const [form, setForm] = useState({
- collection_name: '',
- description: '',
- autoID: true,
- enableDynamicField: false,
- });
- const [consistencyLevel, setConsistencyLevel] =
- useState<ConsistencyLevelEnum>(ConsistencyLevelEnum.Bounded); // Bounded is the default value of consistency level
- const [fields, setFields] = useState<Field[]>([
- {
- data_type: DataTypeEnum.Int64,
- is_primary_key: true,
- name: null, // we need hide helpertext at first time, so we use null to detect user enter input or not.
- description: '',
- isDefault: true,
- id: '1',
- },
- {
- data_type: DataTypeEnum.FloatVector,
- is_primary_key: false,
- name: null,
- dimension: DEFAULT_ATTU_DIM,
- description: '',
- isDefault: true,
- id: '2',
- },
- ]);
- const [fieldsValidation, setFieldsValidation] = useState<
- {
- [x: string]: string | boolean;
- }[]
- >([
- { id: '1', name: false },
- { id: '2', name: false, dimension: true },
- ]);
- const allFieldsValid = useMemo(() => {
- return fieldsValidation.every(v => Object.keys(v).every(key => !!v[key]));
- }, [fieldsValidation]);
- const checkedForm = useMemo(() => {
- const { collection_name } = form;
- return formatForm({ collection_name });
- }, [form]);
- const { validation, checkIsValid, disabled } = useFormValidation(checkedForm);
- const changeIsAutoID = (value: boolean) => {
- setForm({
- ...form,
- autoID: value,
- });
- };
- const changeEnableDynamicField = (
- event: ChangeEvent<any>,
- value: boolean
- ) => {
- setForm({
- ...form,
- enableDynamicField: value,
- });
- };
- const handleInputChange = (key: string, value: string) => {
- setForm(v => ({ ...v, [key]: value }));
- };
- const generalInfoConfigs: ITextfieldConfig[] = [
- {
- label: collectionTrans('name'),
- key: 'collection_name',
- value: form.collection_name,
- onChange: (value: string) => handleInputChange('collection_name', value),
- variant: 'filled',
- validations: [
- // cannot be empty
- {
- rule: 'require',
- errorText: warningTrans('requiredOnly'),
- },
- // length <= 255
- {
- rule: 'range',
- extraParam: {
- max: 255,
- type: 'string',
- },
- errorText: collectionTrans('nameLengthWarning'),
- },
- // name can only be combined with letters, number or underscores
- {
- rule: 'collectionName',
- errorText: collectionTrans('nameContentWarning'),
- },
- // name can not start with number
- {
- rule: 'firstCharacter',
- extraParam: {
- invalidTypes: [TypeEnum.number],
- },
- errorText: collectionTrans('nameFirstLetterWarning'),
- },
- ],
- InputLabelProps: {
- shrink: true,
- },
- size: 'small',
- className: classes.input,
- },
- {
- label: collectionTrans('description'),
- key: 'description',
- value: form.description,
- onChange: (value: string) => handleInputChange('description', value),
- variant: 'filled',
- validations: [],
- size: 'small',
- className: classes.input,
- InputLabelProps: {
- shrink: true,
- },
- },
- ];
- const handleCreateCollection = async () => {
- const vectorType = [DataTypeEnum.BinaryVector, DataTypeEnum.FloatVector];
- const param: CollectionCreateParam = {
- ...form,
- fields: fields.map(v => {
- let data: Field = {
- name: v.name,
- description: v.description,
- is_primary_key: v.is_primary_key,
- is_partition_key: v.is_partition_key,
- data_type: v.data_type,
- };
- // if we need
- if (typeof v.dimension !== undefined) {
- data.dimension = Number(v.dimension);
- }
- if (typeof v.max_length === 'number') {
- data.max_length = Number(v.max_length);
- }
- if (typeof v.element_type !== 'undefined') {
- data.element_type = Number(v.element_type);
- }
- if (typeof v.max_capacity !== 'undefined') {
- data.max_capacity = Number(v.max_capacity);
- }
- v.is_primary_key && (data.autoID = form.autoID);
- return vectorType.includes(v.data_type)
- ? {
- ...data,
- type_params: {
- // if data type is vector, dimension must exist.
- dim: Number(data.dimension!),
- },
- }
- : v.data_type === DataTypeEnum.VarChar ||
- v.element_type === DataTypeEnum.VarChar
- ? {
- ...v,
- type_params: {
- max_length: Number(v.max_length!),
- },
- }
- : { ...data };
- }),
- consistency_level: consistencyLevel,
- };
- await CollectionHttp.createCollection({
- ...param,
- });
- onCreate && onCreate();
- handleCloseDialog();
- };
- return (
- <DialogTemplate
- title={collectionTrans('createTitle')}
- handleClose={() => {
- handleCloseDialog();
- }}
- confirmLabel={btnTrans('create')}
- handleConfirm={handleCreateCollection}
- confirmDisabled={disabled || !allFieldsValid}
- dialogClass={classes.dialog}
- >
- <>
- <fieldset className={classes.fieldset}>
- {generalInfoConfigs.map(config => (
- <CustomInput
- key={config.key}
- type="text"
- textConfig={config}
- checkValid={checkIsValid}
- validInfo={validation}
- />
- ))}
- </fieldset>
- <fieldset className={classes.fieldset}>
- <legend>{collectionTrans('schema')}</legend>
- <CreateFields
- fields={fields}
- setFields={setFields}
- setFieldsValidation={setFieldsValidation}
- autoID={form.autoID}
- setAutoID={changeIsAutoID}
- />
- </fieldset>
- <fieldset className={classes.fieldset}>
- <FormControlLabel
- checked={form.enableDynamicField}
- control={<Checkbox />}
- onChange={changeEnableDynamicField}
- label={collectionTrans('enableDynamicSchema')}
- />
- </fieldset>
- <fieldset className={classes.fieldset}>
- <legend>{collectionTrans('consistency')}</legend>
- <CustomSelector
- wrapperClass={classes.select}
- size="small"
- options={CONSISTENCY_LEVEL_OPTIONS}
- onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
- setConsistencyLevel(e.target.value as ConsistencyLevelEnum);
- }}
- hiddenlabel={true}
- value={consistencyLevel}
- variant="filled"
- />
- </fieldset>
- </>
- </DialogTemplate>
- );
- };
- export default CreateCollectionDialog;
|