4778 multi select field front implement multi select type (#4887)

This commit is contained in:
martmull
2024-04-11 12:57:08 +02:00
committed by GitHub
parent aecf8783a0
commit a7fcc5d47e
42 changed files with 698 additions and 254 deletions

View File

@ -1,3 +1,5 @@
import { FieldMetadataType } from '~/generated-metadata/graphql.ts';
import {
formatFieldMetadataItemInput,
getOptionValueFromLabel,
@ -46,6 +48,7 @@ describe('formatFieldMetadataItemInput', () => {
const input = {
label: 'Example Label',
icon: 'example-icon',
type: FieldMetadataType.Select,
description: 'Example description',
options: [
{ id: '1', label: 'Option 1', color: 'red' as const, isDefault: true },
@ -86,6 +89,70 @@ describe('formatFieldMetadataItemInput', () => {
const input = {
label: 'Example Label',
icon: 'example-icon',
type: FieldMetadataType.Select,
description: 'Example description',
};
const expected = {
description: 'Example description',
icon: 'example-icon',
label: 'Example Label',
name: 'exampleLabel',
options: undefined,
defaultValue: undefined,
};
const result = formatFieldMetadataItemInput(input);
expect(result).toEqual(expected);
});
it('should format the field metadata item multi select input correctly', () => {
const input = {
label: 'Example Label',
icon: 'example-icon',
type: FieldMetadataType.MultiSelect,
description: 'Example description',
options: [
{ id: '1', label: 'Option 1', color: 'red' as const, isDefault: true },
{ id: '2', label: 'Option 2', color: 'blue' as const, isDefault: true },
],
};
const expected = {
description: 'Example description',
icon: 'example-icon',
label: 'Example Label',
name: 'exampleLabel',
options: [
{
id: '1',
label: 'Option 1',
color: 'red',
position: 0,
value: 'OPTION_1',
},
{
id: '2',
label: 'Option 2',
color: 'blue',
position: 1,
value: 'OPTION_2',
},
],
defaultValue: ["'OPTION_1'", "'OPTION_2'"],
};
const result = formatFieldMetadataItemInput(input);
expect(result).toEqual(expected);
});
it('should handle multi select input without options', () => {
const input = {
label: 'Example Label',
icon: 'example-icon',
type: FieldMetadataType.MultiSelect,
description: 'Example description',
};

View File

@ -1,7 +1,8 @@
import toCamelCase from 'lodash.camelcase';
import toSnakeCase from 'lodash.snakecase';
import { Field } from '~/generated-metadata/graphql';
import { Field, FieldMetadataType } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined.ts';
import { FieldMetadataOption } from '../types/FieldMetadataOption';
@ -20,20 +21,36 @@ export const getOptionValueFromLabel = (label: string) => {
};
export const formatFieldMetadataItemInput = (
input: Pick<Field, 'label' | 'icon' | 'description' | 'defaultValue'> & {
options?: FieldMetadataOption[];
},
input: Pick<
Field,
'label' | 'icon' | 'description' | 'defaultValue' | 'type' | 'options'
>,
) => {
const defaultOption = input.options?.find((option) => option.isDefault);
const options = input.options as FieldMetadataOption[];
let defaultValue = input.defaultValue;
if (input.type === FieldMetadataType.MultiSelect) {
const defaultOptions = options?.filter((option) => option.isDefault);
if (isDefined(defaultOptions)) {
defaultValue = defaultOptions.map(
(defaultOption) => `'${getOptionValueFromLabel(defaultOption.label)}'`,
);
}
}
if (input.type === FieldMetadataType.Select) {
const defaultOption = options?.find((option) => option.isDefault);
defaultValue = isDefined(defaultOption)
? `'${getOptionValueFromLabel(defaultOption.label)}'`
: undefined;
}
// Check if options has unique values
if (input.options !== undefined) {
if (options !== undefined) {
// Compute the values based on the label
const values = input.options.map((option) =>
const values = options.map((option) =>
getOptionValueFromLabel(option.label),
);
if (new Set(values).size !== input.options.length) {
if (new Set(values).size !== options.length) {
throw new Error(
`Options must have unique values, but contains the following duplicates ${values.join(
', ',
@ -43,14 +60,12 @@ export const formatFieldMetadataItemInput = (
}
return {
defaultValue: defaultOption
? `'${getOptionValueFromLabel(defaultOption.label)}'`
: input.defaultValue,
defaultValue,
description: input.description?.trim() ?? null,
icon: input.icon,
label: input.label.trim(),
name: toCamelCase(input.label.trim()),
options: input.options?.map((option, index) => ({
options: options?.map((option, index) => ({
color: option.color,
id: option.id,
label: option.label.trim(),

View File

@ -21,6 +21,7 @@ export const formatFieldMetadataItemsAsFilterDefinitions = ({
FieldMetadataType.Address,
FieldMetadataType.Relation,
FieldMetadataType.Select,
FieldMetadataType.MultiSelect,
FieldMetadataType.Currency,
].includes(field.type)
) {
@ -76,6 +77,8 @@ export const getFilterTypeFromFieldType = (fieldType: FieldMetadataType) => {
return 'RELATION';
case FieldMetadataType.Select:
return 'SELECT';
case FieldMetadataType.MultiSelect:
return 'MULTI_SELECT';
case FieldMetadataType.Address:
return 'ADDRESS';
default:

View File

@ -9,10 +9,10 @@ import { formatFieldMetadataItemInput } from './formatFieldMetadataItemInput';
export type FormatRelationMetadataInputParams = {
relationType: RelationType;
field: Pick<Field, 'label' | 'icon' | 'description'>;
field: Pick<Field, 'label' | 'icon' | 'description' | 'type'>;
objectMetadataId: string;
connect: {
field: Pick<Field, 'label' | 'icon'>;
field: Pick<Field, 'label' | 'icon' | 'type'>;
objectMetadataId: string;
};
};

View File

@ -36,6 +36,7 @@ export const mapFieldMetadataToGraphQLQuery = ({
'BOOLEAN',
'RATING',
'SELECT',
'MULTI_SELECT',
'POSITION',
'RAW_JSON',
] as FieldMetadataType[]