fieldmetadatatype + featurelfag creation (#13021)
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
+18
-3
@@ -1,15 +1,30 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
|
||||
import { FieldMetadataValidationService } from 'src/engine/metadata-modules/field-metadata/field-metadata-validation.service';
|
||||
import { FieldMetadataException } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
|
||||
import { FieldMetadataEnumValidationService } from 'src/engine/metadata-modules/field-metadata/services/field-metadata-enum-validation.service';
|
||||
import { FieldMetadataValidationService } from 'src/engine/metadata-modules/field-metadata/services/field-metadata-validation.service';
|
||||
|
||||
describe('FieldMetadataValidationService', () => {
|
||||
let service: FieldMetadataValidationService;
|
||||
|
||||
beforeAll(() => {
|
||||
service = new FieldMetadataValidationService();
|
||||
beforeAll(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
FieldMetadataValidationService,
|
||||
{
|
||||
provide: FieldMetadataEnumValidationService,
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get<FieldMetadataValidationService>(
|
||||
FieldMetadataValidationService,
|
||||
);
|
||||
});
|
||||
|
||||
it('should validate NUMBER settings successfully', async () => {
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface';
|
||||
|
||||
import { FieldStandardOverridesDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-standard-overrides.dto';
|
||||
import { UpdateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/update-field.input';
|
||||
|
||||
export const buildUpdatableStandardFieldInput = (
|
||||
fieldMetadataInput: UpdateFieldInput,
|
||||
existingFieldMetadata: Pick<
|
||||
FieldMetadataInterface,
|
||||
'type' | 'isNullable' | 'defaultValue' | 'options'
|
||||
>,
|
||||
) => {
|
||||
const updatableStandardFieldInput: UpdateFieldInput & {
|
||||
standardOverrides?: FieldStandardOverridesDTO;
|
||||
} = {
|
||||
id: fieldMetadataInput.id,
|
||||
isActive: fieldMetadataInput.isActive,
|
||||
workspaceId: fieldMetadataInput.workspaceId,
|
||||
defaultValue: fieldMetadataInput.defaultValue,
|
||||
settings: fieldMetadataInput.settings,
|
||||
isLabelSyncedWithName: fieldMetadataInput.isLabelSyncedWithName,
|
||||
};
|
||||
|
||||
if ('standardOverrides' in fieldMetadataInput) {
|
||||
updatableStandardFieldInput.standardOverrides =
|
||||
fieldMetadataInput.standardOverrides as FieldStandardOverridesDTO;
|
||||
}
|
||||
|
||||
if (
|
||||
existingFieldMetadata.type === FieldMetadataType.SELECT ||
|
||||
existingFieldMetadata.type === FieldMetadataType.MULTI_SELECT
|
||||
) {
|
||||
return {
|
||||
...updatableStandardFieldInput,
|
||||
options: fieldMetadataInput.options,
|
||||
};
|
||||
}
|
||||
|
||||
return updatableStandardFieldInput;
|
||||
};
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import {
|
||||
FieldMetadataComplexOption,
|
||||
FieldMetadataDefaultOption,
|
||||
} from 'src/engine/metadata-modules/field-metadata/dtos/options.input';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'src/utils/trim-and-remove-duplicated-whitespaces-from-object-string-properties';
|
||||
|
||||
export const prepareCustomFieldMetadataOptions = (
|
||||
options: FieldMetadataDefaultOption[] | FieldMetadataComplexOption[],
|
||||
): undefined | Pick<FieldMetadataEntity, 'options'> => {
|
||||
return {
|
||||
options: options.map((option) => ({
|
||||
id: v4(),
|
||||
...trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(option, [
|
||||
'label',
|
||||
'value',
|
||||
'id',
|
||||
]),
|
||||
})),
|
||||
};
|
||||
};
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { generateDefaultValue } from 'src/engine/metadata-modules/field-metadata/utils/generate-default-value';
|
||||
import { generateNullable } from 'src/engine/metadata-modules/field-metadata/utils/generate-nullable';
|
||||
import { prepareCustomFieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/utils/prepare-custom-field-metadata-for-options.util';
|
||||
|
||||
export const prepareCustomFieldMetadataForCreation = (
|
||||
fieldMetadataInput: CreateFieldInput,
|
||||
) => {
|
||||
const options = fieldMetadataInput.options
|
||||
? prepareCustomFieldMetadataOptions(fieldMetadataInput.options)
|
||||
: undefined;
|
||||
const defaultValue =
|
||||
fieldMetadataInput.defaultValue ??
|
||||
generateDefaultValue(fieldMetadataInput.type);
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
name: fieldMetadataInput.name,
|
||||
label: fieldMetadataInput.label,
|
||||
icon: fieldMetadataInput.icon,
|
||||
type: fieldMetadataInput.type,
|
||||
isLabelSyncedWithName: fieldMetadataInput.isLabelSyncedWithName,
|
||||
objectMetadataId: fieldMetadataInput.objectMetadataId,
|
||||
workspaceId: fieldMetadataInput.workspaceId,
|
||||
isNullable: generateNullable(
|
||||
fieldMetadataInput.type,
|
||||
fieldMetadataInput.isNullable,
|
||||
fieldMetadataInput.isRemoteCreation,
|
||||
),
|
||||
relationTargetObjectMetadataId:
|
||||
fieldMetadataInput?.relationCreationPayload?.targetObjectMetadataId,
|
||||
defaultValue,
|
||||
...options,
|
||||
isActive: true,
|
||||
isCustom: true,
|
||||
settings: fieldMetadataInput.settings,
|
||||
};
|
||||
};
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
import { i18n } from '@lingui/core';
|
||||
import { isDefined } from 'class-validator';
|
||||
import { APP_LOCALES } from 'twenty-shared/translations';
|
||||
|
||||
import { generateMessageId } from 'src/engine/core-modules/i18n/utils/generateMessageId';
|
||||
import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
|
||||
|
||||
export const resolveOverridableString = (
|
||||
fieldMetadata: Pick<
|
||||
FieldMetadataDTO,
|
||||
'label' | 'description' | 'icon' | 'isCustom' | 'standardOverrides'
|
||||
>,
|
||||
labelKey: 'label' | 'description' | 'icon',
|
||||
locale: keyof typeof APP_LOCALES | undefined,
|
||||
): string => {
|
||||
if (fieldMetadata.isCustom) {
|
||||
return fieldMetadata[labelKey] ?? '';
|
||||
}
|
||||
|
||||
const translationValue =
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
fieldMetadata.standardOverrides?.translations?.[locale]?.[labelKey];
|
||||
|
||||
if (isDefined(translationValue)) {
|
||||
return translationValue;
|
||||
}
|
||||
|
||||
const messageId = generateMessageId(fieldMetadata[labelKey] ?? '');
|
||||
const translatedMessage = i18n._(messageId);
|
||||
|
||||
if (translatedMessage === messageId) {
|
||||
return fieldMetadata[labelKey] ?? '';
|
||||
}
|
||||
|
||||
return translatedMessage;
|
||||
};
|
||||
Reference in New Issue
Block a user