Allow input and display of floats for Number fields (#7340)

### Description

- We added a decimal field for a Number Field type in the settings
- We updated the Number Field type create a form with decimals input
- We are not implementing the dropdown present on the Figma because it
seems not related

### Demo


<https://www.loom.com/share/18a8d4b712a14f6d8b66806764f8467f?sid=3fc79b46-ae32-46e3-8635-d0eee02e53b2>

Fixes #6987

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: Marie Stoppa <marie.stoppa@essec.edu>
This commit is contained in:
gitstart-app[bot]
2024-10-04 10:45:25 +02:00
committed by GitHub
parent e3ed574420
commit 97eff774bd
22 changed files with 478 additions and 94 deletions

View File

@ -0,0 +1,48 @@
import { Injectable } from '@nestjs/common';
import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import {
FieldMetadataException,
FieldMetadataExceptionCode,
} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
@Injectable()
export class FieldMetadataValidationService<
T extends FieldMetadataType | 'default' = 'default',
> {
constructor() {}
validateSettingsOrThrow({
fieldType,
settings,
}: {
fieldType: FieldMetadataType;
settings: FieldMetadataSettings<T>;
}) {
switch (fieldType) {
case FieldMetadataType.NUMBER:
this.validateNumberSettings(settings);
break;
default:
break;
}
}
private validateNumberSettings(settings: FieldMetadataSettings<T>) {
if ('decimals' in settings) {
const { decimals } = settings;
if (
decimals !== undefined &&
(decimals < 0 || !Number.isInteger(decimals))
) {
throw new FieldMetadataException(
`Decimals value "${decimals}" must be a positive integer`,
FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
);
}
}
}
}

View File

@ -12,6 +12,7 @@ import { ActorModule } from 'src/engine/core-modules/actor/actor.module';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
import { FieldMetadataValidationService } from 'src/engine/metadata-modules/field-metadata/field-metadata-validation.service';
import { FieldMetadataResolver } from 'src/engine/metadata-modules/field-metadata/field-metadata.resolver';
import { FieldMetadataGraphqlApiExceptionInterceptor } from 'src/engine/metadata-modules/field-metadata/interceptors/field-metadata-graphql-api-exception.interceptor';
import { IsFieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/validators/is-field-metadata-default-value.validator';
@ -44,7 +45,11 @@ import { UpdateFieldInput } from './dtos/update-field.input';
TypeORMModule,
ActorModule,
],
services: [IsFieldMetadataDefaultValue, FieldMetadataService],
services: [
IsFieldMetadataDefaultValue,
FieldMetadataService,
FieldMetadataValidationService,
],
resolvers: [
{
EntityClass: FieldMetadataEntity,

View File

@ -56,6 +56,7 @@ import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service';
import { ViewFieldWorkspaceEntity } from 'src/modules/view/standard-objects/view-field.workspace-entity';
import { FieldMetadataValidationService } from './field-metadata-validation.service';
import {
FieldMetadataEntity,
FieldMetadataType,
@ -82,6 +83,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
private readonly typeORMService: TypeORMService,
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
private readonly fieldMetadataValidationService: FieldMetadataValidationService,
) {
super(fieldMetadataRepository);
}
@ -157,6 +159,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
}
this.validateFieldMetadataInput<CreateFieldInput>(
fieldMetadataInput.type,
fieldMetadataInput,
objectMetadata,
);
@ -391,6 +394,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
}
this.validateFieldMetadataInput<UpdateFieldInput>(
existingFieldMetadata.type,
fieldMetadataInput,
objectMetadata,
);
@ -707,7 +711,11 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
private validateFieldMetadataInput<
T extends UpdateFieldInput | CreateFieldInput,
>(fieldMetadataInput: T, objectMetadata: ObjectMetadataEntity): T {
>(
fieldMetadataType: FieldMetadataType,
fieldMetadataInput: T,
objectMetadata: ObjectMetadataEntity,
): T {
if (fieldMetadataInput.name) {
try {
validateFieldNameValidityOrThrow(fieldMetadataInput.name);
@ -748,6 +756,13 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
}
}
if (fieldMetadataInput.settings) {
this.fieldMetadataValidationService.validateSettingsOrThrow({
fieldType: fieldMetadataType,
settings: fieldMetadataInput.settings,
});
}
return fieldMetadataInput;
}
}

View File

@ -12,6 +12,7 @@ type FieldMetadataDefaultSettings = {
type FieldMetadataNumberSettings = {
dataType: NumberDataType;
decimals?: number;
};
type FieldMetadataDateSettings = {