123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- import { makeStyles, Theme, TextField, IconButton } from '@material-ui/core';
- import { FC, Fragment, ReactElement } from 'react';
- import { useTranslation } from 'react-i18next';
- import CustomButton from '../../components/customButton/CustomButton';
- import CustomSelector from '../../components/customSelector/CustomSelector';
- import icons from '../../components/icons/Icons';
- import { generateId } from '../../utils/Common';
- import { getCreateFieldType } from '../../utils/Format';
- import {
- ALL_OPTIONS,
- AUTO_ID_OPTIONS,
- VECTOR_FIELDS_OPTIONS,
- } from './Constants';
- import {
- CreateFieldsProps,
- CreateFieldType,
- DataTypeEnum,
- Field,
- } from './Types';
- const useStyles = makeStyles((theme: Theme) => ({
- rowWrapper: {
- display: 'flex',
- flexWrap: 'nowrap',
- alignItems: 'center',
- gap: '10px',
- width: '100%',
- '& .dimension': {
- maxWidth: '160px',
- },
- },
- input: {
- fontSize: '14px',
- },
- primaryInput: {
- maxWidth: '160px',
- },
- select: {
- width: '160px',
- },
- descInput: {
- minWidth: '270px',
- flexGrow: 1,
- },
- btnTxt: {
- textTransform: 'uppercase',
- },
- iconBtn: {
- padding: 0,
- width: '20px',
- height: '20px',
- },
- mb3: {
- marginBottom: theme.spacing(3),
- },
- mb2: {
- marginBottom: theme.spacing(2),
- },
- }));
- const CreateFields: FC<CreateFieldsProps> = ({
- fields,
- setFields,
- // @TODO validation
- setfieldsAllValid,
- setAutoID,
- autoID,
- }) => {
- const { t } = useTranslation('collection');
- const classes = useStyles();
- const primaryInt64Value = 'INT64 (Primary key)';
- const AddIcon = icons.add;
- const RemoveIcon = icons.remove;
- const getSelector = (
- type: 'all' | 'vector',
- label: string,
- value: number,
- onChange: (value: DataTypeEnum) => void
- ) => (
- <CustomSelector
- options={type === 'all' ? ALL_OPTIONS : VECTOR_FIELDS_OPTIONS}
- onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
- onChange(e.target.value as DataTypeEnum);
- }}
- value={value}
- variant="filled"
- label={label}
- classes={{ root: classes.select }}
- />
- );
- const getInput = (
- label: string,
- value: string | number,
- handleChange: (value: string) => void,
- className = '',
- inputClassName = '',
- isReadOnly = false
- ) => (
- <TextField
- label={label}
- value={value}
- onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
- handleChange(e.target.value as string);
- }}
- variant="filled"
- className={className}
- InputProps={{
- classes: {
- input: inputClassName,
- },
- }}
- disabled={isReadOnly}
- />
- );
- const changeFields = (
- id: string,
- key: string,
- value: string | DataTypeEnum
- ) => {
- const newFields = fields.map(f => {
- if (f.id !== id) {
- return f;
- }
- return {
- ...f,
- [key]: value,
- };
- });
- setFields(newFields);
- };
- const handleAddNewField = () => {
- const newDefaultItem: Field = {
- name: '',
- type: DataTypeEnum.Int16,
- isPrimaryKey: false,
- desc: '',
- isDefault: false,
- id: generateId(),
- };
- setFields([...fields, newDefaultItem]);
- };
- const handleRemoveField = (field: Field) => {
- const newFields = fields.filter(f => f.id !== field.id);
- setFields(newFields);
- };
- const generatePrimaryKeyRow = (
- field: Field,
- autoID: boolean
- ): ReactElement => {
- return (
- <div className={`${classes.rowWrapper} ${classes.mb3}`}>
- {getInput(
- t('fieldType'),
- primaryInt64Value,
- () => {},
- classes.primaryInput,
- classes.input,
- true
- )}
- {getInput(t('fieldName'), field.name, (value: string) =>
- changeFields(field.id, 'name', value)
- )}
- <CustomSelector
- label={t('autoId')}
- options={AUTO_ID_OPTIONS}
- value={autoID ? 'true' : 'false'}
- onChange={(e: React.ChangeEvent<{ value: unknown }>) => {
- const autoId = e.target.value === 'true';
- setAutoID(autoId);
- }}
- variant="filled"
- classes={{ root: classes.select }}
- />
- {getInput(
- t('description'),
- field.desc,
- (value: string) => changeFields(field.id, 'desc', value),
- classes.descInput
- )}
- </div>
- );
- };
- const generateDefaultVectorRow = (field: Field): ReactElement => {
- return (
- <>
- <div className={`${classes.rowWrapper} ${classes.mb2}`}>
- {getSelector(
- 'vector',
- t('fieldType'),
- field.type,
- (value: DataTypeEnum) => changeFields(field.id, 'type', value)
- )}
- {getInput(t('fieldName'), field.name, (value: string) =>
- changeFields(field.id, 'name', value)
- )}
- {getInput(
- t('dimension'),
- field.dimension as number,
- (value: string) => changeFields(field.id, 'dimension', value),
- 'dimension'
- )}
- {getInput(
- t('description'),
- field.desc,
- (value: string) => changeFields(field.id, 'desc', value),
- classes.descInput
- )}
- </div>
- <CustomButton onClick={handleAddNewField} className={classes.mb2}>
- <AddIcon />
- <span className={classes.btnTxt}>{t('newBtn')}</span>
- </CustomButton>
- </>
- );
- };
- const generateNumberRow = (field: Field): ReactElement => {
- return (
- <div className={`${classes.rowWrapper} ${classes.mb2}`}>
- <IconButton
- onClick={() => handleRemoveField(field)}
- classes={{ root: classes.iconBtn }}
- aria-label="delete"
- >
- <RemoveIcon />
- </IconButton>
- {getInput(t('fieldName'), field.name, (value: string) =>
- changeFields(field.id, 'name', value)
- )}
- {getSelector('all', t('fieldType'), field.type, (value: DataTypeEnum) =>
- changeFields(field.id, 'type', value)
- )}
- {getInput(
- t('description'),
- field.desc,
- (value: string) => changeFields(field.id, 'desc', value),
- classes.descInput
- )}
- </div>
- );
- };
- const generateVectorRow = (field: Field) => {
- return (
- <div className={`${classes.rowWrapper} ${classes.mb2}`}>
- <IconButton classes={{ root: classes.iconBtn }} aria-label="delete">
- <RemoveIcon />
- </IconButton>
- {getInput(t('fieldName'), field.name, (value: string) =>
- changeFields(field.id, 'name', value)
- )}
- {getSelector('all', t('fieldType'), field.type, (value: DataTypeEnum) =>
- changeFields(field.id, 'type', value)
- )}
- {getInput(
- t('dimension'),
- field.dimension as number,
- (value: string) => changeFields(field.id, 'dimension', value),
- 'dimension'
- )}
- {getInput(
- t('description'),
- field.desc,
- (value: string) => changeFields(field.id, 'desc', value),
- classes.descInput
- )}
- </div>
- );
- };
- const generateFieldRow = (field: Field, autoID: boolean) => {
- const createType: CreateFieldType = getCreateFieldType(field);
- switch (createType) {
- case 'primaryKey': {
- return generatePrimaryKeyRow(field, autoID);
- }
- case 'defaultVector': {
- return generateDefaultVectorRow(field);
- }
- case 'vector': {
- return generateVectorRow(field);
- }
- // use number as default createType
- default: {
- return generateNumberRow(field);
- }
- }
- };
- return (
- <>
- {fields.map((field, index) => (
- <Fragment key={index}>{generateFieldRow(field, autoID)}</Fragment>
- ))}
- </>
- );
- };
- export default CreateFields;
|