Feature : Adding percentage option to Input Number (#8481)

fixing #7375

---------

Co-authored-by: guillim <guillaume@twenty.com>
This commit is contained in:
Guillim
2024-11-14 14:23:25 +01:00
committed by GitHub
parent 090f612c4b
commit 15b8b9b158
18 changed files with 166 additions and 47 deletions

View File

@ -54,6 +54,5 @@ export const formatFieldMetadataItemAsFieldDefinition = ({
metadata: fieldDefintionMetadata, metadata: fieldDefintionMetadata,
type: field.type, type: field.type,
}), }),
settings: field.settings,
}; };
}; };

View File

@ -361,7 +361,6 @@ export const RecordBoardCard = ({
metadata: fieldDefinition.metadata, metadata: fieldDefinition.metadata,
type: fieldDefinition.type, type: fieldDefinition.type,
}), }),
settings: fieldDefinition.settings,
}, },
useUpdateRecord: useUpdateOneRecordHook, useUpdateRecord: useUpdateOneRecordHook,
hotkeyScope: InlineCellHotkeyScope.InlineCell, hotkeyScope: InlineCellHotkeyScope.InlineCell,

View File

@ -1,12 +1,16 @@
import { useNumberFieldDisplay } from '@/object-record/record-field/meta-types/hooks/useNumberFieldDisplay'; import { useNumberFieldDisplay } from '@/object-record/record-field/meta-types/hooks/useNumberFieldDisplay';
import { NumberDisplay } from '@/ui/field/display/components/NumberDisplay'; import { NumberDisplay } from '@/ui/field/display/components/NumberDisplay';
import { formatNumber } from '~/utils/format/number';
export const NumberFieldDisplay = () => { export const NumberFieldDisplay = () => {
const { fieldValue, fieldDefinition } = useNumberFieldDisplay(); const { fieldValue, fieldDefinition } = useNumberFieldDisplay();
return ( const decimals = fieldDefinition.metadata.settings?.decimals;
<NumberDisplay const type = fieldDefinition.metadata.settings?.type;
value={fieldValue} const value =
decimals={fieldDefinition.settings?.decimals} type === 'percentage' && fieldValue
/> ? `${formatNumber(Number(fieldValue) * 100, decimals)}%`
); : fieldValue
? formatNumber(Number(fieldValue), decimals)
: null;
return <NumberDisplay value={value} decimals={decimals} />;
}; };

View File

@ -11,6 +11,7 @@ import {
castAsNumberOrNull, castAsNumberOrNull,
} from '~/utils/cast-as-number-or-null'; } from '~/utils/cast-as-number-or-null';
import { isNull } from '@sniptt/guards';
import { FieldContext } from '../../contexts/FieldContext'; import { FieldContext } from '../../contexts/FieldContext';
import { usePersistField } from '../../hooks/usePersistField'; import { usePersistField } from '../../hooks/usePersistField';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata'; import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
@ -33,12 +34,23 @@ export const useNumberField = () => {
const persistField = usePersistField(); const persistField = usePersistField();
const persistNumberField = (newValue: string) => { const persistNumberField = (newValue: string) => {
if (fieldDefinition?.metadata?.settings?.type === 'percentage') {
newValue = newValue.replaceAll('%', '');
if (!canBeCastAsNumberOrNull(newValue)) {
return;
}
const castedValue = castAsNumberOrNull(newValue);
if (!isNull(castedValue)) {
persistField(castedValue / 100);
return;
}
persistField(null);
return;
}
if (!canBeCastAsNumberOrNull(newValue)) { if (!canBeCastAsNumberOrNull(newValue)) {
return; return;
} }
const castedValue = castAsNumberOrNull(newValue); const castedValue = castAsNumberOrNull(newValue);
persistField(castedValue); persistField(castedValue);
}; };

View File

@ -16,7 +16,4 @@ export type FieldDefinition<T extends FieldMetadata> = {
infoTooltipContent?: string; infoTooltipContent?: string;
defaultValue?: any; defaultValue?: any;
editButtonIcon?: IconComponent; editButtonIcon?: IconComponent;
settings?: {
decimals?: number;
};
}; };

View File

@ -10,17 +10,20 @@ import { CurrencyCode } from './CurrencyCode';
export type FieldUuidMetadata = { export type FieldUuidMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldBooleanMetadata = { export type FieldBooleanMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldTextMetadata = { export type FieldTextMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
placeHolder: string; placeHolder: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldDateTimeMetadata = { export type FieldDateTimeMetadata = {
@ -46,17 +49,23 @@ export type FieldNumberMetadata = {
fieldName: string; fieldName: string;
placeHolder: string; placeHolder: string;
isPositive?: boolean; isPositive?: boolean;
settings?: {
decimals?: number;
type?: 'percentage' | 'number';
};
}; };
export type FieldLinkMetadata = { export type FieldLinkMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
placeHolder: string; placeHolder: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldLinksMetadata = { export type FieldLinksMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldCurrencyMetadata = { export type FieldCurrencyMetadata = {
@ -64,56 +73,66 @@ export type FieldCurrencyMetadata = {
fieldName: string; fieldName: string;
placeHolder: string; placeHolder: string;
isPositive?: boolean; isPositive?: boolean;
settings?: Record<string, never>;
}; };
export type FieldFullNameMetadata = { export type FieldFullNameMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
placeHolder: string; placeHolder: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldEmailMetadata = { export type FieldEmailMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
placeHolder: string; placeHolder: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldEmailsMetadata = { export type FieldEmailsMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldPhoneMetadata = { export type FieldPhoneMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
placeHolder: string; placeHolder: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldRatingMetadata = { export type FieldRatingMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldAddressMetadata = { export type FieldAddressMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
placeHolder: string; placeHolder: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldRawJsonMetadata = { export type FieldRawJsonMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
fieldName: string; fieldName: string;
placeHolder: string; placeHolder: string;
settings?: Record<string, never>;
}; };
export type FieldRichTextMetadata = { export type FieldRichTextMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldPositionMetadata = { export type FieldPositionMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldRelationMetadata = { export type FieldRelationMetadata = {
@ -125,6 +144,7 @@ export type FieldRelationMetadata = {
relationType?: RelationDefinitionType; relationType?: RelationDefinitionType;
targetFieldMetadataName?: string; targetFieldMetadataName?: string;
useEditButton?: boolean; useEditButton?: boolean;
settings?: Record<string, never>;
}; };
export type FieldSelectMetadata = { export type FieldSelectMetadata = {
@ -132,33 +152,39 @@ export type FieldSelectMetadata = {
fieldName: string; fieldName: string;
options: { label: string; color: ThemeColor; value: string }[]; options: { label: string; color: ThemeColor; value: string }[];
isNullable: boolean; isNullable: boolean;
settings?: Record<string, never>;
}; };
export type FieldMultiSelectMetadata = { export type FieldMultiSelectMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
fieldName: string; fieldName: string;
options: { label: string; color: ThemeColor; value: string }[]; options: { label: string; color: ThemeColor; value: string }[];
settings?: Record<string, never>;
}; };
export type FieldActorMetadata = { export type FieldActorMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldArrayMetadata = { export type FieldArrayMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
fieldName: string; fieldName: string;
values: { label: string; value: string }[]; values: { label: string; value: string }[];
settings?: Record<string, never>;
}; };
export type FieldPhonesMetadata = { export type FieldPhonesMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldTsVectorMetadata = { export type FieldTsVectorMetadata = {
objectMetadataNameSingular?: string; objectMetadataNameSingular?: string;
fieldName: string; fieldName: string;
settings?: Record<string, never>;
}; };
export type FieldMetadata = export type FieldMetadata =

View File

@ -3,6 +3,8 @@ import { FieldInputDraftValue } from '@/object-record/record-field/types/FieldIn
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { isFieldCurrency } from '@/object-record/record-field/types/guards/isFieldCurrency'; import { isFieldCurrency } from '@/object-record/record-field/types/guards/isFieldCurrency';
import { isFieldCurrencyValue } from '@/object-record/record-field/types/guards/isFieldCurrencyValue'; import { isFieldCurrencyValue } from '@/object-record/record-field/types/guards/isFieldCurrencyValue';
import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber';
import { isFieldNumberValue } from '@/object-record/record-field/types/guards/isFieldNumberValue';
import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson'; import { isFieldRawJson } from '@/object-record/record-field/types/guards/isFieldRawJson';
import { isFieldRawJsonValue } from '@/object-record/record-field/types/guards/isFieldRawJsonValue'; import { isFieldRawJsonValue } from '@/object-record/record-field/types/guards/isFieldRawJsonValue';
import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation'; import { isFieldRelation } from '@/object-record/record-field/types/guards/isFieldRelation';
@ -12,7 +14,7 @@ import { isDefined } from '~/utils/isDefined';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
type computeDraftValueFromFieldValueParams<FieldValue> = { type computeDraftValueFromFieldValueParams<FieldValue> = {
fieldDefinition: Pick<FieldDefinition<FieldMetadata>, 'type'>; fieldDefinition: Pick<FieldDefinition<FieldMetadata>, 'type' | 'metadata'>;
fieldValue: FieldValue; fieldValue: FieldValue;
}; };
@ -40,6 +42,18 @@ export const computeDraftValueFromFieldValue = <FieldValue>({
} as unknown as FieldInputDraftValue<FieldValue>; } as unknown as FieldInputDraftValue<FieldValue>;
} }
if (
isFieldNumber(fieldDefinition) &&
isFieldNumberValue(fieldValue) &&
fieldDefinition.metadata.settings?.type === 'percentage'
) {
return (isUndefinedOrNull(fieldValue)
? ''
: (
fieldValue * 100
).toString()) as unknown as FieldInputDraftValue<FieldValue>;
}
if (isFieldRelation(fieldDefinition)) { if (isFieldRelation(fieldDefinition)) {
return computeEmptyDraftValue<FieldValue>({ fieldDefinition }); return computeEmptyDraftValue<FieldValue>({ fieldDefinition });
} }

View File

@ -2,4 +2,5 @@ import { z } from 'zod';
export const numberFieldDefaultValueSchema = z.object({ export const numberFieldDefaultValueSchema = z.object({
decimals: z.number().nullable(), decimals: z.number().nullable(),
type: z.enum(['percentage', 'number']).nullable(),
}); });

View File

@ -304,9 +304,6 @@ describe('useRecordData', () => {
}, },
}, },
position: expect.any(Number), position: expect.any(Number),
settings: {
displayAsRelativeDate: true,
},
showLabel: undefined, showLabel: undefined,
size: 100, size: 100,
type: 'DATE_TIME', type: 'DATE_TIME',

View File

@ -4,7 +4,9 @@ import { z } from 'zod';
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { numberFieldDefaultValueSchema } from '@/object-record/record-field/validation-schemas/numberFieldDefaultValueSchema'; import { numberFieldDefaultValueSchema } from '@/object-record/record-field/validation-schemas/numberFieldDefaultValueSchema';
import { SettingsDataModelFieldNumberDecimalsInput } from '@/settings/data-model/fields/forms/number/components/SettingsDataModelFieldNumberDecimalInput'; import { SettingsDataModelFieldNumberDecimalsInput } from '@/settings/data-model/fields/forms/number/components/SettingsDataModelFieldNumberDecimalInput';
import { CardContent } from 'twenty-ui'; import { Select } from '@/ui/input/components/Select';
import styled from '@emotion/styled';
import { CardContent, IconNumber9, IconPercentage } from 'twenty-ui';
import { DEFAULT_DECIMAL_VALUE } from '~/utils/format/number'; import { DEFAULT_DECIMAL_VALUE } from '~/utils/format/number';
export const settingsDataModelFieldNumberFormSchema = z.object({ export const settingsDataModelFieldNumberFormSchema = z.object({
@ -15,6 +17,13 @@ export type SettingsDataModelFieldNumberFormValues = z.infer<
typeof settingsDataModelFieldNumberFormSchema typeof settingsDataModelFieldNumberFormSchema
>; >;
const StyledFormCardTitle = styled.div`
color: ${({ theme }) => theme.font.color.light};
font-size: ${({ theme }) => theme.font.size.xs};
font-weight: ${({ theme }) => theme.font.weight.semiBold};
margin-bottom: ${({ theme }) => theme.spacing(1)};
`;
type SettingsDataModelFieldNumberFormProps = { type SettingsDataModelFieldNumberFormProps = {
disabled?: boolean; disabled?: boolean;
fieldMetadataItem: Pick< fieldMetadataItem: Pick<
@ -36,17 +45,43 @@ export const SettingsDataModelFieldNumberForm = ({
defaultValue={{ defaultValue={{
decimals: decimals:
fieldMetadataItem?.settings?.decimals ?? DEFAULT_DECIMAL_VALUE, fieldMetadataItem?.settings?.decimals ?? DEFAULT_DECIMAL_VALUE,
type: fieldMetadataItem?.settings?.type || 'number',
}} }}
control={control} control={control}
render={({ field: { onChange, value } }) => { render={({ field: { onChange, value } }) => {
const count = value?.decimals ?? 0; const count = value?.decimals ?? 0;
const type = value?.type ?? 'number';
return ( return (
<SettingsDataModelFieldNumberDecimalsInput <>
value={count} <StyledFormCardTitle>Type</StyledFormCardTitle>
onChange={(value) => onChange({ decimals: value })} <Select
disabled={disabled} disabled={disabled}
></SettingsDataModelFieldNumberDecimalsInput> dropdownId="selectNumberTypes"
options={[
{
label: 'Number',
value: 'number',
Icon: IconNumber9,
},
{
label: 'Percentage',
value: 'percentage',
Icon: IconPercentage,
},
]}
value={type}
onChange={(value) => onChange({ type: value, decimals: count })}
withSearchInput={false}
dropdownWidthAuto={true}
/>
<br />
<SettingsDataModelFieldNumberDecimalsInput
value={count}
onChange={(value) => onChange({ type: type, decimals: value })}
disabled={disabled}
/>
</>
); );
}} }}
/> />

View File

@ -11,6 +11,7 @@ type SettingsObjectFieldDataTypeProps = {
to?: string; to?: string;
Icon?: IconComponent; Icon?: IconComponent;
label?: string; label?: string;
labelDetail?: string;
value: SettingsFieldType; value: SettingsFieldType;
}; };
@ -50,11 +51,15 @@ const StyledLabelContainer = styled.div`
white-space: nowrap; white-space: nowrap;
`; `;
const StyledSpan = styled.span`
color: ${({ theme }) => theme.font.color.extraLight};
`;
export const SettingsObjectFieldDataType = ({ export const SettingsObjectFieldDataType = ({
to, to,
value, value,
Icon: IconFromProps, Icon: IconFromProps,
label: labelFromProps, label: labelFromProps,
labelDetail,
}: SettingsObjectFieldDataTypeProps) => { }: SettingsObjectFieldDataTypeProps) => {
const theme = useTheme(); const theme = useTheme();
@ -70,7 +75,9 @@ export const SettingsObjectFieldDataType = ({
return ( return (
<StyledDataType as={to ? Link : 'div'} to={to} value={value}> <StyledDataType as={to ? Link : 'div'} to={to} value={value}>
<StyledIcon size={theme.icon.size.sm} /> <StyledIcon size={theme.icon.size.sm} />
<StyledLabelContainer>{label}</StyledLabelContainer> <StyledLabelContainer>
{label} <StyledSpan>{labelDetail && `· ${labelDetail}`}</StyledSpan>
</StyledLabelContainer>
</StyledDataType> </StyledDataType>
); );
}; };

View File

@ -90,7 +90,6 @@ export const SettingsObjectFieldItemTableRow = ({
() => getRelationMetadata({ fieldMetadataItem }), () => getRelationMetadata({ fieldMetadataItem }),
[fieldMetadataItem, getRelationMetadata], [fieldMetadataItem, getRelationMetadata],
) ?? {}; ) ?? {};
const fieldType = fieldMetadataItem.type; const fieldType = fieldMetadataItem.type;
const isFieldTypeSupported = isFieldTypeSupportedInSettings(fieldType); const isFieldTypeSupported = isFieldTypeSupportedInSettings(fieldType);
@ -234,6 +233,9 @@ export const SettingsObjectFieldItemTableRow = ({
? relationObjectMetadataItem?.labelSingular ? relationObjectMetadataItem?.labelSingular
: relationObjectMetadataItem?.labelPlural : relationObjectMetadataItem?.labelPlural
} }
labelDetail={
fieldMetadataItem.settings?.type === 'percentage' ? '%' : undefined
}
to={ to={
relationObjectMetadataItem?.namePlural && relationObjectMetadataItem?.namePlural &&
!relationObjectMetadataItem.isSystem !relationObjectMetadataItem.isSystem

View File

@ -1,5 +1,3 @@
import { formatNumber } from '~/utils/format/number';
import { EllipsisDisplay } from './EllipsisDisplay'; import { EllipsisDisplay } from './EllipsisDisplay';
type NumberDisplayProps = { type NumberDisplayProps = {
@ -7,8 +5,6 @@ type NumberDisplayProps = {
decimals?: number; decimals?: number;
}; };
export const NumberDisplay = ({ value, decimals }: NumberDisplayProps) => ( export const NumberDisplay = ({ value }: NumberDisplayProps) => (
<EllipsisDisplay> <EllipsisDisplay>{value}</EllipsisDisplay>
{value && formatNumber(Number(value), decimals)}
</EllipsisDisplay>
); );

View File

@ -50,7 +50,7 @@ export const mapViewFieldsToColumnDefinitions = ({
isSortable: correspondingColumnDefinition.isSortable, isSortable: correspondingColumnDefinition.isSortable,
isFilterable: correspondingColumnDefinition.isFilterable, isFilterable: correspondingColumnDefinition.isFilterable,
defaultValue: correspondingColumnDefinition.defaultValue, defaultValue: correspondingColumnDefinition.defaultValue,
settings: correspondingColumnDefinition.settings, settings: correspondingColumnDefinition.metadata.settings,
} as ColumnDefinition<FieldMetadata>; } as ColumnDefinition<FieldMetadata>;
}) })
.filter(isDefined); .filter(isDefined);

View File

@ -1,5 +1,14 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { plainToInstance } from 'class-transformer';
import {
IsEnum,
IsInt,
IsOptional,
Min,
validateOrReject,
} from 'class-validator';
import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface'; 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 { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
@ -8,13 +17,29 @@ import {
FieldMetadataExceptionCode, FieldMetadataExceptionCode,
} from 'src/engine/metadata-modules/field-metadata/field-metadata.exception'; } from 'src/engine/metadata-modules/field-metadata/field-metadata.exception';
enum ValueType {
PERCENTAGE = 'percentage',
NUMBER = 'number',
}
class SettingsValidation {
@IsOptional()
@IsInt()
@Min(0)
decimals?: number;
@IsOptional()
@IsEnum(ValueType)
type?: 'percentage' | 'number';
}
@Injectable() @Injectable()
export class FieldMetadataValidationService< export class FieldMetadataValidationService<
T extends FieldMetadataType | 'default' = 'default', T extends FieldMetadataType | 'default' = 'default',
> { > {
constructor() {} constructor() {}
validateSettingsOrThrow({ async validateSettingsOrThrow({
fieldType, fieldType,
settings, settings,
}: { }: {
@ -23,26 +48,28 @@ export class FieldMetadataValidationService<
}) { }) {
switch (fieldType) { switch (fieldType) {
case FieldMetadataType.NUMBER: case FieldMetadataType.NUMBER:
this.validateNumberSettings(settings); await this.validateNumberSettings(settings);
break; break;
default: default:
break; break;
} }
} }
private validateNumberSettings(settings: FieldMetadataSettings<T>) { private async validateNumberSettings(settings: any) {
if ('decimals' in settings) { try {
const { decimals } = settings; const settingsInstance = plainToInstance(SettingsValidation, settings);
if ( await validateOrReject(settingsInstance);
decimals !== undefined && } catch (errors) {
(decimals < 0 || !Number.isInteger(decimals)) const errorMessages = errors
) { .map((error: any) => Object.values(error.constraints))
throw new FieldMetadataException( .flat()
`Decimals value "${decimals}" must be a positive integer`, .join(', ');
FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
); throw new FieldMetadataException(
} `Value for settings is invalid: ${errorMessages}`,
FieldMetadataExceptionCode.INVALID_FIELD_INPUT,
);
} }
} }
} }

View File

@ -410,7 +410,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
// We're running field update under a transaction, so we can rollback if migration fails // We're running field update under a transaction, so we can rollback if migration fails
await fieldMetadataRepository.update(id, fieldMetadataForUpdate); await fieldMetadataRepository.update(id, fieldMetadataForUpdate);
const updatedFieldMetadata = await fieldMetadataRepository.findOne({ const [updatedFieldMetadata] = await fieldMetadataRepository.find({
where: { id }, where: { id },
}); });

View File

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

View File

@ -176,9 +176,11 @@ export {
IconMouse2, IconMouse2,
IconNorthStar, IconNorthStar,
IconNotes, IconNotes,
IconNumber9,
IconNumbers, IconNumbers,
IconPaperclip, IconPaperclip,
IconPencil, IconPencil,
IconPercentage,
IconPhone, IconPhone,
IconPhoto, IconPhoto,
IconPhotoUp, IconPhotoUp,