download record sample - Import (#12489)
<img width="400" alt="Screenshot 2025-06-10 at 18 14 17" src="https://github.com/user-attachments/assets/05591b46-c36d-45c6-a236-3469c29d7420" /> closes https://github.com/twentyhq/core-team-issues/issues/915 --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -3,5 +3,7 @@ import { COMPOSITE_FIELD_TYPES } from '@/settings/data-model/types/CompositeFiel
|
||||
|
||||
export const ALL_SUB_FIELDS = COMPOSITE_FIELD_TYPES.flatMap(
|
||||
(compositeFieldType) =>
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[compositeFieldType].subFields,
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[compositeFieldType].subFields.map(
|
||||
(subField) => subField.subFieldName,
|
||||
),
|
||||
);
|
||||
|
||||
@ -25,11 +25,16 @@ import {
|
||||
} from 'twenty-ui/display';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
type CompositeSubFieldConfig<T> = {
|
||||
subFieldName: keyof T;
|
||||
subFieldLabel: string;
|
||||
isImportable: boolean;
|
||||
isFilterable: boolean;
|
||||
};
|
||||
|
||||
export type SettingsCompositeFieldTypeConfig<T> = SettingsFieldTypeConfig<T> & {
|
||||
subFields: (keyof T)[];
|
||||
filterableSubFields: (keyof T)[];
|
||||
labelBySubField: Record<keyof T, string>;
|
||||
exampleValue: T;
|
||||
subFields: CompositeSubFieldConfig<T>[];
|
||||
exampleValues: [T, T, T];
|
||||
};
|
||||
|
||||
type SettingsCompositeFieldTypeConfigArray = Record<
|
||||
@ -41,215 +46,415 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
||||
[FieldMetadataType.CURRENCY]: {
|
||||
label: 'Currency',
|
||||
Icon: IllustrationIconCurrency,
|
||||
subFields: ['amountMicros', 'currencyCode'],
|
||||
filterableSubFields: ['amountMicros', 'currencyCode'],
|
||||
labelBySubField: {
|
||||
amountMicros:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.CURRENCY]
|
||||
.amountMicros,
|
||||
currencyCode:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.CURRENCY]
|
||||
.currencyCode,
|
||||
},
|
||||
exampleValue: {
|
||||
amountMicros: 2000000000,
|
||||
currencyCode: CurrencyCode.USD,
|
||||
},
|
||||
subFields: [
|
||||
{
|
||||
subFieldName: 'amountMicros',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.CURRENCY]
|
||||
.amountMicros,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'currencyCode',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.CURRENCY]
|
||||
.currencyCode,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
],
|
||||
exampleValues: [
|
||||
{
|
||||
amountMicros: 2000000000,
|
||||
currencyCode: CurrencyCode.USD,
|
||||
},
|
||||
{
|
||||
amountMicros: 3000000000,
|
||||
currencyCode: CurrencyCode.GBP,
|
||||
},
|
||||
{
|
||||
amountMicros: 100000000,
|
||||
currencyCode: CurrencyCode.AED,
|
||||
},
|
||||
],
|
||||
category: 'Basic',
|
||||
} as const satisfies SettingsCompositeFieldTypeConfig<FieldCurrencyValue>,
|
||||
[FieldMetadataType.EMAILS]: {
|
||||
label: 'Emails',
|
||||
Icon: IllustrationIconMail,
|
||||
subFields: ['primaryEmail', 'additionalEmails'],
|
||||
filterableSubFields: ['primaryEmail', 'additionalEmails'],
|
||||
labelBySubField: {
|
||||
primaryEmail: 'Primary Email',
|
||||
additionalEmails: 'Additional Emails',
|
||||
},
|
||||
exampleValue: {
|
||||
primaryEmail: 'john@twenty.com',
|
||||
additionalEmails: [
|
||||
'tim@twenty.com',
|
||||
'timapple@twenty.com',
|
||||
'johnappletim@twenty.com',
|
||||
],
|
||||
},
|
||||
subFields: [
|
||||
{
|
||||
subFieldName: 'primaryEmail',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.EMAILS]
|
||||
.primaryEmail,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'additionalEmails',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.EMAILS]
|
||||
.additionalEmails,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
],
|
||||
exampleValues: [
|
||||
{
|
||||
primaryEmail: 'tim@twenty.com',
|
||||
additionalEmails: [
|
||||
'tim@twenty.com',
|
||||
'timapple@twenty.com',
|
||||
'johnappletim@twenty.com',
|
||||
],
|
||||
},
|
||||
{
|
||||
primaryEmail: 'jane@twenty.com',
|
||||
additionalEmails: ['jane@twenty.com', 'jane.doe@twenty.com'],
|
||||
},
|
||||
{
|
||||
primaryEmail: 'john@twenty.com',
|
||||
additionalEmails: ['john.doe@twenty.com'],
|
||||
},
|
||||
],
|
||||
category: 'Basic',
|
||||
} as const satisfies SettingsCompositeFieldTypeConfig<FieldEmailsValue>,
|
||||
[FieldMetadataType.LINKS]: {
|
||||
label: 'Links',
|
||||
Icon: IllustrationIconLink,
|
||||
exampleValue: {
|
||||
primaryLinkUrl: 'twenty.com',
|
||||
primaryLinkLabel: '',
|
||||
secondaryLinks: [{ url: 'twenty.com', label: 'Twenty' }],
|
||||
},
|
||||
category: 'Basic',
|
||||
subFields: ['primaryLinkUrl', 'primaryLinkLabel', 'secondaryLinks'],
|
||||
filterableSubFields: [
|
||||
'primaryLinkUrl',
|
||||
'primaryLinkLabel',
|
||||
'secondaryLinks',
|
||||
subFields: [
|
||||
{
|
||||
subFieldName: 'primaryLinkUrl',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.LINKS]
|
||||
.primaryLinkUrl,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'primaryLinkLabel',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.LINKS]
|
||||
.primaryLinkLabel,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'secondaryLinks',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.LINKS]
|
||||
.secondaryLinks,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
],
|
||||
labelBySubField: {
|
||||
primaryLinkUrl:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.LINKS]
|
||||
.primaryLinkUrl,
|
||||
primaryLinkLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.LINKS]
|
||||
.primaryLinkLabel,
|
||||
secondaryLinks:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.LINKS]
|
||||
.secondaryLinks,
|
||||
},
|
||||
exampleValues: [
|
||||
{
|
||||
primaryLinkUrl: 'twenty.com',
|
||||
primaryLinkLabel: '',
|
||||
secondaryLinks: [{ url: 'twenty.com', label: 'Twenty' }],
|
||||
},
|
||||
{
|
||||
primaryLinkUrl: 'github.com/twentyhq/twenty',
|
||||
primaryLinkLabel: 'Twenty Repo',
|
||||
secondaryLinks: [{ url: 'twenty.com', label: '' }],
|
||||
},
|
||||
{
|
||||
primaryLinkUrl: 'react.dev',
|
||||
primaryLinkLabel: '',
|
||||
secondaryLinks: [],
|
||||
},
|
||||
],
|
||||
category: 'Basic',
|
||||
} as const satisfies SettingsCompositeFieldTypeConfig<FieldLinksValue>,
|
||||
[FieldMetadataType.PHONES]: {
|
||||
label: 'Phones',
|
||||
Icon: IllustrationIconPhone,
|
||||
exampleValue: {
|
||||
primaryPhoneCallingCode: '+33',
|
||||
primaryPhoneCountryCode: 'FR',
|
||||
primaryPhoneNumber: '789012345',
|
||||
additionalPhones: [
|
||||
{ number: '617272323', callingCode: '+33', countryCode: 'FR' },
|
||||
],
|
||||
},
|
||||
subFields: [
|
||||
'primaryPhoneNumber',
|
||||
'primaryPhoneCountryCode',
|
||||
'primaryPhoneCallingCode',
|
||||
'additionalPhones',
|
||||
{
|
||||
subFieldName: 'primaryPhoneCallingCode',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.PHONES]
|
||||
.primaryPhoneCallingCode,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'primaryPhoneCountryCode',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.PHONES]
|
||||
.primaryPhoneCountryCode,
|
||||
isImportable: true,
|
||||
isFilterable: false,
|
||||
},
|
||||
{
|
||||
subFieldName: 'primaryPhoneNumber',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.PHONES]
|
||||
.primaryPhoneNumber,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'additionalPhones',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.PHONES]
|
||||
.additionalPhones,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
],
|
||||
filterableSubFields: [
|
||||
'primaryPhoneNumber',
|
||||
'primaryPhoneCallingCode',
|
||||
'additionalPhones',
|
||||
exampleValues: [
|
||||
{
|
||||
primaryPhoneCallingCode: '+33',
|
||||
primaryPhoneCountryCode: 'FR',
|
||||
primaryPhoneNumber: '789012345',
|
||||
additionalPhones: [
|
||||
{ number: '617272323', callingCode: '+33', countryCode: 'FR' },
|
||||
],
|
||||
},
|
||||
{
|
||||
primaryPhoneCallingCode: '+1',
|
||||
primaryPhoneCountryCode: 'US',
|
||||
primaryPhoneNumber: '612345789',
|
||||
additionalPhones: [
|
||||
{ number: '123456789', callingCode: '+1', countryCode: 'US' },
|
||||
{ number: '617272323', callingCode: '+1', countryCode: 'US' },
|
||||
],
|
||||
},
|
||||
{
|
||||
primaryPhoneCallingCode: '+33',
|
||||
primaryPhoneCountryCode: 'FR',
|
||||
primaryPhoneNumber: '123456789',
|
||||
additionalPhones: [],
|
||||
},
|
||||
],
|
||||
labelBySubField: {
|
||||
primaryPhoneNumber:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.PHONES]
|
||||
.primaryPhoneNumber,
|
||||
primaryPhoneCountryCode:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.PHONES]
|
||||
.primaryPhoneCountryCode,
|
||||
primaryPhoneCallingCode:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.PHONES]
|
||||
.primaryPhoneCallingCode,
|
||||
additionalPhones:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.PHONES]
|
||||
.additionalPhones,
|
||||
},
|
||||
category: 'Basic',
|
||||
} as const satisfies SettingsCompositeFieldTypeConfig<FieldPhonesValue>,
|
||||
[FieldMetadataType.FULL_NAME]: {
|
||||
label: 'Full Name',
|
||||
Icon: IllustrationIconUser,
|
||||
exampleValue: { firstName: 'John', lastName: 'Doe' },
|
||||
subFields: [
|
||||
{
|
||||
subFieldName: 'firstName',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.FULL_NAME]
|
||||
.firstName,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'lastName',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.FULL_NAME]
|
||||
.lastName,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
],
|
||||
exampleValues: [
|
||||
{ firstName: 'John', lastName: 'Doe' },
|
||||
{ firstName: 'Jane', lastName: 'Doe' },
|
||||
{ firstName: 'John', lastName: 'Smith' },
|
||||
],
|
||||
category: 'Basic',
|
||||
subFields: ['firstName', 'lastName'],
|
||||
filterableSubFields: ['firstName', 'lastName'],
|
||||
labelBySubField: {
|
||||
firstName:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.FULL_NAME].firstName,
|
||||
lastName:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.FULL_NAME].lastName,
|
||||
},
|
||||
} as const satisfies SettingsCompositeFieldTypeConfig<FieldFullNameValue>,
|
||||
[FieldMetadataType.ADDRESS]: {
|
||||
label: 'Address',
|
||||
Icon: IllustrationIconMap,
|
||||
subFields: [
|
||||
'addressStreet1',
|
||||
'addressStreet2',
|
||||
'addressCity',
|
||||
'addressState',
|
||||
'addressCountry',
|
||||
'addressPostcode',
|
||||
'addressLat',
|
||||
'addressLng',
|
||||
{
|
||||
subFieldName: 'addressStreet1',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
|
||||
.addressStreet1,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'addressStreet2',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
|
||||
.addressStreet2,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'addressCity',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
|
||||
.addressCity,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'addressState',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
|
||||
.addressState,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'addressCountry',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
|
||||
.addressCountry,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'addressPostcode',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
|
||||
.addressPostcode,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'addressLat',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
|
||||
.addressLat,
|
||||
isImportable: false,
|
||||
isFilterable: false,
|
||||
},
|
||||
{
|
||||
subFieldName: 'addressLng',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
|
||||
.addressLng,
|
||||
isImportable: false,
|
||||
isFilterable: false,
|
||||
},
|
||||
],
|
||||
filterableSubFields: [
|
||||
'addressStreet1',
|
||||
'addressStreet2',
|
||||
'addressCity',
|
||||
'addressState',
|
||||
'addressCountry',
|
||||
'addressPostcode',
|
||||
exampleValues: [
|
||||
{
|
||||
addressStreet1: '456 Oak Street',
|
||||
addressStreet2: '',
|
||||
addressCity: 'Springfield',
|
||||
addressState: 'California',
|
||||
addressCountry: 'United States',
|
||||
addressPostcode: '90210',
|
||||
addressLat: 34.0522,
|
||||
addressLng: -118.2437,
|
||||
},
|
||||
{
|
||||
addressStreet1: '123 Main Street',
|
||||
addressStreet2: '',
|
||||
addressCity: 'New York',
|
||||
addressState: 'New York',
|
||||
addressCountry: 'United States',
|
||||
addressPostcode: '10001',
|
||||
addressLat: 40.7128,
|
||||
addressLng: -74.006,
|
||||
},
|
||||
{
|
||||
addressStreet1: '8 rue Saint-Anne',
|
||||
addressStreet2: '',
|
||||
addressCity: 'Paris',
|
||||
addressState: 'Ile-de-France',
|
||||
addressCountry: 'France',
|
||||
addressPostcode: '75001',
|
||||
addressLat: 40.7128,
|
||||
addressLng: -74.006,
|
||||
},
|
||||
],
|
||||
labelBySubField: {
|
||||
addressStreet1:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
|
||||
.addressStreet1,
|
||||
addressStreet2:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
|
||||
.addressStreet2,
|
||||
addressCity:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS].addressCity,
|
||||
addressState:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
|
||||
.addressState,
|
||||
addressCountry:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
|
||||
.addressCountry,
|
||||
addressPostcode:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS]
|
||||
.addressPostcode,
|
||||
addressLat:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS].addressLat,
|
||||
addressLng:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ADDRESS].addressLng,
|
||||
},
|
||||
exampleValue: {
|
||||
addressStreet1: '456 Oak Street',
|
||||
addressStreet2: '',
|
||||
addressCity: 'Springfield',
|
||||
addressState: 'California',
|
||||
addressCountry: 'United States',
|
||||
addressPostcode: '90210',
|
||||
addressLat: 34.0522,
|
||||
addressLng: -118.2437,
|
||||
},
|
||||
category: 'Basic',
|
||||
} as const satisfies SettingsCompositeFieldTypeConfig<FieldAddressValue>,
|
||||
[FieldMetadataType.ACTOR]: {
|
||||
label: 'Actor',
|
||||
Icon: IllustrationIconSetting,
|
||||
category: 'Basic',
|
||||
subFields: ['source', 'name'],
|
||||
filterableSubFields: ['source', 'name'],
|
||||
labelBySubField: {
|
||||
source: COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].source,
|
||||
name: COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].name,
|
||||
workspaceMemberId:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR]
|
||||
.workspaceMemberId,
|
||||
context:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].context,
|
||||
},
|
||||
exampleValue: {
|
||||
source: 'IMPORT',
|
||||
name: 'name',
|
||||
workspaceMemberId: 'id',
|
||||
context: { provider: ConnectedAccountProvider.GOOGLE },
|
||||
},
|
||||
subFields: [
|
||||
{
|
||||
subFieldName: 'source',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].source,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'name',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].name,
|
||||
isImportable: true,
|
||||
isFilterable: true,
|
||||
},
|
||||
{
|
||||
subFieldName: 'workspaceMemberId',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR]
|
||||
.workspaceMemberId,
|
||||
isImportable: true,
|
||||
isFilterable: false,
|
||||
},
|
||||
{
|
||||
subFieldName: 'context',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].context,
|
||||
isImportable: true,
|
||||
isFilterable: false,
|
||||
},
|
||||
],
|
||||
exampleValues: [
|
||||
{
|
||||
source: 'IMPORT',
|
||||
name: 'name',
|
||||
workspaceMemberId: 'id',
|
||||
context: { provider: ConnectedAccountProvider.GOOGLE },
|
||||
},
|
||||
{
|
||||
source: 'MANUAL',
|
||||
name: 'name',
|
||||
workspaceMemberId: 'id',
|
||||
context: { provider: ConnectedAccountProvider.MICROSOFT },
|
||||
},
|
||||
{
|
||||
source: 'WEBHOOK',
|
||||
name: 'name',
|
||||
workspaceMemberId: 'id',
|
||||
context: {},
|
||||
},
|
||||
],
|
||||
} as const satisfies SettingsCompositeFieldTypeConfig<FieldActorValue>,
|
||||
[FieldMetadataType.RICH_TEXT_V2]: {
|
||||
label: 'Rich Text',
|
||||
Icon: IllustrationIconText,
|
||||
subFields: ['blocknote', 'markdown'],
|
||||
filterableSubFields: [],
|
||||
labelBySubField: {
|
||||
blocknote:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.RICH_TEXT_V2]
|
||||
.blocknote,
|
||||
markdown:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.RICH_TEXT_V2]
|
||||
.markdown,
|
||||
},
|
||||
exampleValue: {
|
||||
blocknote: '[{"type":"heading","content":"Hello"}]',
|
||||
markdown: '# Hello',
|
||||
},
|
||||
category: 'Basic',
|
||||
subFields: [
|
||||
{
|
||||
subFieldName: 'blocknote',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.RICH_TEXT_V2]
|
||||
.blocknote,
|
||||
isImportable: false,
|
||||
isFilterable: false,
|
||||
},
|
||||
{
|
||||
subFieldName: 'markdown',
|
||||
subFieldLabel:
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.RICH_TEXT_V2]
|
||||
.markdown,
|
||||
isImportable: false,
|
||||
isFilterable: false,
|
||||
},
|
||||
],
|
||||
exampleValues: [
|
||||
{
|
||||
blocknote: '[{"type":"heading","content":"Hello"}]',
|
||||
markdown: '# Hello',
|
||||
},
|
||||
{
|
||||
blocknote: '[{"type":"heading","content":"Hello World"}]',
|
||||
markdown: '# Hello World',
|
||||
},
|
||||
{
|
||||
blocknote: '[{"type":"heading","content":"Hello Again"}]',
|
||||
markdown: '# Hello Again',
|
||||
},
|
||||
],
|
||||
} as const satisfies SettingsCompositeFieldTypeConfig<FieldRichTextV2Value>,
|
||||
} as const satisfies SettingsCompositeFieldTypeConfigArray;
|
||||
|
||||
@ -15,7 +15,6 @@ import {
|
||||
import { DEFAULT_DATE_VALUE } from '@/settings/data-model/constants/DefaultDateValue';
|
||||
import { SettingsFieldTypeCategoryType } from '@/settings/data-model/types/SettingsFieldTypeCategoryType';
|
||||
import { SettingsNonCompositeFieldType } from '@/settings/data-model/types/SettingsNonCompositeFieldType';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import {
|
||||
IconComponent,
|
||||
IllustrationIconArray,
|
||||
@ -31,13 +30,14 @@ import {
|
||||
IllustrationIconToggle,
|
||||
IllustrationIconUid,
|
||||
} from 'twenty-ui/display';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
DEFAULT_DATE_VALUE.setFullYear(DEFAULT_DATE_VALUE.getFullYear() + 2);
|
||||
|
||||
export type SettingsFieldTypeConfig<T> = {
|
||||
label: string;
|
||||
Icon: IconComponent;
|
||||
exampleValue?: T;
|
||||
exampleValues?: [T, T, T];
|
||||
category: SettingsFieldTypeCategoryType;
|
||||
};
|
||||
|
||||
@ -52,44 +52,59 @@ export const SETTINGS_NON_COMPOSITE_FIELD_TYPE_CONFIGS: SettingsNonCompositeFiel
|
||||
[FieldMetadataType.UUID]: {
|
||||
label: 'Unique ID',
|
||||
Icon: IllustrationIconUid,
|
||||
exampleValue: '00000000-0000-0000-0000-000000000000',
|
||||
exampleValues: [
|
||||
'00000000-0000-0000-0000-000000000000',
|
||||
'00000000-0000-0000-0000-000000000001',
|
||||
'00000000-0000-0000-0000-000000000002',
|
||||
],
|
||||
category: 'Advanced',
|
||||
} as const satisfies SettingsFieldTypeConfig<FieldUUidValue>,
|
||||
[FieldMetadataType.TEXT]: {
|
||||
label: 'Text',
|
||||
Icon: IllustrationIconText,
|
||||
exampleValue:
|
||||
exampleValues: [
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum magna enim, dapibus non enim in, lacinia faucibus nunc. Sed interdum ante sed felis facilisis, eget ultricies neque molestie. Mauris auctor, justo eu volutpat cursus, libero erat tempus nulla, non sodales lorem lacus a est.',
|
||||
'Vestibulum magna enim, dapibus non enim in, lacinia faucibus nunc. Sed interdum ante sed felis facilisis, eget ultricies neque molestie. Mauris auctor, justo eu volutpat cursus, libero erat tempus nulla, non sodales lorem lacus a est.',
|
||||
'Sed interdum ante sed felis facilisis, eget ultricies neque molestie. Mauris auctor, justo eu volutpat cursus, libero erat tempus nulla, non sodales lorem lacus a est.',
|
||||
],
|
||||
category: 'Basic',
|
||||
} as const satisfies SettingsFieldTypeConfig<FieldTextValue>,
|
||||
[FieldMetadataType.NUMERIC]: {
|
||||
label: 'Numeric',
|
||||
Icon: IllustrationIconNumbers,
|
||||
exampleValue: 2000,
|
||||
exampleValues: [2000, 3000, 4000],
|
||||
category: 'Basic',
|
||||
} as const satisfies SettingsFieldTypeConfig<FieldNumberValue>,
|
||||
[FieldMetadataType.NUMBER]: {
|
||||
label: 'Number',
|
||||
Icon: IllustrationIconNumbers,
|
||||
exampleValue: 2000,
|
||||
exampleValues: [2000, 3000, 4000],
|
||||
category: 'Basic',
|
||||
} as const satisfies SettingsFieldTypeConfig<FieldNumberValue>,
|
||||
[FieldMetadataType.BOOLEAN]: {
|
||||
label: 'True/False',
|
||||
Icon: IllustrationIconToggle,
|
||||
exampleValue: true,
|
||||
exampleValues: [true, false, true],
|
||||
category: 'Basic',
|
||||
} as const satisfies SettingsFieldTypeConfig<FieldBooleanValue>,
|
||||
[FieldMetadataType.DATE_TIME]: {
|
||||
label: 'Date and Time',
|
||||
Icon: IllustrationIconCalendarTime,
|
||||
exampleValue: DEFAULT_DATE_VALUE.toISOString(),
|
||||
exampleValues: [
|
||||
DEFAULT_DATE_VALUE.toISOString(),
|
||||
'2025-06-10T12:01:00.000Z',
|
||||
'2018-07-14T12:02:00.000Z',
|
||||
],
|
||||
category: 'Basic',
|
||||
} as const satisfies SettingsFieldTypeConfig<FieldDateTimeValue>,
|
||||
[FieldMetadataType.DATE]: {
|
||||
label: 'Date',
|
||||
Icon: IllustrationIconCalendarEvent,
|
||||
exampleValue: DEFAULT_DATE_VALUE.toISOString(),
|
||||
exampleValues: [
|
||||
DEFAULT_DATE_VALUE.toISOString(),
|
||||
'2025-06-10T00:00:00.000Z',
|
||||
'2018-07-14T00:00:00.000Z',
|
||||
],
|
||||
category: 'Basic',
|
||||
} as const satisfies SettingsFieldTypeConfig<FieldDateValue>,
|
||||
[FieldMetadataType.SELECT]: {
|
||||
@ -110,19 +125,19 @@ export const SETTINGS_NON_COMPOSITE_FIELD_TYPE_CONFIGS: SettingsNonCompositeFiel
|
||||
[FieldMetadataType.RATING]: {
|
||||
label: 'Rating',
|
||||
Icon: IllustrationIconStar,
|
||||
exampleValue: 'RATING_3',
|
||||
exampleValues: ['RATING_3', 'RATING_4', 'RATING_5'],
|
||||
category: 'Basic',
|
||||
} as const satisfies SettingsFieldTypeConfig<FieldRatingValue>,
|
||||
[FieldMetadataType.RAW_JSON]: {
|
||||
label: 'JSON',
|
||||
Icon: IllustrationIconJson,
|
||||
exampleValue: { key: 'value' },
|
||||
exampleValues: [{ key: 'value1' }, { key: 'value2', key2: 'value2' }, {}],
|
||||
category: 'Advanced',
|
||||
} as const satisfies SettingsFieldTypeConfig<FieldJsonValue>,
|
||||
[FieldMetadataType.ARRAY]: {
|
||||
label: 'Array',
|
||||
Icon: IllustrationIconArray,
|
||||
category: 'Advanced',
|
||||
exampleValue: ['value1', 'value2'],
|
||||
exampleValues: [['value1', 'value2'], ['value3'], []],
|
||||
} as const satisfies SettingsFieldTypeConfig<FieldArrayValue>,
|
||||
};
|
||||
|
||||
@ -51,7 +51,7 @@ describe('getFieldPreviewValue', () => {
|
||||
// Then
|
||||
expect(result).toBe(2000);
|
||||
expect(result).toBe(
|
||||
getSettingsFieldTypeConfig(FieldMetadataType.NUMBER).exampleValue,
|
||||
getSettingsFieldTypeConfig(FieldMetadataType.NUMBER).exampleValues?.[0],
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ export const getAddressFieldPreviewValue = ({
|
||||
FieldMetadataType.ADDRESS,
|
||||
);
|
||||
|
||||
const placeholderDefaultValue = addressFieldTypeConfig.exampleValue;
|
||||
const placeholderDefaultValue = addressFieldTypeConfig.exampleValues?.[0];
|
||||
|
||||
const addressCountry =
|
||||
fieldMetadataItem.defaultValue?.addressCountry &&
|
||||
|
||||
@ -20,7 +20,7 @@ export const getCurrencyFieldPreviewValue = ({
|
||||
FieldMetadataType.CURRENCY,
|
||||
);
|
||||
|
||||
const placeholderDefaultValue = currencyFieldTypeConfig.exampleValue;
|
||||
const placeholderDefaultValue = currencyFieldTypeConfig.exampleValues?.[0];
|
||||
|
||||
return currencyFieldDefaultValueSchema
|
||||
.transform((value) => ({
|
||||
|
||||
@ -31,10 +31,10 @@ export const getFieldPreviewValue = ({
|
||||
|
||||
if (
|
||||
isDefined(fieldTypeConfig) &&
|
||||
'exampleValue' in fieldTypeConfig &&
|
||||
isDefined(fieldTypeConfig.exampleValue)
|
||||
'exampleValues' in fieldTypeConfig &&
|
||||
isDefined(fieldTypeConfig.exampleValues?.[0])
|
||||
) {
|
||||
return fieldTypeConfig.exampleValue;
|
||||
return fieldTypeConfig.exampleValues?.[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@ -38,7 +38,7 @@ export const getPhonesFieldPreviewValue = ({
|
||||
FieldMetadataType.PHONES,
|
||||
);
|
||||
|
||||
const placeholderDefaultValue = phonesFieldTypeConfig.exampleValue;
|
||||
const placeholderDefaultValue = phonesFieldTypeConfig.exampleValues?.[0];
|
||||
const primaryPhoneCountryCode =
|
||||
fieldMetadataItem.defaultValue?.primaryPhoneCountryCode &&
|
||||
fieldMetadataItem.defaultValue.primaryPhoneCountryCode !== ''
|
||||
|
||||
@ -5,9 +5,10 @@ import { COMPOSITE_FIELD_TYPES } from '@/settings/data-model/types/CompositeFiel
|
||||
export const isValidSubFieldName = (
|
||||
subFieldName: string,
|
||||
): subFieldName is CompositeFieldSubFieldName => {
|
||||
const allSubFields = COMPOSITE_FIELD_TYPES.flatMap(
|
||||
(compositeFieldType) =>
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[compositeFieldType].subFields,
|
||||
const allSubFields = COMPOSITE_FIELD_TYPES.flatMap((compositeFieldType) =>
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[compositeFieldType].subFields.map(
|
||||
(subField) => subField.subFieldName,
|
||||
),
|
||||
);
|
||||
|
||||
return allSubFields.includes(subFieldName as any);
|
||||
|
||||
Reference in New Issue
Block a user