diff --git a/front/src/generated-metadata/graphql.ts b/front/src/generated-metadata/graphql.ts index 7b127d1a5..f0741e8c6 100644 --- a/front/src/generated-metadata/graphql.ts +++ b/front/src/generated-metadata/graphql.ts @@ -221,7 +221,7 @@ export type CreateRelationInput = { toObjectMetadataId: Scalars['String']['input']; }; -export enum Currency { +export enum CurrencyCode { Aed = 'AED', Afn = 'AFN', All = 'ALL', @@ -457,16 +457,16 @@ export type FieldDeleteResponse = { /** Type of the field */ export enum FieldMetadataType { Boolean = 'BOOLEAN', + Currency = 'CURRENCY', Date = 'DATE', Email = 'EMAIL', Enum = 'ENUM', - Money = 'MONEY', + Link = 'LINK', Number = 'NUMBER', Phone = 'PHONE', Probability = 'PROBABILITY', Relation = 'RELATION', Text = 'TEXT', - Url = 'URL', Uuid = 'UUID' } @@ -608,7 +608,7 @@ export type Person = { export type Pipeline = { __typename?: 'Pipeline'; createdAt: Scalars['DateTime']['output']; - currency: Currency; + currency: CurrencyCode; icon: Scalars['String']['output']; id: Scalars['ID']['output']; name: Scalars['String']['output']; diff --git a/front/src/generated/graphql.tsx b/front/src/generated/graphql.tsx index 2098c8b44..7c602aab1 100644 --- a/front/src/generated/graphql.tsx +++ b/front/src/generated/graphql.tsx @@ -981,7 +981,7 @@ export type CreateRefreshTokenInput = { expiresAt: Scalars['DateTime']; }; -export enum Currency { +export enum CurrencyCode { Aed = 'AED', Afn = 'AFN', All = 'ALL', @@ -1206,11 +1206,11 @@ export type EnumColorSchemeFilter = { notIn?: InputMaybe>; }; -export type EnumCurrencyFilter = { - equals?: InputMaybe; - in?: InputMaybe>; - not?: InputMaybe; - notIn?: InputMaybe>; +export type EnumCurrencyCodeFilter = { + equals?: InputMaybe; + in?: InputMaybe>; + not?: InputMaybe; + notIn?: InputMaybe>; }; export type EnumPipelineProgressableTypeFilter = { @@ -1332,16 +1332,16 @@ export type FieldDeleteResponse = { /** Type of the field */ export enum FieldMetadataType { Boolean = 'BOOLEAN', + Currency = 'CURRENCY', Date = 'DATE', Email = 'EMAIL', Enum = 'ENUM', - Money = 'MONEY', + Link = 'LINK', Number = 'NUMBER', Phone = 'PHONE', Probability = 'PROBABILITY', Relation = 'RELATION', Text = 'TEXT', - Url = 'URL', Uuid = 'UUID' } @@ -1770,11 +1770,11 @@ export type NestedEnumColorSchemeFilter = { notIn?: InputMaybe>; }; -export type NestedEnumCurrencyFilter = { - equals?: InputMaybe; - in?: InputMaybe>; - not?: InputMaybe; - notIn?: InputMaybe>; +export type NestedEnumCurrencyCodeFilter = { + equals?: InputMaybe; + in?: InputMaybe>; + not?: InputMaybe; + notIn?: InputMaybe>; }; export type NestedEnumPipelineProgressableTypeFilter = { @@ -2093,7 +2093,7 @@ export type PersonWhereUniqueInput = { export type Pipeline = { __typename?: 'Pipeline'; createdAt: Scalars['DateTime']; - currency: Currency; + currency: CurrencyCode; icon: Scalars['String']; id: Scalars['ID']; name: Scalars['String']; @@ -2442,7 +2442,7 @@ export type PipelineWhereInput = { NOT?: InputMaybe>; OR?: InputMaybe>; createdAt?: InputMaybe; - currency?: InputMaybe; + currency?: InputMaybe; icon?: InputMaybe; id?: InputMaybe; name?: InputMaybe; diff --git a/front/src/modules/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery.ts b/front/src/modules/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery.ts index be5970f70..66f17e51b 100644 --- a/front/src/modules/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery.ts +++ b/front/src/modules/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery.ts @@ -6,7 +6,14 @@ import { FieldMetadataItem } from '../types/FieldMetadataItem'; export const useMapFieldMetadataToGraphQLQuery = () => { const { objectMetadataItems } = useFindManyObjectMetadataItems(); - const mapFieldMetadataToGraphQLQuery = (field: FieldMetadataItem): any => { + const mapFieldMetadataToGraphQLQuery = ( + field: FieldMetadataItem, + maxDepthForRelations: number = 1, + ): any => { + if (maxDepthForRelations <= 0) { + return ''; + } + // TODO: parse const fieldType = field.type as FieldType; @@ -22,11 +29,6 @@ export const useMapFieldMetadataToGraphQLQuery = () => { ] as FieldType[] ).includes(fieldType); - const fieldIsURL = fieldType === 'URL' || fieldType === 'URL_V2'; - - const fieldIsMoneyAmount = - fieldType === 'MONEY' || fieldType === 'MONEY_AMOUNT_V2'; - if (fieldIsSimpleValue) { return field.name; } else if ( @@ -44,7 +46,9 @@ export const useMapFieldMetadataToGraphQLQuery = () => { id ${(relationMetadataItem?.fields ?? []) .filter((field) => field.type !== 'RELATION') - .map((field) => field.name) + .map((field) => + mapFieldMetadataToGraphQLQuery(field, maxDepthForRelations - 1), + ) .join('\n')} }`; } else if ( @@ -64,25 +68,27 @@ export const useMapFieldMetadataToGraphQLQuery = () => { id ${(relationMetadataItem?.fields ?? []) .filter((field) => field.type !== 'RELATION') - .map((field) => field.name) + .map((field) => + mapFieldMetadataToGraphQLQuery(field, maxDepthForRelations - 1), + ) .join('\n')} } } }`; - } else if (fieldIsURL) { + } else if (fieldType === 'LINK') { return ` ${field.name} { - text - link + label + url } `; - } else if (fieldIsMoneyAmount) { + } else if (fieldType === 'CURRENCY') { return ` ${field.name} { - amount - currency + amountMicros + currencyCode } `; } diff --git a/front/src/modules/object-metadata/utils/parseFieldType.ts b/front/src/modules/object-metadata/utils/parseFieldType.ts index 3015d4245..f4edcf8d4 100644 --- a/front/src/modules/object-metadata/utils/parseFieldType.ts +++ b/front/src/modules/object-metadata/utils/parseFieldType.ts @@ -2,12 +2,12 @@ import { FieldType } from '@/ui/object/field/types/FieldType'; import { FieldMetadataType } from '~/generated-metadata/graphql'; export const parseFieldType = (fieldType: FieldMetadataType): FieldType => { - if (fieldType === FieldMetadataType.Url) { - return 'URL_V2'; + if (fieldType === FieldMetadataType.Link) { + return 'LINK'; } - if (fieldType === FieldMetadataType.Money) { - return 'MONEY_AMOUNT_V2'; + if (fieldType === FieldMetadataType.Currency) { + return 'CURRENCY'; } return fieldType as FieldType; diff --git a/front/src/modules/object-record/hooks/useCreateOneObjectRecord.ts b/front/src/modules/object-record/hooks/useCreateOneObjectRecord.ts index 77fd79c69..d52fac0ca 100644 --- a/front/src/modules/object-record/hooks/useCreateOneObjectRecord.ts +++ b/front/src/modules/object-record/hooks/useCreateOneObjectRecord.ts @@ -4,11 +4,14 @@ import { v4 } from 'uuid'; import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect'; import { useFindOneObjectMetadataItem } from '@/object-metadata/hooks/useFindOneObjectMetadataItem'; import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier'; -import { Currency, FieldMetadataType } from '~/generated-metadata/graphql'; +import { CurrencyCode, FieldMetadataType } from '~/generated-metadata/graphql'; import { capitalize } from '~/utils/string/capitalize'; const defaultFieldValues: Record = { - [FieldMetadataType.Money]: { amount: null, currency: Currency.Usd }, + [FieldMetadataType.Currency]: { + amountMicros: null, + currencyCode: CurrencyCode.Usd, + }, [FieldMetadataType.Boolean]: false, [FieldMetadataType.Date]: null, [FieldMetadataType.Email]: '', @@ -18,7 +21,7 @@ const defaultFieldValues: Record = { [FieldMetadataType.Relation]: null, [FieldMetadataType.Phone]: '', [FieldMetadataType.Text]: '', - [FieldMetadataType.Url]: { link: '', text: '' }, + [FieldMetadataType.Link]: { url: '', label: '' }, [FieldMetadataType.Uuid]: '', }; diff --git a/front/src/modules/settings/data-model/components/__stories__/SettingsObjectFieldPreview.stories.tsx b/front/src/modules/settings/data-model/components/__stories__/SettingsObjectFieldPreview.stories.tsx index 76b4d7bc5..adad8371e 100644 --- a/front/src/modules/settings/data-model/components/__stories__/SettingsObjectFieldPreview.stories.tsx +++ b/front/src/modules/settings/data-model/components/__stories__/SettingsObjectFieldPreview.stories.tsx @@ -38,7 +38,7 @@ export const Currency: Story = { args: { fieldIconKey: 'IconCurrencyDollar', fieldLabel: 'Amount', - fieldType: FieldMetadataType.Money, + fieldType: FieldMetadataType.Currency, }, }; @@ -61,7 +61,7 @@ export const Link: Story = { args: { fieldIconKey: 'IconWorldWww', fieldLabel: 'Website', - fieldType: FieldMetadataType.Url, + fieldType: FieldMetadataType.Link, }, }; diff --git a/front/src/modules/settings/data-model/constants/dataTypes.ts b/front/src/modules/settings/data-model/constants/dataTypes.ts index a36f33fb4..0bbd8ae06 100644 --- a/front/src/modules/settings/data-model/constants/dataTypes.ts +++ b/front/src/modules/settings/data-model/constants/dataTypes.ts @@ -11,7 +11,7 @@ import { IconTextSize, } from '@/ui/display/icon'; import { IconComponent } from '@/ui/display/icon/types/IconComponent'; -import { Currency, FieldMetadataType } from '~/generated-metadata/graphql'; +import { CurrencyCode, FieldMetadataType } from '~/generated-metadata/graphql'; const defaultDateValue = new Date(); defaultDateValue.setFullYear(defaultDateValue.getFullYear() + 2); @@ -36,10 +36,10 @@ export const dataTypes: Record< Icon: IconNumbers, defaultValue: 2000, }, - [FieldMetadataType.Url]: { + [FieldMetadataType.Link]: { label: 'Link', Icon: IconLink, - defaultValue: { link: 'www.twenty.com', text: '' }, + defaultValue: { url: 'www.twenty.com', label: '' }, }, [FieldMetadataType.Boolean]: { label: 'True/False', @@ -51,10 +51,10 @@ export const dataTypes: Record< Icon: IconCalendarEvent, defaultValue: defaultDateValue.toISOString(), }, - [FieldMetadataType.Money]: { + [FieldMetadataType.Currency]: { label: 'Currency', Icon: IconCoins, - defaultValue: { amount: 2000, currency: Currency.Usd }, + defaultValue: { amount: 2000, currency: CurrencyCode.Usd }, }, [FieldMetadataType.Relation]: { label: 'Relation', Icon: IconPlug }, [FieldMetadataType.Email]: { label: 'Email', Icon: IconMail }, diff --git a/front/src/modules/ui/object/field/components/FieldDisplay.tsx b/front/src/modules/ui/object/field/components/FieldDisplay.tsx index 9c0d3b934..e912566cb 100644 --- a/front/src/modules/ui/object/field/components/FieldDisplay.tsx +++ b/front/src/modules/ui/object/field/components/FieldDisplay.tsx @@ -6,30 +6,30 @@ import { isFieldUuid } from '@/ui/object/field/types/guards/isFieldUuid'; import { FieldContext } from '../contexts/FieldContext'; import { ChipFieldDisplay } from '../meta-types/display/components/ChipFieldDisplay'; +import { CurrencyFieldDisplay } from '../meta-types/display/components/CurrencyFieldDisplay'; import { DateFieldDisplay } from '../meta-types/display/components/DateFieldDisplay'; import { DoubleTextChipFieldDisplay } from '../meta-types/display/components/DoubleTextChipFieldDisplay'; import { DoubleTextFieldDisplay } from '../meta-types/display/components/DoubleTextFieldDisplay'; import { EmailFieldDisplay } from '../meta-types/display/components/EmailFieldDisplay'; -import { MoneyAmountV2FieldDisplay } from '../meta-types/display/components/MoneyAmountV2FieldDisplay'; +import { LinkFieldDisplay } from '../meta-types/display/components/LinkFieldDisplay'; import { MoneyFieldDisplay } from '../meta-types/display/components/MoneyFieldDisplay'; import { NumberFieldDisplay } from '../meta-types/display/components/NumberFieldDisplay'; import { PhoneFieldDisplay } from '../meta-types/display/components/PhoneFieldDisplay'; import { TextFieldDisplay } from '../meta-types/display/components/TextFieldDisplay'; import { URLFieldDisplay } from '../meta-types/display/components/URLFieldDisplay'; -import { URLV2FieldDisplay } from '../meta-types/display/components/URLV2FieldDisplay'; import { isFieldChip } from '../types/guards/isFieldChip'; +import { isFieldCurrency } from '../types/guards/isFieldCurrency'; import { isFieldDate } from '../types/guards/isFieldDate'; import { isFieldDoubleText } from '../types/guards/isFieldDoubleText'; import { isFieldDoubleTextChip } from '../types/guards/isFieldDoubleTextChip'; import { isFieldEmail } from '../types/guards/isFieldEmail'; +import { isFieldLink } from '../types/guards/isFieldLink'; import { isFieldMoney } from '../types/guards/isFieldMoney'; -import { isFieldMoneyAmountV2 } from '../types/guards/isFieldMoneyAmountV2'; import { isFieldNumber } from '../types/guards/isFieldNumber'; import { isFieldPhone } from '../types/guards/isFieldPhone'; import { isFieldRelation } from '../types/guards/isFieldRelation'; import { isFieldText } from '../types/guards/isFieldText'; import { isFieldURL } from '../types/guards/isFieldURL'; -import { isFieldURLV2 } from '../types/guards/isFieldURLV2'; export const FieldDisplay = () => { const { fieldDefinition } = useContext(FieldContext); @@ -52,10 +52,10 @@ export const FieldDisplay = () => { ) : isFieldURL(fieldDefinition) ? ( - ) : isFieldURLV2(fieldDefinition) ? ( - - ) : isFieldMoneyAmountV2(fieldDefinition) ? ( - + ) : isFieldLink(fieldDefinition) ? ( + + ) : isFieldCurrency(fieldDefinition) ? ( + ) : isFieldPhone(fieldDefinition) ? ( ) : isFieldChip(fieldDefinition) ? ( diff --git a/front/src/modules/ui/object/field/components/FieldInput.tsx b/front/src/modules/ui/object/field/components/FieldInput.tsx index 4dbaa933f..ca7f2aca8 100644 --- a/front/src/modules/ui/object/field/components/FieldInput.tsx +++ b/front/src/modules/ui/object/field/components/FieldInput.tsx @@ -5,11 +5,12 @@ import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope' import { FieldContext } from '../contexts/FieldContext'; import { BooleanFieldInput } from '../meta-types/input/components/BooleanFieldInput'; import { ChipFieldInput } from '../meta-types/input/components/ChipFieldInput'; +import { CurrencyFieldInput } from '../meta-types/input/components/CurrencyFieldInput'; import { DateFieldInput } from '../meta-types/input/components/DateFieldInput'; import { DoubleTextChipFieldInput } from '../meta-types/input/components/DoubleTextChipFieldInput'; import { DoubleTextFieldInput } from '../meta-types/input/components/DoubleTextFieldInput'; import { EmailFieldInput } from '../meta-types/input/components/EmailFieldInput'; -import { MoneyAmountV2FieldInput } from '../meta-types/input/components/MoneyAmountV2FieldInput'; +import { LinkFieldInput } from '../meta-types/input/components/LinkFieldInput'; import { MoneyFieldInput } from '../meta-types/input/components/MoneyFieldInput'; import { NumberFieldInput } from '../meta-types/input/components/NumberFieldInput'; import { PhoneFieldInput } from '../meta-types/input/components/PhoneFieldInput'; @@ -17,23 +18,22 @@ import { ProbabilityFieldInput } from '../meta-types/input/components/Probabilit import { RelationFieldInput } from '../meta-types/input/components/RelationFieldInput'; import { TextFieldInput } from '../meta-types/input/components/TextFieldInput'; import { URLFieldInput } from '../meta-types/input/components/URLFieldInput'; -import { URLV2FieldInput } from '../meta-types/input/components/URLV2FieldInput'; import { FieldInputEvent } from '../types/FieldInputEvent'; import { isFieldBoolean } from '../types/guards/isFieldBoolean'; import { isFieldChip } from '../types/guards/isFieldChip'; +import { isFieldCurrency } from '../types/guards/isFieldCurrency'; import { isFieldDate } from '../types/guards/isFieldDate'; import { isFieldDoubleText } from '../types/guards/isFieldDoubleText'; import { isFieldDoubleTextChip } from '../types/guards/isFieldDoubleTextChip'; import { isFieldEmail } from '../types/guards/isFieldEmail'; +import { isFieldLink } from '../types/guards/isFieldLink'; import { isFieldMoney } from '../types/guards/isFieldMoney'; -import { isFieldMoneyAmountV2 } from '../types/guards/isFieldMoneyAmountV2'; import { isFieldNumber } from '../types/guards/isFieldNumber'; import { isFieldPhone } from '../types/guards/isFieldPhone'; import { isFieldProbability } from '../types/guards/isFieldProbability'; import { isFieldRelation } from '../types/guards/isFieldRelation'; import { isFieldText } from '../types/guards/isFieldText'; import { isFieldURL } from '../types/guards/isFieldURL'; -import { isFieldURLV2 } from '../types/guards/isFieldURLV2'; type FieldInputProps = { onSubmit?: FieldInputEvent; @@ -102,16 +102,16 @@ export const FieldInput = ({ onTab={onTab} onShiftTab={onShiftTab} /> - ) : isFieldURLV2(fieldDefinition) ? ( - - ) : isFieldMoneyAmountV2(fieldDefinition) ? ( - { @@ -73,8 +73,8 @@ export const usePersistField = () => { const fieldIsURL = isFieldURL(fieldDefinition) && isFieldURLValue(valueToPersist); - const fieldIsURLV2 = - isFieldURLV2(fieldDefinition) && isFieldURLV2Value(valueToPersist); + const fieldIsLink = + isFieldLink(fieldDefinition) && isFieldLinkValue(valueToPersist); const fieldIsBoolean = isFieldBoolean(fieldDefinition) && @@ -90,9 +90,9 @@ export const usePersistField = () => { const fieldIsMoney = isFieldMoney(fieldDefinition) && isFieldMoneyValue(valueToPersist); - const fieldIsMoneyAmountV2 = - isFieldMoneyAmountV2(fieldDefinition) && - isFieldMoneyAmountV2Value(valueToPersist); + const fieldIsCurrency = + isFieldCurrency(fieldDefinition) && + isFieldCurrencyValue(valueToPersist); const fieldIsPhone = isFieldPhone(fieldDefinition) && isFieldPhoneValue(valueToPersist); @@ -169,8 +169,8 @@ export const usePersistField = () => { fieldIsMoney || fieldIsDate || fieldIsPhone || - fieldIsURLV2 || - fieldIsMoneyAmountV2 + fieldIsLink || + fieldIsCurrency ) { const fieldName = fieldDefinition.metadata.fieldName; diff --git a/front/src/modules/ui/object/field/meta-types/display/components/CurrencyFieldDisplay.tsx b/front/src/modules/ui/object/field/meta-types/display/components/CurrencyFieldDisplay.tsx new file mode 100644 index 000000000..f649072e2 --- /dev/null +++ b/front/src/modules/ui/object/field/meta-types/display/components/CurrencyFieldDisplay.tsx @@ -0,0 +1,8 @@ +import { useCurrencyField } from '../../hooks/useCurrencyField'; +import { CurrencyDisplay } from '../content-display/components/CurrencyDisplay'; + +export const CurrencyFieldDisplay = () => { + const { fieldValue } = useCurrencyField(); + + return ; +}; diff --git a/front/src/modules/ui/object/field/meta-types/display/components/LinkFieldDisplay.tsx b/front/src/modules/ui/object/field/meta-types/display/components/LinkFieldDisplay.tsx new file mode 100644 index 000000000..7ff174790 --- /dev/null +++ b/front/src/modules/ui/object/field/meta-types/display/components/LinkFieldDisplay.tsx @@ -0,0 +1,8 @@ +import { useLinkField } from '../../hooks/useLinkField'; +import { LinkDisplay } from '../content-display/components/LinkDisplay'; + +export const LinkFieldDisplay = () => { + const { fieldValue } = useLinkField(); + + return ; +}; diff --git a/front/src/modules/ui/object/field/meta-types/display/components/MoneyAmountV2FieldDisplay.tsx b/front/src/modules/ui/object/field/meta-types/display/components/MoneyAmountV2FieldDisplay.tsx deleted file mode 100644 index f0ab589ba..000000000 --- a/front/src/modules/ui/object/field/meta-types/display/components/MoneyAmountV2FieldDisplay.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { useMoneyAmountV2Field } from '../../hooks/useMoneyAmountV2Field'; -import { MoneyAmountV2Display } from '../content-display/components/MoneyAmountV2Display'; - -export const MoneyAmountV2FieldDisplay = () => { - const { fieldValue } = useMoneyAmountV2Field(); - - return ; -}; diff --git a/front/src/modules/ui/object/field/meta-types/display/components/URLV2FieldDisplay.tsx b/front/src/modules/ui/object/field/meta-types/display/components/URLV2FieldDisplay.tsx deleted file mode 100644 index 1fefd28d5..000000000 --- a/front/src/modules/ui/object/field/meta-types/display/components/URLV2FieldDisplay.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { useURLV2Field } from '../../hooks/useURLV2Field'; -import { URLV2Display } from '../content-display/components/URLDisplayV2'; - -export const URLV2FieldDisplay = () => { - const { fieldValue } = useURLV2Field(); - - return ; -}; diff --git a/front/src/modules/ui/object/field/meta-types/display/content-display/components/CurrencyDisplay.tsx b/front/src/modules/ui/object/field/meta-types/display/content-display/components/CurrencyDisplay.tsx new file mode 100644 index 000000000..c0cb53cc3 --- /dev/null +++ b/front/src/modules/ui/object/field/meta-types/display/content-display/components/CurrencyDisplay.tsx @@ -0,0 +1,18 @@ +import { FieldCurrencyValue } from '@/ui/object/field/types/FieldMetadata'; +import { convertCurrencyMicrosToCurrency } from '~/utils/convert-currency-amount'; + +import { EllipsisDisplay } from './EllipsisDisplay'; + +type CurrencyDisplayProps = { + value?: FieldCurrencyValue; +}; + +// TODO: convert currencyCode to currency symbol +export const CurrencyDisplay = ({ value }: CurrencyDisplayProps) => { + return ( + + {convertCurrencyMicrosToCurrency(value?.amountMicros)}{' '} + {value?.currencyCode} + + ); +}; diff --git a/front/src/modules/ui/object/field/meta-types/display/content-display/components/URLDisplayV2.tsx b/front/src/modules/ui/object/field/meta-types/display/content-display/components/LinkDisplay.tsx similarity index 78% rename from front/src/modules/ui/object/field/meta-types/display/content-display/components/URLDisplayV2.tsx rename to front/src/modules/ui/object/field/meta-types/display/content-display/components/LinkDisplay.tsx index 3820638ba..c2f1bc7f2 100644 --- a/front/src/modules/ui/object/field/meta-types/display/content-display/components/URLDisplayV2.tsx +++ b/front/src/modules/ui/object/field/meta-types/display/content-display/components/LinkDisplay.tsx @@ -6,7 +6,7 @@ import { LinkType, SocialLink, } from '@/ui/navigation/link/components/SocialLink'; -import { FieldURLV2Value } from '@/ui/object/field/types/FieldMetadata'; +import { FieldLinkValue } from '@/ui/object/field/types/FieldMetadata'; import { EllipsisDisplay } from './EllipsisDisplay'; @@ -20,8 +20,8 @@ const StyledRawLink = styled(RoundedLink)` } `; -type URLV2DisplayProps = { - value?: FieldURLV2Value; +type LinkDisplayProps = { + value?: FieldLinkValue; }; const checkUrlType = (url: string) => { @@ -39,18 +39,18 @@ const checkUrlType = (url: string) => { return LinkType.Url; }; -export const URLV2Display = ({ value }: URLV2DisplayProps) => { +export const LinkDisplay = ({ value }: LinkDisplayProps) => { const handleClick = (event: MouseEvent) => { event.stopPropagation(); }; - const absoluteUrl = value?.link - ? value.link.startsWith('http') - ? value.link - : 'https://' + value.link + const absoluteUrl = value?.url + ? value.url.startsWith('http') + ? value.url + : 'https://' + value.url : ''; - const displayedValue = value?.text || value?.link || ''; + const displayedValue = value?.label || value?.url || ''; const type = checkUrlType(absoluteUrl); diff --git a/front/src/modules/ui/object/field/meta-types/display/content-display/components/MoneyAmountV2Display.tsx b/front/src/modules/ui/object/field/meta-types/display/content-display/components/MoneyAmountV2Display.tsx deleted file mode 100644 index a1ac631ad..000000000 --- a/front/src/modules/ui/object/field/meta-types/display/content-display/components/MoneyAmountV2Display.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { FieldMoneyAmountV2Value } from '@/ui/object/field/types/FieldMetadata'; - -import { EllipsisDisplay } from './EllipsisDisplay'; - -type MoneyAmountV2DisplayProps = { - value?: FieldMoneyAmountV2Value; -}; - -export const MoneyAmountV2Display = ({ value }: MoneyAmountV2DisplayProps) => { - return ( - - {value?.amount} {value?.currency} - - ); -}; diff --git a/front/src/modules/ui/object/field/meta-types/hooks/useMoneyAmountV2Field.ts b/front/src/modules/ui/object/field/meta-types/hooks/useCurrencyField.ts similarity index 54% rename from front/src/modules/ui/object/field/meta-types/hooks/useMoneyAmountV2Field.ts rename to front/src/modules/ui/object/field/meta-types/hooks/useCurrencyField.ts index a1240a982..3bf2f29ae 100644 --- a/front/src/modules/ui/object/field/meta-types/hooks/useMoneyAmountV2Field.ts +++ b/front/src/modules/ui/object/field/meta-types/hooks/useCurrencyField.ts @@ -5,19 +5,19 @@ import { FieldContext } from '../../contexts/FieldContext'; import { useFieldInitialValue } from '../../hooks/useFieldInitialValue'; import { usePersistField } from '../../hooks/usePersistField'; import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector'; -import { FieldMoneyAmountV2Value } from '../../types/FieldMetadata'; +import { FieldCurrencyValue } from '../../types/FieldMetadata'; import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata'; -import { isFieldMoneyAmountV2 } from '../../types/guards/isFieldMoneyAmountV2'; -import { isFieldMoneyAmountV2Value } from '../../types/guards/isFieldMoneyAmountV2Value'; +import { isFieldCurrency } from '../../types/guards/isFieldCurrency'; +import { isFieldCurrencyValue } from '../../types/guards/isFieldCurrencyValue'; -export const useMoneyAmountV2Field = () => { +export const useCurrencyField = () => { const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext); - assertFieldMetadata('MONEY_AMOUNT_V2', isFieldMoneyAmountV2, fieldDefinition); + assertFieldMetadata('CURRENCY', isFieldCurrency, fieldDefinition); const fieldName = fieldDefinition.metadata.fieldName; - const [fieldValue, setFieldValue] = useRecoilState( + const [fieldValue, setFieldValue] = useRecoilState( entityFieldsFamilySelector({ entityId: entityId, fieldName: fieldName, @@ -26,8 +26,8 @@ export const useMoneyAmountV2Field = () => { const persistField = usePersistField(); - const persistMoneyAmountV2Field = (newValue: FieldMoneyAmountV2Value) => { - if (!isFieldMoneyAmountV2Value(newValue)) { + const persistCurrencyField = (newValue: FieldCurrencyValue) => { + if (!isFieldCurrencyValue(newValue)) { return; } @@ -36,11 +36,11 @@ export const useMoneyAmountV2Field = () => { const fieldInitialValue = useFieldInitialValue(); - const initialValue: FieldMoneyAmountV2Value = fieldInitialValue?.isEmpty - ? { amount: 0, currency: '' } + const initialValue: FieldCurrencyValue = fieldInitialValue?.isEmpty + ? { amountMicros: 0, currencyCode: '' } : !isNaN(Number(fieldInitialValue?.value)) - ? { amount: Number(fieldInitialValue?.value), currency: '' } - : { amount: 0, currency: '' } ?? fieldValue; + ? { amountMicros: Number(fieldInitialValue?.value), currencyCode: '' } + : { amountMicros: 0, currencyCode: '' } ?? fieldValue; return { fieldDefinition, @@ -48,6 +48,6 @@ export const useMoneyAmountV2Field = () => { initialValue, setFieldValue, hotkeyScope, - persistMoneyAmountV2Field, + persistCurrencyField, }; }; diff --git a/front/src/modules/ui/object/field/meta-types/hooks/useURLV2Field.ts b/front/src/modules/ui/object/field/meta-types/hooks/useLinkField.ts similarity index 61% rename from front/src/modules/ui/object/field/meta-types/hooks/useURLV2Field.ts rename to front/src/modules/ui/object/field/meta-types/hooks/useLinkField.ts index 6ed7354b6..a12e02d4a 100644 --- a/front/src/modules/ui/object/field/meta-types/hooks/useURLV2Field.ts +++ b/front/src/modules/ui/object/field/meta-types/hooks/useLinkField.ts @@ -5,19 +5,19 @@ import { FieldContext } from '../../contexts/FieldContext'; import { useFieldInitialValue } from '../../hooks/useFieldInitialValue'; import { usePersistField } from '../../hooks/usePersistField'; import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector'; -import { FieldURLV2Value } from '../../types/FieldMetadata'; +import { FieldLinkValue } from '../../types/FieldMetadata'; import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata'; -import { isFieldURLV2 } from '../../types/guards/isFieldURLV2'; -import { isFieldURLV2Value } from '../../types/guards/isFieldURLV2Value'; +import { isFieldLink } from '../../types/guards/isFieldLink'; +import { isFieldLinkValue } from '../../types/guards/isFieldLinkValue'; -export const useURLV2Field = () => { +export const useLinkField = () => { const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext); - assertFieldMetadata('URL_V2', isFieldURLV2, fieldDefinition); + assertFieldMetadata('LINK', isFieldLink, fieldDefinition); const fieldName = fieldDefinition.metadata.fieldName; - const [fieldValue, setFieldValue] = useRecoilState( + const [fieldValue, setFieldValue] = useRecoilState( entityFieldsFamilySelector({ entityId: entityId, fieldName: fieldName, @@ -26,16 +26,16 @@ export const useURLV2Field = () => { const fieldInitialValue = useFieldInitialValue(); - const initialValue: FieldURLV2Value = fieldInitialValue?.isEmpty - ? { link: '', text: '' } + const initialValue: FieldLinkValue = fieldInitialValue?.isEmpty + ? { url: '', label: '' } : fieldInitialValue?.value - ? { link: fieldInitialValue.value, text: '' } + ? { url: fieldInitialValue.value, label: '' } : fieldValue; const persistField = usePersistField(); - const persistURLField = (newValue: FieldURLV2Value) => { - if (!isFieldURLV2Value(newValue)) { + const persistLinkField = (newValue: FieldLinkValue) => { + if (!isFieldLinkValue(newValue)) { return; } @@ -48,6 +48,6 @@ export const useURLV2Field = () => { initialValue, setFieldValue, hotkeyScope, - persistURLField, + persistLinkField, }; }; diff --git a/front/src/modules/ui/object/field/meta-types/input/components/CurrencyFieldInput.tsx b/front/src/modules/ui/object/field/meta-types/input/components/CurrencyFieldInput.tsx new file mode 100644 index 000000000..dfe3bb290 --- /dev/null +++ b/front/src/modules/ui/object/field/meta-types/input/components/CurrencyFieldInput.tsx @@ -0,0 +1,94 @@ +import { TextInput } from '@/ui/object/field/meta-types/input/components/internal/TextInput'; +import { convertCurrencyToCurrencyMicros } from '~/utils/convert-currency-amount'; + +import { useCurrencyField } from '../../hooks/useCurrencyField'; + +import { FieldInputOverlay } from './internal/FieldInputOverlay'; +import { FieldInputEvent } from './DateFieldInput'; + +export type CurrencyFieldInputProps = { + onClickOutside?: FieldInputEvent; + onEnter?: FieldInputEvent; + onEscape?: FieldInputEvent; + onTab?: FieldInputEvent; + onShiftTab?: FieldInputEvent; +}; + +export const CurrencyFieldInput = ({ + onEnter, + onEscape, + onClickOutside, + onTab, + onShiftTab, +}: CurrencyFieldInputProps) => { + const { hotkeyScope, initialValue, persistCurrencyField } = + useCurrencyField(); + + const handleEnter = (newValue: string) => { + onEnter?.(() => + persistCurrencyField({ + amountMicros: + convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0, + currencyCode: initialValue.currencyCode, + }), + ); + }; + + const handleEscape = (newValue: string) => { + onEscape?.(() => + persistCurrencyField({ + amountMicros: + convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0, + currencyCode: initialValue.currencyCode, + }), + ); + }; + + const handleClickOutside = ( + event: MouseEvent | TouchEvent, + newValue: string, + ) => { + onClickOutside?.(() => + persistCurrencyField({ + amountMicros: + convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0, + currencyCode: initialValue.currencyCode, + }), + ); + }; + + const handleTab = (newValue: string) => { + onTab?.(() => + persistCurrencyField({ + amountMicros: + convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0, + currencyCode: initialValue.currencyCode, + }), + ); + }; + + const handleShiftTab = (newValue: string) => { + onShiftTab?.(() => + persistCurrencyField({ + amountMicros: + convertCurrencyToCurrencyMicros(parseFloat(newValue)) ?? 0, + currencyCode: initialValue.currencyCode, + }), + ); + }; + + return ( + + + + ); +}; diff --git a/front/src/modules/ui/object/field/meta-types/input/components/URLV2FieldInput.tsx b/front/src/modules/ui/object/field/meta-types/input/components/LinkFieldInput.tsx similarity index 62% rename from front/src/modules/ui/object/field/meta-types/input/components/URLV2FieldInput.tsx rename to front/src/modules/ui/object/field/meta-types/input/components/LinkFieldInput.tsx index 0fc5e254b..5425ea716 100644 --- a/front/src/modules/ui/object/field/meta-types/input/components/URLV2FieldInput.tsx +++ b/front/src/modules/ui/object/field/meta-types/input/components/LinkFieldInput.tsx @@ -1,11 +1,11 @@ import { FieldDoubleText } from '../../../types/FieldDoubleText'; -import { useURLV2Field } from '../../hooks/useURLV2Field'; +import { useLinkField } from '../../hooks/useLinkField'; import { DoubleTextInput } from './internal/DoubleTextInput'; import { FieldInputOverlay } from './internal/FieldInputOverlay'; import { FieldInputEvent } from './DateFieldInput'; -export type URLV2FieldInputProps = { +export type LinkFieldInputProps = { onClickOutside?: FieldInputEvent; onEnter?: FieldInputEvent; onEscape?: FieldInputEvent; @@ -13,29 +13,29 @@ export type URLV2FieldInputProps = { onShiftTab?: FieldInputEvent; }; -export const URLV2FieldInput = ({ +export const LinkFieldInput = ({ onEnter, onEscape, onClickOutside, onTab, onShiftTab, -}: URLV2FieldInputProps) => { - const { initialValue, hotkeyScope, persistURLField } = useURLV2Field(); +}: LinkFieldInputProps) => { + const { initialValue, hotkeyScope, persistLinkField } = useLinkField(); const handleEnter = (newURL: FieldDoubleText) => { onEnter?.(() => - persistURLField({ - link: newURL.firstValue, - text: newURL.secondValue, + persistLinkField({ + url: newURL.firstValue, + label: newURL.secondValue, }), ); }; const handleEscape = (newURL: FieldDoubleText) => { onEscape?.(() => - persistURLField({ - link: newURL.firstValue, - text: newURL.secondValue, + persistLinkField({ + url: newURL.firstValue, + label: newURL.secondValue, }), ); }; @@ -45,27 +45,27 @@ export const URLV2FieldInput = ({ newURL: FieldDoubleText, ) => { onClickOutside?.(() => - persistURLField({ - link: newURL.firstValue, - text: newURL.secondValue, + persistLinkField({ + url: newURL.firstValue, + label: newURL.secondValue, }), ); }; const handleTab = (newURL: FieldDoubleText) => { onTab?.(() => - persistURLField({ - link: newURL.firstValue, - text: newURL.secondValue, + persistLinkField({ + url: newURL.firstValue, + label: newURL.secondValue, }), ); }; const handleShiftTab = (newURL: FieldDoubleText) => { onShiftTab?.(() => - persistURLField({ - link: newURL.firstValue, - text: newURL.secondValue, + persistLinkField({ + url: newURL.firstValue, + label: newURL.secondValue, }), ); }; @@ -73,9 +73,9 @@ export const URLV2FieldInput = ({ return ( { - const { hotkeyScope, initialValue } = useMoneyAmountV2Field(); - - const persistField = usePersistField(); - - const handleEnter = (newDoubleText: FieldDoubleText) => { - onEnter?.(() => - persistField({ - amount: parseFloat(newDoubleText.firstValue), - currency: newDoubleText.secondValue, - }), - ); - }; - - const handleEscape = (newDoubleText: FieldDoubleText) => { - onEscape?.(() => - persistField({ - amount: parseFloat(newDoubleText.firstValue), - currency: newDoubleText.secondValue, - }), - ); - }; - - const handleClickOutside = ( - event: MouseEvent | TouchEvent, - newDoubleText: FieldDoubleText, - ) => { - onClickOutside?.(() => - persistField({ - amount: parseFloat(newDoubleText.firstValue), - currency: newDoubleText.secondValue, - }), - ); - }; - - const handleTab = (newDoubleText: FieldDoubleText) => { - onTab?.(() => - persistField({ - amount: parseFloat(newDoubleText.firstValue), - currency: newDoubleText.secondValue, - }), - ); - }; - - const handleShiftTab = (newDoubleText: FieldDoubleText) => { - onShiftTab?.(() => - persistField({ - amount: parseFloat(newDoubleText.firstValue), - currency: newDoubleText.secondValue, - }), - ); - }; - - return ( - - - - ); -}; diff --git a/front/src/modules/ui/object/field/states/selectors/isEntityFieldEmptyFamilySelector.ts b/front/src/modules/ui/object/field/states/selectors/isEntityFieldEmptyFamilySelector.ts index 3f959634d..376208d63 100644 --- a/front/src/modules/ui/object/field/states/selectors/isEntityFieldEmptyFamilySelector.ts +++ b/front/src/modules/ui/object/field/states/selectors/isEntityFieldEmptyFamilySelector.ts @@ -7,12 +7,14 @@ import { FieldDefinition } from '../../types/FieldDefinition'; import { FieldMetadata } from '../../types/FieldMetadata'; import { isFieldBoolean } from '../../types/guards/isFieldBoolean'; import { isFieldChip } from '../../types/guards/isFieldChip'; +import { isFieldCurrency } from '../../types/guards/isFieldCurrency'; +import { isFieldCurrencyValue } from '../../types/guards/isFieldCurrencyValue'; import { isFieldDate } from '../../types/guards/isFieldDate'; import { isFieldDoubleTextChip } from '../../types/guards/isFieldDoubleTextChip'; import { isFieldEmail } from '../../types/guards/isFieldEmail'; +import { isFieldLink } from '../../types/guards/isFieldLink'; +import { isFieldLinkValue } from '../../types/guards/isFieldLinkValue'; import { isFieldMoney } from '../../types/guards/isFieldMoney'; -import { isFieldMoneyAmountV2 } from '../../types/guards/isFieldMoneyAmountV2'; -import { isFieldMoneyAmountV2Value } from '../../types/guards/isFieldMoneyAmountV2Value'; import { isFieldNumber } from '../../types/guards/isFieldNumber'; import { isFieldPhone } from '../../types/guards/isFieldPhone'; import { isFieldProbability } from '../../types/guards/isFieldProbability'; @@ -20,8 +22,6 @@ import { isFieldRelation } from '../../types/guards/isFieldRelation'; import { isFieldRelationValue } from '../../types/guards/isFieldRelationValue'; import { isFieldText } from '../../types/guards/isFieldText'; import { isFieldURL } from '../../types/guards/isFieldURL'; -import { isFieldURLV2 } from '../../types/guards/isFieldURLV2'; -import { isFieldURLV2Value } from '../../types/guards/isFieldURLV2Value'; import { entityFieldsFamilyState } from '../entityFieldsFamilyState'; const isValueEmpty = (value: unknown) => !assertNotNull(value) || value === ''; @@ -98,21 +98,21 @@ export const isEntityFieldEmptyFamilySelector = selectorFamily({ ); } - if (isFieldMoneyAmountV2(fieldDefinition)) { + if (isFieldCurrency(fieldDefinition)) { const fieldName = fieldDefinition.metadata.fieldName; const fieldValue = get(entityFieldsFamilyState(entityId))?.[fieldName]; return ( - !isFieldMoneyAmountV2Value(fieldValue) || - isValueEmpty(fieldValue?.amount) + !isFieldCurrencyValue(fieldValue) || + isValueEmpty(fieldValue?.amountMicros) ); } - if (isFieldURLV2(fieldDefinition)) { + if (isFieldLink(fieldDefinition)) { const fieldName = fieldDefinition.metadata.fieldName; const fieldValue = get(entityFieldsFamilyState(entityId))?.[fieldName]; - return !isFieldURLV2Value(fieldValue) || isValueEmpty(fieldValue?.link); + return !isFieldLinkValue(fieldValue) || isValueEmpty(fieldValue?.url); } throw new Error( diff --git a/front/src/modules/ui/object/field/types/FieldMetadata.ts b/front/src/modules/ui/object/field/types/FieldMetadata.ts index d8e39a259..3c67acc3c 100644 --- a/front/src/modules/ui/object/field/types/FieldMetadata.ts +++ b/front/src/modules/ui/object/field/types/FieldMetadata.ts @@ -21,7 +21,7 @@ export type FieldURLMetadata = { fieldName: string; }; -export type FieldURLV2Metadata = { +export type FieldLinkMetadata = { placeHolder: string; fieldName: string; }; @@ -42,7 +42,7 @@ export type FieldMoneyMetadata = { isPositive?: boolean; }; -export type FieldMoneyAmountV2Metadata = { +export type FieldCurrencyMetadata = { fieldName: string; placeHolder: string; isPositive?: boolean; @@ -91,22 +91,22 @@ export type FieldBooleanMetadata = { }; export type FieldMetadata = - | FieldUuidMetadata - | FieldTextMetadata - | FieldRelationMetadata + | FieldBooleanMetadata | FieldChipMetadata + | FieldCurrencyMetadata + | FieldDateMetadata | FieldDoubleTextChipMetadata | FieldDoubleTextMetadata - | FieldPhoneMetadata - | FieldURLMetadata - | FieldURLV2Metadata - | FieldNumberMetadata - | FieldMoneyMetadata - | FieldMoneyAmountV2Metadata | FieldEmailMetadata - | FieldDateMetadata + | FieldLinkMetadata + | FieldMoneyMetadata + | FieldNumberMetadata + | FieldPhoneMetadata | FieldProbabilityMetadata - | FieldBooleanMetadata; + | FieldRelationMetadata + | FieldTextMetadata + | FieldURLMetadata + | FieldUuidMetadata; export type FieldTextValue = string; export type FieldUUidValue = string; @@ -115,10 +115,10 @@ export type FieldChipValue = string; export type FieldDateValue = string | null; export type FieldPhoneValue = string; export type FieldURLValue = string; -export type FieldURLV2Value = { link: string; text: string }; +export type FieldLinkValue = { url: string; label: string }; export type FieldNumberValue = number | null; export type FieldMoneyValue = number | null; -export type FieldMoneyAmountV2Value = { currency: string; amount: number }; +export type FieldCurrencyValue = { currencyCode: string; amountMicros: number }; export type FieldEmailValue = string; export type FieldProbabilityValue = number; diff --git a/front/src/modules/ui/object/field/types/FieldType.ts b/front/src/modules/ui/object/field/types/FieldType.ts index cc42ee693..dcf6534b9 100644 --- a/front/src/modules/ui/object/field/types/FieldType.ts +++ b/front/src/modules/ui/object/field/types/FieldType.ts @@ -11,8 +11,8 @@ export type FieldType = | 'DATE' | 'PHONE' | 'URL' - | 'URL_V2' + | 'LINK' | 'PROBABILITY' - | 'MONEY_AMOUNT_V2' + | 'CURRENCY' | 'MONEY_AMOUNT' | 'MONEY'; diff --git a/front/src/modules/ui/object/field/types/guards/assertFieldMetadata.ts b/front/src/modules/ui/object/field/types/guards/assertFieldMetadata.ts index ff3189c71..e44249265 100644 --- a/front/src/modules/ui/object/field/types/guards/assertFieldMetadata.ts +++ b/front/src/modules/ui/object/field/types/guards/assertFieldMetadata.ts @@ -2,12 +2,13 @@ import { FieldDefinition } from '../FieldDefinition'; import { FieldBooleanMetadata, FieldChipMetadata, + FieldCurrencyMetadata, FieldDateMetadata, FieldDoubleTextChipMetadata, FieldDoubleTextMetadata, FieldEmailMetadata, + FieldLinkMetadata, FieldMetadata, - FieldMoneyAmountV2Metadata, FieldMoneyMetadata, FieldNumberMetadata, FieldPhoneMetadata, @@ -15,45 +16,44 @@ import { FieldRelationMetadata, FieldTextMetadata, FieldURLMetadata, - FieldURLV2Metadata, FieldUuidMetadata, } from '../FieldMetadata'; import { FieldType } from '../FieldType'; type AssertFieldMetadataFunction = < E extends FieldType, - T extends E extends 'TEXT' - ? FieldTextMetadata - : E extends 'UUID' - ? FieldUuidMetadata - : E extends 'RELATION' - ? FieldRelationMetadata + T extends E extends 'BOOLEAN' + ? FieldBooleanMetadata : E extends 'CHIP' ? FieldChipMetadata - : E extends 'DOUBLE_TEXT_CHIP' - ? FieldDoubleTextChipMetadata - : E extends 'DOUBLE_TEXT' - ? FieldDoubleTextMetadata - : E extends 'NUMBER' - ? FieldNumberMetadata - : E extends 'EMAIL' - ? FieldEmailMetadata - : E extends 'BOOLEAN' - ? FieldBooleanMetadata + : E extends 'CURRENCY' + ? FieldCurrencyMetadata : E extends 'DATE' ? FieldDateMetadata - : E extends 'PHONE' - ? FieldPhoneMetadata - : E extends 'URL' - ? FieldURLMetadata - : E extends 'URL_V2' - ? FieldURLV2Metadata - : E extends 'PROBABILITY' - ? FieldProbabilityMetadata + : E extends 'DOUBLE_TEXT' + ? FieldDoubleTextMetadata + : E extends 'DOUBLE_TEXT_CHIP' + ? FieldDoubleTextChipMetadata + : E extends 'EMAIL' + ? FieldEmailMetadata + : E extends 'LINK' + ? FieldLinkMetadata : E extends 'MONEY_AMOUNT' ? FieldMoneyMetadata - : E extends 'MONEY_AMOUNT_V2' - ? FieldMoneyAmountV2Metadata + : E extends 'NUMBER' + ? FieldNumberMetadata + : E extends 'PHONE' + ? FieldPhoneMetadata + : E extends 'PROBABILITY' + ? FieldProbabilityMetadata + : E extends 'RELATION' + ? FieldRelationMetadata + : E extends 'TEXT' + ? FieldTextMetadata + : E extends 'URL' + ? FieldURLMetadata + : E extends 'UUID' + ? FieldUuidMetadata : never, >( fieldType: E, diff --git a/front/src/modules/ui/object/field/types/guards/isFieldCurrency.ts b/front/src/modules/ui/object/field/types/guards/isFieldCurrency.ts new file mode 100644 index 000000000..dbf58bc96 --- /dev/null +++ b/front/src/modules/ui/object/field/types/guards/isFieldCurrency.ts @@ -0,0 +1,6 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldCurrencyMetadata, FieldMetadata } from '../FieldMetadata'; + +export const isFieldCurrency = ( + field: FieldDefinition, +): field is FieldDefinition => field.type === 'CURRENCY'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldCurrencyValue.ts b/front/src/modules/ui/object/field/types/guards/isFieldCurrencyValue.ts new file mode 100644 index 000000000..69378fd6e --- /dev/null +++ b/front/src/modules/ui/object/field/types/guards/isFieldCurrencyValue.ts @@ -0,0 +1,13 @@ +import { z } from 'zod'; + +import { FieldCurrencyValue } from '../FieldMetadata'; + +const currencySchema = z.object({ + currencyCode: z.string(), + amountMicros: z.number(), +}); + +export const isFieldCurrencyValue = ( + fieldValue: unknown, +): fieldValue is FieldCurrencyValue => + currencySchema.safeParse(fieldValue).success; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldLink.ts b/front/src/modules/ui/object/field/types/guards/isFieldLink.ts new file mode 100644 index 000000000..b32c898cb --- /dev/null +++ b/front/src/modules/ui/object/field/types/guards/isFieldLink.ts @@ -0,0 +1,6 @@ +import { FieldDefinition } from '../FieldDefinition'; +import { FieldLinkMetadata, FieldMetadata } from '../FieldMetadata'; + +export const isFieldLink = ( + field: FieldDefinition, +): field is FieldDefinition => field.type === 'LINK'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldLinkValue.ts b/front/src/modules/ui/object/field/types/guards/isFieldLinkValue.ts new file mode 100644 index 000000000..63ef67761 --- /dev/null +++ b/front/src/modules/ui/object/field/types/guards/isFieldLinkValue.ts @@ -0,0 +1,13 @@ +import { z } from 'zod'; + +import { FieldLinkValue } from '../FieldMetadata'; + +const linkSchema = z.object({ + url: z.string(), + label: z.string(), +}); + +// TODO: add zod +export const isFieldLinkValue = ( + fieldValue: unknown, +): fieldValue is FieldLinkValue => linkSchema.safeParse(fieldValue).success; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldMoneyAmountV2.ts b/front/src/modules/ui/object/field/types/guards/isFieldMoneyAmountV2.ts deleted file mode 100644 index b8e40b696..000000000 --- a/front/src/modules/ui/object/field/types/guards/isFieldMoneyAmountV2.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { FieldDefinition } from '../FieldDefinition'; -import { FieldMetadata, FieldMoneyAmountV2Metadata } from '../FieldMetadata'; - -export const isFieldMoneyAmountV2 = ( - field: FieldDefinition, -): field is FieldDefinition => - field.type === 'MONEY_AMOUNT_V2'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldMoneyAmountV2Value.ts b/front/src/modules/ui/object/field/types/guards/isFieldMoneyAmountV2Value.ts deleted file mode 100644 index 78476f925..000000000 --- a/front/src/modules/ui/object/field/types/guards/isFieldMoneyAmountV2Value.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { z } from 'zod'; - -import { FieldMoneyAmountV2Value } from '../FieldMetadata'; - -const moneyAmountV2Schema = z.object({ - currency: z.string(), - amount: z.number(), -}); - -export const isFieldMoneyAmountV2Value = ( - fieldValue: unknown, -): fieldValue is FieldMoneyAmountV2Value => - moneyAmountV2Schema.safeParse(fieldValue).success; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldURLV2.ts b/front/src/modules/ui/object/field/types/guards/isFieldURLV2.ts deleted file mode 100644 index eb78383e9..000000000 --- a/front/src/modules/ui/object/field/types/guards/isFieldURLV2.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { FieldDefinition } from '../FieldDefinition'; -import { FieldMetadata, FieldURLV2Metadata } from '../FieldMetadata'; - -export const isFieldURLV2 = ( - field: FieldDefinition, -): field is FieldDefinition => field.type === 'URL_V2'; diff --git a/front/src/modules/ui/object/field/types/guards/isFieldURLV2Value.ts b/front/src/modules/ui/object/field/types/guards/isFieldURLV2Value.ts deleted file mode 100644 index 713d60f40..000000000 --- a/front/src/modules/ui/object/field/types/guards/isFieldURLV2Value.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { z } from 'zod'; - -import { FieldURLV2Value } from '../FieldMetadata'; - -const urlV2Schema = z.object({ - link: z.string(), - text: z.string(), -}); - -// TODO: add zod -export const isFieldURLV2Value = ( - fieldValue: unknown, -): fieldValue is FieldURLV2Value => urlV2Schema.safeParse(fieldValue).success; diff --git a/front/src/utils/convert-currency-amount.ts b/front/src/utils/convert-currency-amount.ts new file mode 100644 index 000000000..4cbabb0e3 --- /dev/null +++ b/front/src/utils/convert-currency-amount.ts @@ -0,0 +1,30 @@ +export const convertCurrencyToCurrencyMicros = ( + currencyAmount: number | undefined, +) => { + if (!currencyAmount) { + return undefined; + } + const currencyAmountAsNumber = +currencyAmount; + if (isNaN(currencyAmountAsNumber)) { + throw new Error(`Cannot convert ${currencyAmount} to micros`); + } + const currencyAmountAsMicros = currencyAmountAsNumber * 1000000; + if (currencyAmountAsMicros % 1 !== 0) { + throw new Error(`Cannot convert ${currencyAmount} to micros`); + } + return currencyAmountAsMicros; +}; + +export const convertCurrencyMicrosToCurrency = ( + currencyAmountMicros: number | undefined, +) => { + if (!currencyAmountMicros) { + return undefined; + } + const currencyAmountMicrosAsNumber = +currencyAmountMicros; + if (isNaN(currencyAmountMicrosAsNumber)) { + throw new Error(`Cannot convert ${currencyAmountMicros} to currency`); + } + const currencyAmount = currencyAmountMicrosAsNumber / 1000000; + return currencyAmount; +}; diff --git a/server/src/database/migrations/20231116134842_rename_currency_to_currency_code/migration.sql b/server/src/database/migrations/20231116134842_rename_currency_to_currency_code/migration.sql new file mode 100644 index 000000000..16d5238ab --- /dev/null +++ b/server/src/database/migrations/20231116134842_rename_currency_to_currency_code/migration.sql @@ -0,0 +1,15 @@ +/* + Warnings: + + - The `currency` column on the `pipelines` table would be dropped and recreated. This will lead to data loss if there is data in the column. + +*/ +-- CreateEnum +CREATE TYPE "CurrencyCode" AS ENUM ('AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', 'ARS', 'AUD', 'AWG', 'AZN', 'BAM', 'BBD', 'BDT', 'BGN', 'BHD', 'BIF', 'BMD', 'BND', 'BOB', 'BOV', 'BRL', 'BSD', 'BTN', 'BWP', 'BYN', 'BZD', 'CAD', 'CDF', 'CHF', 'CLF', 'CLP', 'CNY', 'COP', 'COU', 'CRC', 'CUC', 'CUP', 'CVE', 'CZK', 'DJF', 'DKK', 'DOP', 'DZD', 'EGP', 'ERN', 'ETB', 'EUR', 'FJD', 'FKP', 'GBP', 'GEL', 'GHS', 'GIP', 'GMD', 'GNF', 'GTQ', 'GYD', 'HKD', 'HNL', 'HRK', 'HTG', 'HUF', 'IDR', 'ILS', 'INR', 'IQD', 'IRR', 'ISK', 'JMD', 'JOD', 'JPY', 'KES', 'KGS', 'KHR', 'KMF', 'KPW', 'KRW', 'KWD', 'KYD', 'KZT', 'LAK', 'LBP', 'LKR', 'LRD', 'LSL', 'LYD', 'MAD', 'MDL', 'MGA', 'MKD', 'MMK', 'MNT', 'MOP', 'MRO', 'MRU', 'MUR', 'MVR', 'MWK', 'MXN', 'MXV', 'MYR', 'MZN', 'NAD', 'NGN', 'NIO', 'NOK', 'NPR', 'NZD', 'OMR', 'PAB', 'PEN', 'PGK', 'PHP', 'PKR', 'PLN', 'PYG', 'QAR', 'RON', 'RSD', 'RUB', 'RWF', 'SAR', 'SBD', 'SCR', 'SDD', 'SDG', 'SEK', 'SGD', 'SHP', 'SLL', 'SOS', 'SRD', 'SSP', 'STD', 'STN', 'SVC', 'SYP', 'SZL', 'THB', 'TJS', 'TMM', 'TMT', 'TND', 'TOP', 'TRY', 'TTD', 'TWD', 'TZS', 'UAH', 'UGX', 'USD', 'UYU', 'UZS', 'VEF', 'VES', 'VND', 'VUV', 'WST', 'XAF', 'XCD', 'XOF', 'XPF', 'XSU', 'XUA', 'YER', 'ZAR', 'ZMW', 'ZWL'); + +-- AlterTable +ALTER TABLE "pipelines" DROP COLUMN "currency", +ADD COLUMN "currency" "CurrencyCode" NOT NULL DEFAULT 'USD'; + +-- DropEnum +DROP TYPE "Currency"; diff --git a/server/src/database/schema.prisma b/server/src/database/schema.prisma index c028db125..6da983ad6 100644 --- a/server/src/database/schema.prisma +++ b/server/src/database/schema.prisma @@ -446,7 +446,7 @@ model ActivityTarget { } // All of the world's currently active currencies based on the ISO 4217 standard -enum Currency { +enum CurrencyCode { AED AFN ALL @@ -615,6 +615,8 @@ enum Currency { ZAR ZMW ZWL + + @@map("CurrencyCode") } model Pipeline { @@ -640,7 +642,7 @@ model Pipeline { createdAt DateTime @default(now()) updatedAt DateTime @updatedAt - currency Currency @default(USD) + currency CurrencyCode @default(USD) @@map("pipelines") } diff --git a/server/src/metadata/field-metadata/field-metadata.entity.ts b/server/src/metadata/field-metadata/field-metadata.entity.ts index 64ca615a5..efd0b0102 100644 --- a/server/src/metadata/field-metadata/field-metadata.entity.ts +++ b/server/src/metadata/field-metadata/field-metadata.entity.ts @@ -27,8 +27,8 @@ export enum FieldMetadataType { NUMBER = 'NUMBER', PROBABILITY = 'PROBABILITY', ENUM = 'ENUM', - URL = 'URL', - MONEY = 'MONEY', + LINK = 'LINK', + CURRENCY = 'CURRENCY', RELATION = 'RELATION', } diff --git a/server/src/metadata/field-metadata/interfaces/field-metadata-default-value.interface.ts b/server/src/metadata/field-metadata/interfaces/field-metadata-default-value.interface.ts index 2a259f4dd..34d21fff9 100644 --- a/server/src/metadata/field-metadata/interfaces/field-metadata-default-value.interface.ts +++ b/server/src/metadata/field-metadata/interfaces/field-metadata-default-value.interface.ts @@ -23,21 +23,21 @@ export type FieldMetadataDynamicDefaultValue = | { type: 'uuid' } | { type: 'now' }; -interface FieldMetadataDefaultValueUrl { - text: string; - link: string; +interface FieldMetadataDefaultValueLink { + label: string; + url: string; } -interface FieldMetadataDefaultValueMoney { - amount: number; - currency: string; +interface FieldMetadataDefaultValueCurrency { + amountMicros: number; + currencyCode: string; } type AllFieldMetadataDefaultValueTypes = | FieldMetadataScalarDefaultValue | FieldMetadataDynamicDefaultValue - | FieldMetadataDefaultValueUrl - | FieldMetadataDefaultValueMoney; + | FieldMetadataDefaultValueLink + | FieldMetadataDefaultValueCurrency; type FieldMetadataDefaultValueMapping = { [FieldMetadataType.UUID]: FieldMetadataDefaultValueString; @@ -49,8 +49,8 @@ type FieldMetadataDefaultValueMapping = { [FieldMetadataType.NUMBER]: FieldMetadataDefaultValueNumber; [FieldMetadataType.PROBABILITY]: FieldMetadataDefaultValueNumber; [FieldMetadataType.ENUM]: FieldMetadataDefaultValueString; - [FieldMetadataType.URL]: FieldMetadataDefaultValueUrl; - [FieldMetadataType.MONEY]: FieldMetadataDefaultValueMoney; + [FieldMetadataType.LINK]: FieldMetadataDefaultValueLink; + [FieldMetadataType.CURRENCY]: FieldMetadataDefaultValueCurrency; }; type DefaultValueByFieldMetadata = [ diff --git a/server/src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface.ts b/server/src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface.ts index 03f31ae0f..4fbd3f418 100644 --- a/server/src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface.ts +++ b/server/src/metadata/field-metadata/interfaces/field-metadata-target-column-map.interface.ts @@ -4,14 +4,14 @@ export interface FieldMetadataTargetColumnMapValue { value: string; } -export interface FieldMetadataTargetColumnMapUrl { - text: string; - link: string; +export interface FieldMetadataTargetColumnMapLink { + label: string; + url: string; } -export interface FieldMetadataTargetColumnMapMoney { - amount: string; - currency: string; +export interface FieldMetadataTargetColumnMapCurrency { + amountMicros: string; + currencyCode: string; } type AllFieldMetadataTypes = { @@ -19,8 +19,8 @@ type AllFieldMetadataTypes = { }; type FieldMetadataTypeMapping = { - [FieldMetadataType.URL]: FieldMetadataTargetColumnMapUrl; - [FieldMetadataType.MONEY]: FieldMetadataTargetColumnMapMoney; + [FieldMetadataType.LINK]: FieldMetadataTargetColumnMapLink; + [FieldMetadataType.CURRENCY]: FieldMetadataTargetColumnMapCurrency; }; type TypeByFieldMetadata = diff --git a/server/src/metadata/field-metadata/utils/__tests__/convert-field-metadata-to-column-action.spec.ts b/server/src/metadata/field-metadata/utils/__tests__/convert-field-metadata-to-column-action.spec.ts index 42a6180fc..1242c025e 100644 --- a/server/src/metadata/field-metadata/utils/__tests__/convert-field-metadata-to-column-action.spec.ts +++ b/server/src/metadata/field-metadata/utils/__tests__/convert-field-metadata-to-column-action.spec.ts @@ -19,46 +19,49 @@ describe('convertFieldMetadataToColumnActions', () => { ]); }); - it('should convert URL field metadata to column actions', () => { + it('should convert LINK field metadata to column actions', () => { const fieldMetadata = { - type: FieldMetadataType.URL, - targetColumnMap: { text: 'url_text', link: 'url_link' }, - defaultValue: { text: 'http://example.com', link: 'Example' }, + type: FieldMetadataType.LINK, + targetColumnMap: { label: 'linkLabel', url: 'linkURL' }, + defaultValue: { label: 'http://example.com', url: 'Example' }, } as any; const columnActions = convertFieldMetadataToColumnActions(fieldMetadata); expect(columnActions).toEqual([ { action: 'CREATE', - columnName: 'url_text', + columnName: 'linkLabel', columnType: 'varchar', defaultValue: "'http://example.com'", }, { action: 'CREATE', - columnName: 'url_link', + columnName: 'linkURL', columnType: 'varchar', defaultValue: "'Example'", }, ]); }); - it('should convert MONEY field metadata to column actions', () => { + it('should convert CURRENCY field metadata to column actions', () => { const fieldMetadata = { - type: FieldMetadataType.MONEY, - targetColumnMap: { amount: 'money_amount', currency: 'money_currency' }, - defaultValue: { amount: 100, currency: 'USD' }, + type: FieldMetadataType.CURRENCY, + targetColumnMap: { + amountMicros: 'moneyAmountMicros', + currencyCode: 'moneyCurrencyCode', + }, + defaultValue: { amountMicros: 100 * 1_000_000, currencyCode: 'USD' }, } as any; const columnActions = convertFieldMetadataToColumnActions(fieldMetadata); expect(columnActions).toEqual([ { action: 'CREATE', - columnName: 'money_amount', + columnName: 'moneyAmountMicros', columnType: 'integer', - defaultValue: 100, + defaultValue: 100 * 1_000_000, }, { action: 'CREATE', - columnName: 'money_currency', + columnName: 'moneyCurrencyCode', columnType: 'varchar', defaultValue: "'USD'", }, diff --git a/server/src/metadata/field-metadata/utils/__tests__/generate-target-column-map.spec.ts b/server/src/metadata/field-metadata/utils/__tests__/generate-target-column-map.spec.ts index 7e6b8edbc..3910cbf71 100644 --- a/server/src/metadata/field-metadata/utils/__tests__/generate-target-column-map.spec.ts +++ b/server/src/metadata/field-metadata/utils/__tests__/generate-target-column-map.spec.ts @@ -12,21 +12,21 @@ describe('generateTargetColumnMap', () => { ); expect(textMap).toEqual({ value: 'name' }); - const urlMap = generateTargetColumnMap( - FieldMetadataType.URL, + const linkMap = generateTargetColumnMap( + FieldMetadataType.LINK, false, 'website', ); - expect(urlMap).toEqual({ text: 'website_text', link: 'website_link' }); + expect(linkMap).toEqual({ label: 'websiteLabel', url: 'websiteUrl' }); - const moneyMap = generateTargetColumnMap( - FieldMetadataType.MONEY, + const currencyMap = generateTargetColumnMap( + FieldMetadataType.CURRENCY, true, 'price', ); - expect(moneyMap).toEqual({ - amount: '_price_amount', - currency: '_price_currency', + expect(currencyMap).toEqual({ + amountMicros: '_priceAmountMicros', + currencyCode: '_priceCurrencyCode', }); }); diff --git a/server/src/metadata/field-metadata/utils/__tests__/serialize-default-value.spec.ts b/server/src/metadata/field-metadata/utils/__tests__/serialize-default-value.spec.ts index 6abae077e..1bd493390 100644 --- a/server/src/metadata/field-metadata/utils/__tests__/serialize-default-value.spec.ts +++ b/server/src/metadata/field-metadata/utils/__tests__/serialize-default-value.spec.ts @@ -8,7 +8,9 @@ describe('serializeDefaultValue', () => { }); it('should handle uuid dynamic default value', () => { - expect(serializeDefaultValue({ type: 'uuid' })).toBe('uuid_generate_v4()'); + expect(serializeDefaultValue({ type: 'uuid' })).toBe( + 'public.uuid_generate_v4()', + ); }); it('should handle now dynamic default value', () => { diff --git a/server/src/metadata/field-metadata/utils/__tests__/validate-default-value-based-on-type.spec.ts b/server/src/metadata/field-metadata/utils/__tests__/validate-default-value-based-on-type.spec.ts index 149ec172e..0702c95e3 100644 --- a/server/src/metadata/field-metadata/utils/__tests__/validate-default-value-based-on-type.spec.ts +++ b/server/src/metadata/field-metadata/utils/__tests__/validate-default-value-based-on-type.spec.ts @@ -124,44 +124,44 @@ describe('validateDefaultValueBasedOnType', () => { ).toBe(false); }); - // URL type - it('should validate URL default value', () => { + // LINK type + it('should validate LINK default value', () => { expect( validateDefaultValueBasedOnType( - { text: 'http://example.com', link: 'Example' }, - FieldMetadataType.URL, + { label: 'http://example.com', url: 'Example' }, + FieldMetadataType.LINK, ), ).toBe(true); }); - it('should return false for invalid URL default value', () => { + it('should return false for invalid LINK default value', () => { expect( validateDefaultValueBasedOnType( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error Just for testing purposes - { text: 123, link: {} }, - FieldMetadataType.URL, + { label: 123, url: {} }, + FieldMetadataType.LINK, ), ).toBe(false); }); - // MONEY type - it('should validate MONEY default value', () => { + // CURRENCY type + it('should validate CURRENCY default value', () => { expect( validateDefaultValueBasedOnType( - { amount: 100, currency: 'USD' }, - FieldMetadataType.MONEY, + { amountMicros: 100, currencyCode: 'USD' }, + FieldMetadataType.CURRENCY, ), ).toBe(true); }); - it('should return false for invalid MONEY default value', () => { + it('should return false for invalid CURRENCY default value', () => { expect( validateDefaultValueBasedOnType( // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error Just for testing purposes - { amount: '100', currency: 'USD' }, - FieldMetadataType.MONEY, + { amountMicros: '100', currencyCode: 'USD' }, + FieldMetadataType.CURRENCY, ), ).toBe(false); }); diff --git a/server/src/metadata/field-metadata/utils/convert-field-metadata-to-column-action.util.ts b/server/src/metadata/field-metadata/utils/convert-field-metadata-to-column-action.util.ts index 3631fcbc2..aaa36e76d 100644 --- a/server/src/metadata/field-metadata/utils/convert-field-metadata-to-column-action.util.ts +++ b/server/src/metadata/field-metadata/utils/convert-field-metadata-to-column-action.util.ts @@ -85,41 +85,41 @@ export function convertFieldMetadataToColumnActions( }, ]; } - case FieldMetadataType.URL: { + case FieldMetadataType.LINK: { const defaultValue = - fieldMetadata.defaultValue as FieldMetadataDefaultValue; + fieldMetadata.defaultValue as FieldMetadataDefaultValue; return [ { action: TenantMigrationColumnActionType.CREATE, - columnName: fieldMetadata.targetColumnMap.text, + columnName: fieldMetadata.targetColumnMap.label, columnType: 'varchar', - defaultValue: serializeDefaultValue(defaultValue?.text), + defaultValue: serializeDefaultValue(defaultValue?.label), }, { action: TenantMigrationColumnActionType.CREATE, - columnName: fieldMetadata.targetColumnMap.link, + columnName: fieldMetadata.targetColumnMap.url, columnType: 'varchar', - defaultValue: serializeDefaultValue(defaultValue?.link), + defaultValue: serializeDefaultValue(defaultValue?.url), }, ]; } - case FieldMetadataType.MONEY: { + case FieldMetadataType.CURRENCY: { const defaultValue = - fieldMetadata.defaultValue as FieldMetadataDefaultValue; + fieldMetadata.defaultValue as FieldMetadataDefaultValue; return [ { action: TenantMigrationColumnActionType.CREATE, - columnName: fieldMetadata.targetColumnMap.amount, + columnName: fieldMetadata.targetColumnMap.amountMicros, columnType: 'integer', - defaultValue: serializeDefaultValue(defaultValue?.amount), + defaultValue: serializeDefaultValue(defaultValue?.amountMicros), }, { action: TenantMigrationColumnActionType.CREATE, - columnName: fieldMetadata.targetColumnMap.currency, + columnName: fieldMetadata.targetColumnMap.currencyCode, columnType: 'varchar', - defaultValue: serializeDefaultValue(defaultValue?.currency), + defaultValue: serializeDefaultValue(defaultValue?.currencyCode), }, ]; } diff --git a/server/src/metadata/field-metadata/utils/generate-target-column-map.util.ts b/server/src/metadata/field-metadata/utils/generate-target-column-map.util.ts index 304e035d1..58e94b17d 100644 --- a/server/src/metadata/field-metadata/utils/generate-target-column-map.util.ts +++ b/server/src/metadata/field-metadata/utils/generate-target-column-map.util.ts @@ -29,15 +29,15 @@ export function generateTargetColumnMap( return { value: columnName, }; - case FieldMetadataType.URL: + case FieldMetadataType.LINK: return { - text: `${columnName}_text`, - link: `${columnName}_link`, + label: `${columnName}Label`, + url: `${columnName}Url`, }; - case FieldMetadataType.MONEY: + case FieldMetadataType.CURRENCY: return { - amount: `${columnName}_amount`, - currency: `${columnName}_currency`, + amountMicros: `${columnName}AmountMicros`, + currencyCode: `${columnName}CurrencyCode`, }; default: throw new BadRequestException(`Unknown type ${type}`); diff --git a/server/src/metadata/field-metadata/utils/serialize-default-value.ts b/server/src/metadata/field-metadata/utils/serialize-default-value.ts index 6bbea1680..ef45af5e0 100644 --- a/server/src/metadata/field-metadata/utils/serialize-default-value.ts +++ b/server/src/metadata/field-metadata/utils/serialize-default-value.ts @@ -13,7 +13,7 @@ export const serializeDefaultValue = ( if (typeof defaultValue === 'object' && 'type' in defaultValue) { switch (defaultValue.type) { case 'uuid': - return 'uuid_generate_v4()'; + return 'public.uuid_generate_v4()'; case 'now': return 'now()'; default: diff --git a/server/src/metadata/field-metadata/utils/validate-default-value-based-on-type.util.ts b/server/src/metadata/field-metadata/utils/validate-default-value-based-on-type.util.ts index 76d976001..72d74335b 100644 --- a/server/src/metadata/field-metadata/utils/validate-default-value-based-on-type.util.ts +++ b/server/src/metadata/field-metadata/utils/validate-default-value-based-on-type.util.ts @@ -54,22 +54,22 @@ export const validateDefaultValueBasedOnType = ( defaultValue.value instanceof Date ); - case FieldMetadataType.URL: + case FieldMetadataType.LINK: return ( typeof defaultValue === 'object' && - 'text' in defaultValue && - typeof defaultValue.text === 'string' && - 'link' in defaultValue && - typeof defaultValue.link === 'string' + 'label' in defaultValue && + typeof defaultValue.label === 'string' && + 'url' in defaultValue && + typeof defaultValue.url === 'string' ); - case FieldMetadataType.MONEY: + case FieldMetadataType.CURRENCY: return ( typeof defaultValue === 'object' && - 'amount' in defaultValue && - typeof defaultValue.amount === 'number' && - 'currency' in defaultValue && - typeof defaultValue.currency === 'string' + 'amountMicros' in defaultValue && + typeof defaultValue.amountMicros === 'number' && + 'currencyCode' in defaultValue && + typeof defaultValue.currencyCode === 'string' ); default: diff --git a/server/src/metadata/object-metadata/object-metadata.service.ts b/server/src/metadata/object-metadata/object-metadata.service.ts index eddc7cbc9..bcda53941 100644 --- a/server/src/metadata/object-metadata/object-metadata.service.ts +++ b/server/src/metadata/object-metadata/object-metadata.service.ts @@ -75,7 +75,7 @@ export class ObjectMetadataService extends TypeOrmQueryService([ [FieldMetadataType.UUID, GraphQLID], [FieldMetadataType.TEXT, GraphQLString], @@ -78,7 +78,7 @@ export class TypeMapperService { const numberScalar = numberScalarMode === 'float' ? FloatFilterType : IntFilterType; - // URL and MONEY are handled in the factories because they are objects + // LINK and CURRENCY are handled in the factories because they are objects const typeFilterMapping = new Map< FieldMetadataType, GraphQLInputObjectType | GraphQLScalarType @@ -100,7 +100,7 @@ export class TypeMapperService { mapToOrderByType( fieldMetadataType: FieldMetadataType, ): GraphQLInputType | undefined { - // URL and MONEY are handled in the factories because they are objects + // LINK and CURRENCY are handled in the factories because they are objects const typeOrderByMapping = new Map([ [FieldMetadataType.UUID, OrderByDirectionType], [FieldMetadataType.TEXT, OrderByDirectionType], diff --git a/server/src/tenant/schema-builder/type-definitions.generator.ts b/server/src/tenant/schema-builder/type-definitions.generator.ts index 642ada9e0..a161dbd76 100644 --- a/server/src/tenant/schema-builder/type-definitions.generator.ts +++ b/server/src/tenant/schema-builder/type-definitions.generator.ts @@ -14,8 +14,8 @@ import { } from './factories/input-type-definition.factory'; import { getFieldMetadataType } from './utils/get-field-metadata-type.util'; import { BuildSchemaOptions } from './interfaces/build-schema-optionts.interface'; -import { moneyObjectDefinition } from './object-definitions/money.object-definition'; -import { urlObjectDefinition } from './object-definitions/url.object-definition'; +import { currencyObjectDefinition } from './object-definitions/currency.object-definition'; +import { linkObjectDefinition } from './object-definitions/link.object-definition'; import { ObjectMetadataInterface } from './interfaces/object-metadata.interface'; import { FieldMetadataInterface } from './interfaces/field-metadata.interface'; import { FilterTypeDefinitionFactory } from './factories/filter-type-definition.factory'; @@ -61,8 +61,8 @@ export class TypeDefinitionsGenerator { private generateStaticObjectTypeDefs(options: BuildSchemaOptions) { const staticObjectMetadataCollection = [ - moneyObjectDefinition, - urlObjectDefinition, + currencyObjectDefinition, + linkObjectDefinition, ]; this.logger.log(