Refactor default value for select (#5343)

In this PR, we are refactoring two things:
- leverage field.defaultValue for Select and MultiSelect settings form
(instead of option.isDefault)
- use quoted string (ex: "'USD'") for string default values to embrace
backend format

---------

Co-authored-by: Thaïs Guigon <guigon.thais@gmail.com>
This commit is contained in:
Charles Bochet
2024-05-10 10:26:46 +02:00
committed by GitHub
parent 7728c09dba
commit 8590bd7227
40 changed files with 843 additions and 559 deletions

View File

@ -1,5 +1,4 @@
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { SettingsDataModelFieldSelectFormValues } from '@/settings/data-model/components/SettingsObjectFieldSelectForm';
import {
mockedCompanyObjectMetadataItem,
mockedOpportunityObjectMetadataItem,
@ -10,35 +9,21 @@ import { getFieldDefaultPreviewValue } from '../getFieldDefaultPreviewValue';
describe('getFieldDefaultPreviewValue', () => {
describe('SELECT field', () => {
it('returns the default select option', () => {
it('returns the default select option value', () => {
// Given
const objectMetadataItem = mockedOpportunityObjectMetadataItem;
const fieldMetadataItem = mockedOpportunityObjectMetadataItem.fields.find(
({ name }) => name === 'stage',
)!;
const selectOptions: SettingsDataModelFieldSelectFormValues['options'] = [
{
color: 'purple',
label: '🏭 Industry',
value: 'INDUSTRY',
},
{
color: 'pink',
isDefault: true,
label: '💊 Health',
value: 'HEALTH',
},
];
// When
const result = getFieldDefaultPreviewValue({
objectMetadataItem,
fieldMetadataItem,
selectOptions,
fieldMetadataItem: { ...fieldMetadataItem, defaultValue: "'MEETING'" },
});
// Then
expect(result).toEqual(selectOptions[1].value);
expect(result).toEqual('MEETING');
});
it('returns the first select option if no default option was found', () => {
@ -47,28 +32,15 @@ describe('getFieldDefaultPreviewValue', () => {
const fieldMetadataItem = mockedOpportunityObjectMetadataItem.fields.find(
({ name }) => name === 'stage',
)!;
const selectOptions: SettingsDataModelFieldSelectFormValues['options'] = [
{
color: 'purple' as const,
label: '🏭 Industry',
value: 'INDUSTRY',
},
{
color: 'pink' as const,
label: '💊 Health',
value: 'HEALTH',
},
];
// When
const result = getFieldDefaultPreviewValue({
objectMetadataItem,
fieldMetadataItem,
selectOptions,
fieldMetadataItem: { ...fieldMetadataItem, defaultValue: null },
});
// Then
expect(result).toEqual(selectOptions[0].value);
expect(result).toEqual(fieldMetadataItem.options![0].value);
});
});

View File

@ -1,106 +1,12 @@
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { SettingsDataModelFieldSelectFormValues } from '@/settings/data-model/components/SettingsObjectFieldSelectForm';
import {
mockedCompanyObjectMetadataItem,
mockedOpportunityObjectMetadataItem,
mockedPersonObjectMetadataItem,
} from '~/testing/mock-data/metadata';
import { getFieldPreviewValueFromRecord } from '../getFieldPreviewValueFromRecord';
describe('getFieldPreviewValueFromRecord', () => {
describe('SELECT field', () => {
it('returns the select option corresponding to the record field value', () => {
// Given
const record: ObjectRecord = {
id: '',
stage: 'MEETING',
__typename: 'Opportunity',
};
const fieldMetadataItem = mockedOpportunityObjectMetadataItem.fields.find(
({ name }) => name === 'stage',
)!;
const selectOptions: SettingsDataModelFieldSelectFormValues['options'] = [
{
color: 'red',
label: 'New',
value: 'NEW',
},
{
color: 'purple',
label: 'Screening',
value: 'SCREENING',
},
{
color: 'sky',
label: 'Meeting',
value: 'MEETING',
isDefault: true,
},
{
color: 'turquoise',
label: 'Proposal',
value: 'PROPOSAL',
},
{
color: 'yellow',
label: 'Customer',
value: 'CUSTOMER',
},
];
// When
const result = getFieldPreviewValueFromRecord({
record,
fieldMetadataItem,
selectOptions,
});
// Then
expect(result).toEqual(selectOptions[2].value);
});
it('returns undefined if the select option was not found', () => {
// Given
const record: ObjectRecord = {
id: '',
industry: 'DOES_NOT_EXIST',
__typename: 'Opportunity',
};
const fieldMetadataItem = mockedOpportunityObjectMetadataItem.fields.find(
({ name }) => name === 'stage',
)!;
const selectOptions: SettingsDataModelFieldSelectFormValues['options'] = [
{
color: 'purple',
label: '🏭 Industry',
value: 'INDUSTRY',
},
{
color: 'pink',
isDefault: true,
label: '💊 Health',
value: 'HEALTH',
},
{
color: 'turquoise',
label: '🌿 Green tech',
value: 'GREEN_TECH',
},
];
// When
const result = getFieldPreviewValueFromRecord({
record,
fieldMetadataItem,
selectOptions,
});
// Then
expect(result).toBeUndefined();
});
});
describe('RELATION field', () => {
it('returns the first relation record from a list of edges ("to many" relation)', () => {
// Given

View File

@ -0,0 +1,69 @@
import { FieldMetadataType } from '~/generated/graphql';
import { isSelectOptionDefaultValue } from '../isSelectOptionDefaultValue';
describe('isSelectOptionDefaultValue', () => {
describe('SELECT field', () => {
it('returns true if the option value matches the default value', () => {
// Given
const optionValue = 'OPTION_1';
const fieldMetadataItem = {
defaultValue: `'${optionValue}'`,
type: FieldMetadataType.Select,
};
// When
const result = isSelectOptionDefaultValue(optionValue, fieldMetadataItem);
// Then
expect(result).toBe(true);
});
it('returns false if the option value does not match the default value', () => {
// Given
const optionValue = 'OPTION_1';
const fieldMetadataItem = {
defaultValue: "'OPTION_2'",
type: FieldMetadataType.Select,
};
// When
const result = isSelectOptionDefaultValue(optionValue, fieldMetadataItem);
// Then
expect(result).toBe(false);
});
});
describe('MULTI_SELECT field', () => {
it('returns true if the option value is included in the default value array', () => {
// Given
const optionValue = 'OPTION_1';
const fieldMetadataItem = {
defaultValue: ["'OPTION_1'", "'OPTION_2'"],
type: FieldMetadataType.MultiSelect,
};
// When
const result = isSelectOptionDefaultValue(optionValue, fieldMetadataItem);
// Then
expect(result).toBe(true);
});
it('returns false if the option value is not included in the default value array', () => {
// Given
const optionValue = 'OPTION_1';
const fieldMetadataItem = {
defaultValue: ["'OPTION_2'", "'OPTION_3'"],
type: FieldMetadataType.MultiSelect,
};
// When
const result = isSelectOptionDefaultValue(optionValue, fieldMetadataItem);
// Then
expect(result).toBe(false);
});
});
});

View File

@ -2,39 +2,41 @@ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
import { SettingsDataModelFieldSelectFormValues } from '@/settings/data-model/components/SettingsObjectFieldSelectForm';
import { getSettingsFieldTypeConfig } from '@/settings/data-model/utils/getSettingsFieldTypeConfig';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined';
import { stripSimpleQuotesFromString } from '~/utils/string/stripSimpleQuotesFromString';
export const getFieldDefaultPreviewValue = ({
fieldMetadataItem,
objectMetadataItem,
relationObjectMetadataItem,
selectOptions,
}: {
fieldMetadataItem: Pick<FieldMetadataItem, 'type'> & {
fieldMetadataItem: Pick<
FieldMetadataItem,
'type' | 'defaultValue' | 'options'
> & {
id?: string;
name?: string;
};
objectMetadataItem: ObjectMetadataItem;
relationObjectMetadataItem?: ObjectMetadataItem;
selectOptions?: SettingsDataModelFieldSelectFormValues['options'];
}) => {
if (
fieldMetadataItem.type === FieldMetadataType.Select &&
isDefined(selectOptions)
) {
const defaultSelectOption =
selectOptions.find(({ isDefault }) => isDefault) || selectOptions[0];
return defaultSelectOption.value;
if (fieldMetadataItem.type === FieldMetadataType.Select) {
const defaultValue = fieldMetadataItem.defaultValue
? stripSimpleQuotesFromString(fieldMetadataItem.defaultValue)
: null;
return defaultValue ?? fieldMetadataItem.options?.[0]?.value ?? null;
}
if (
fieldMetadataItem.type === FieldMetadataType.MultiSelect &&
isDefined(selectOptions)
) {
return selectOptions.map((selectOption) => selectOption.value);
if (fieldMetadataItem.type === FieldMetadataType.MultiSelect) {
const defaultValues = fieldMetadataItem.defaultValue?.map(
(defaultValue: `'${string}'`) =>
stripSimpleQuotesFromString(defaultValue),
);
return defaultValues?.length
? defaultValues
: fieldMetadataItem.options?.map(({ value }) => value) ?? null;
}
if (

View File

@ -1,26 +1,16 @@
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { SettingsDataModelFieldSelectFormValues } from '@/settings/data-model/components/SettingsObjectFieldSelectForm';
import { FieldMetadataType } from '~/generated-metadata/graphql';
export const getFieldPreviewValueFromRecord = ({
record,
fieldMetadataItem,
selectOptions,
}: {
record: ObjectRecord;
fieldMetadataItem: Pick<FieldMetadataItem, 'name' | 'type'>;
selectOptions?: SettingsDataModelFieldSelectFormValues['options'];
}) => {
const recordFieldValue = record[fieldMetadataItem.name];
// Select field
if (fieldMetadataItem.type === FieldMetadataType.Select) {
return selectOptions?.find(
(selectOption) => selectOption.value === recordFieldValue,
)?.value;
}
// Relation fields (to many)
if (
fieldMetadataItem.type === FieldMetadataType.Relation &&

View File

@ -0,0 +1,25 @@
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { applySimpleQuotesToString } from '~/utils/string/applySimpleQuotesToString';
export const isSelectOptionDefaultValue = (
optionValue: string,
fieldMetadataItem: Pick<FieldMetadataItem, 'defaultValue' | 'type'>,
): boolean => {
if (fieldMetadataItem.type === FieldMetadataType.Select) {
return (
applySimpleQuotesToString(optionValue) === fieldMetadataItem.defaultValue
);
}
if (
fieldMetadataItem.type === FieldMetadataType.MultiSelect &&
Array.isArray(fieldMetadataItem.defaultValue)
) {
return fieldMetadataItem.defaultValue.includes(
applySimpleQuotesToString(optionValue),
);
}
return false;
};