|
@@ -1,5 +1,5 @@
|
|
import { makeStyles, Theme, TextField, IconButton } from '@material-ui/core';
|
|
import { makeStyles, Theme, TextField, IconButton } from '@material-ui/core';
|
|
-import { FC, Fragment, ReactElement } from 'react';
|
|
|
|
|
|
+import { FC, Fragment, ReactElement, useMemo } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { useTranslation } from 'react-i18next';
|
|
import CustomButton from '../../components/customButton/CustomButton';
|
|
import CustomButton from '../../components/customButton/CustomButton';
|
|
import CustomSelector from '../../components/customSelector/CustomSelector';
|
|
import CustomSelector from '../../components/customSelector/CustomSelector';
|
|
@@ -21,6 +21,12 @@ import {
|
|
} from './Types';
|
|
} from './Types';
|
|
|
|
|
|
const useStyles = makeStyles((theme: Theme) => ({
|
|
const useStyles = makeStyles((theme: Theme) => ({
|
|
|
|
+ optionalWrapper: {
|
|
|
|
+ width: '100%',
|
|
|
|
+ paddingRight: theme.spacing(1),
|
|
|
|
+ maxHeight: '240px',
|
|
|
|
+ overflowY: 'auto',
|
|
|
|
+ },
|
|
rowWrapper: {
|
|
rowWrapper: {
|
|
display: 'flex',
|
|
display: 'flex',
|
|
flexWrap: 'nowrap',
|
|
flexWrap: 'nowrap',
|
|
@@ -69,14 +75,13 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|
width: '20px',
|
|
width: '20px',
|
|
height: '20px',
|
|
height: '20px',
|
|
},
|
|
},
|
|
- mb3: {
|
|
|
|
- marginBottom: theme.spacing(3),
|
|
|
|
- },
|
|
|
|
mb2: {
|
|
mb2: {
|
|
marginBottom: theme.spacing(2),
|
|
marginBottom: theme.spacing(2),
|
|
},
|
|
},
|
|
helperText: {
|
|
helperText: {
|
|
- color: theme.palette.error.main,
|
|
|
|
|
|
+ lineHeight: '20px',
|
|
|
|
+ margin: theme.spacing(0.25, 0),
|
|
|
|
+ marginLeft: '12px',
|
|
},
|
|
},
|
|
}));
|
|
}));
|
|
|
|
|
|
@@ -106,6 +111,35 @@ const CreateFields: FC<CreateFieldsProps> = ({
|
|
const AddIcon = icons.add;
|
|
const AddIcon = icons.add;
|
|
const RemoveIcon = icons.remove;
|
|
const RemoveIcon = icons.remove;
|
|
|
|
|
|
|
|
+ const { requiredFields, optionalFields } = useMemo(
|
|
|
|
+ () =>
|
|
|
|
+ fields.reduce(
|
|
|
|
+ (acc, field) => {
|
|
|
|
+ const createType: CreateFieldType = getCreateFieldType(field);
|
|
|
|
+ const requiredTypes: CreateFieldType[] = [
|
|
|
|
+ 'primaryKey',
|
|
|
|
+ 'defaultVector',
|
|
|
|
+ ];
|
|
|
|
+ const key = requiredTypes.includes(createType)
|
|
|
|
+ ? 'requiredFields'
|
|
|
|
+ : 'optionalFields';
|
|
|
|
+
|
|
|
|
+ acc[key].push({
|
|
|
|
+ ...field,
|
|
|
|
+ createType,
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ return acc;
|
|
|
|
+ },
|
|
|
|
+ {
|
|
|
|
+ requiredFields: [] as Field[],
|
|
|
|
+ optionalFields: [] as Field[],
|
|
|
|
+ }
|
|
|
|
+ ),
|
|
|
|
+
|
|
|
|
+ [fields]
|
|
|
|
+ );
|
|
|
|
+
|
|
const getSelector = (
|
|
const getSelector = (
|
|
type: 'all' | 'vector',
|
|
type: 'all' | 'vector',
|
|
label: string,
|
|
label: string,
|
|
@@ -152,6 +186,7 @@ const CreateFields: FC<CreateFieldsProps> = ({
|
|
},
|
|
},
|
|
}}
|
|
}}
|
|
disabled={isReadOnly}
|
|
disabled={isReadOnly}
|
|
|
|
+ error={validate(value) !== ' '}
|
|
helperText={validate(value)}
|
|
helperText={validate(value)}
|
|
FormHelperTextProps={{
|
|
FormHelperTextProps={{
|
|
className: classes.helperText,
|
|
className: classes.helperText,
|
|
@@ -294,7 +329,7 @@ const CreateFields: FC<CreateFieldsProps> = ({
|
|
autoID: boolean
|
|
autoID: boolean
|
|
): ReactElement => {
|
|
): ReactElement => {
|
|
return (
|
|
return (
|
|
- <div className={`${classes.rowWrapper} ${classes.mb3}`}>
|
|
|
|
|
|
+ <div className={`${classes.rowWrapper}`}>
|
|
{getInput({
|
|
{getInput({
|
|
label: collectionTrans('fieldType'),
|
|
label: collectionTrans('fieldType'),
|
|
value: PRIMARY_KEY_FIELD,
|
|
value: PRIMARY_KEY_FIELD,
|
|
@@ -325,7 +360,7 @@ const CreateFields: FC<CreateFieldsProps> = ({
|
|
const generateDefaultVectorRow = (field: Field): ReactElement => {
|
|
const generateDefaultVectorRow = (field: Field): ReactElement => {
|
|
return (
|
|
return (
|
|
<>
|
|
<>
|
|
- <div className={`${classes.rowWrapper} ${classes.mb2}`}>
|
|
|
|
|
|
+ <div className={`${classes.rowWrapper}`}>
|
|
{getSelector(
|
|
{getSelector(
|
|
'vector',
|
|
'vector',
|
|
collectionTrans('fieldType'),
|
|
collectionTrans('fieldType'),
|
|
@@ -350,7 +385,7 @@ const CreateFields: FC<CreateFieldsProps> = ({
|
|
|
|
|
|
const generateNumberRow = (field: Field): ReactElement => {
|
|
const generateNumberRow = (field: Field): ReactElement => {
|
|
return (
|
|
return (
|
|
- <div className={`${classes.rowWrapper} ${classes.mb2}`}>
|
|
|
|
|
|
+ <div className={`${classes.rowWrapper}`}>
|
|
<IconButton
|
|
<IconButton
|
|
onClick={() => handleRemoveField(field)}
|
|
onClick={() => handleRemoveField(field)}
|
|
classes={{ root: classes.iconBtn }}
|
|
classes={{ root: classes.iconBtn }}
|
|
@@ -373,7 +408,7 @@ const CreateFields: FC<CreateFieldsProps> = ({
|
|
|
|
|
|
const generateVectorRow = (field: Field) => {
|
|
const generateVectorRow = (field: Field) => {
|
|
return (
|
|
return (
|
|
- <div className={`${classes.rowWrapper} ${classes.mb2}`}>
|
|
|
|
|
|
+ <div className={`${classes.rowWrapper}`}>
|
|
<IconButton classes={{ root: classes.iconBtn }} aria-label="delete">
|
|
<IconButton classes={{ root: classes.iconBtn }} aria-label="delete">
|
|
<RemoveIcon />
|
|
<RemoveIcon />
|
|
</IconButton>
|
|
</IconButton>
|
|
@@ -391,30 +426,37 @@ const CreateFields: FC<CreateFieldsProps> = ({
|
|
);
|
|
);
|
|
};
|
|
};
|
|
|
|
|
|
- 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);
|
|
|
|
- }
|
|
|
|
|
|
+ const generateRequiredFieldRow = (field: Field, autoID: boolean) => {
|
|
|
|
+ // required type is primaryKey or defaultVector
|
|
|
|
+ if (field.createType === 'primaryKey') {
|
|
|
|
+ return generatePrimaryKeyRow(field, autoID);
|
|
|
|
+ }
|
|
|
|
+ // use defaultVector as default return type
|
|
|
|
+ return generateDefaultVectorRow(field);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ const generateOptionalFieldRow = (field: Field) => {
|
|
|
|
+ // optional type is vector or number
|
|
|
|
+ if (field.createType === 'vector') {
|
|
|
|
+ return generateVectorRow(field);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ // use number as default createType
|
|
|
|
+ return generateNumberRow(field);
|
|
};
|
|
};
|
|
|
|
|
|
return (
|
|
return (
|
|
<>
|
|
<>
|
|
- {fields.map((field, index) => (
|
|
|
|
- <Fragment key={index}>{generateFieldRow(field, autoID)}</Fragment>
|
|
|
|
|
|
+ {requiredFields.map((field, index) => (
|
|
|
|
+ <Fragment key={index}>
|
|
|
|
+ {generateRequiredFieldRow(field, autoID)}
|
|
|
|
+ </Fragment>
|
|
))}
|
|
))}
|
|
|
|
+ <div className={classes.optionalWrapper}>
|
|
|
|
+ {optionalFields.map((field, index) => (
|
|
|
|
+ <Fragment key={index}>{generateOptionalFieldRow(field)}</Fragment>
|
|
|
|
+ ))}
|
|
|
|
+ </div>
|
|
</>
|
|
</>
|
|
);
|
|
);
|
|
};
|
|
};
|