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:
@ -90,9 +90,9 @@ export const AdvancedFilterSubFieldSelectMenu = ({
|
||||
return null;
|
||||
}
|
||||
|
||||
const subFieldNames =
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[objectFilterDropdownSubMenuFieldType]
|
||||
.filterableSubFields;
|
||||
const subFieldNames = SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[
|
||||
objectFilterDropdownSubMenuFieldType
|
||||
].subFields.map((subField) => subField.subFieldName);
|
||||
|
||||
const subFieldsAreFilterable =
|
||||
isDefined(fieldMetadataItemUsedInDropdown) &&
|
||||
|
||||
@ -3,10 +3,11 @@ import { CompositeFieldType } from '@/settings/data-model/types/CompositeFieldTy
|
||||
|
||||
export const getCompositeSubFieldLabel = (
|
||||
compositeFieldType: CompositeFieldType,
|
||||
subFieldName: (typeof SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS)[CompositeFieldType]['subFields'][number],
|
||||
subFieldName: (typeof SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS)[CompositeFieldType]['subFields'][number]['subFieldName'],
|
||||
): string => {
|
||||
return (
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[compositeFieldType]
|
||||
.labelBySubField as any
|
||||
)[subFieldName];
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[compositeFieldType].subFields.find(
|
||||
(subField) => subField.subFieldName === subFieldName,
|
||||
)?.subFieldLabel || ''
|
||||
);
|
||||
};
|
||||
|
||||
@ -5,16 +5,15 @@ export const isExpectedSubFieldName = <
|
||||
CompositeFieldTypeSettings extends
|
||||
typeof SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS,
|
||||
PossibleSubFieldsForGivenFieldType extends
|
||||
CompositeFieldTypeSettings[GivenFieldType]['subFields'][number],
|
||||
CompositeFieldTypeSettings[GivenFieldType]['subFields'][number]['subFieldName'],
|
||||
>(
|
||||
fieldMetadataType: GivenFieldType,
|
||||
subFieldName: PossibleSubFieldsForGivenFieldType,
|
||||
subFieldNameToCheck: string | null | undefined,
|
||||
): subFieldNameToCheck is PossibleSubFieldsForGivenFieldType => {
|
||||
return (
|
||||
(
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[fieldMetadataType]
|
||||
.subFields as string[]
|
||||
).includes(subFieldName) && subFieldName === subFieldNameToCheck
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[fieldMetadataType].subFields
|
||||
.map((subField) => subField.subFieldName)
|
||||
.includes(subFieldName) && subFieldName === subFieldNameToCheck
|
||||
);
|
||||
};
|
||||
|
||||
@ -12,6 +12,7 @@ import {
|
||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { COMPOSITE_FIELD_SUB_FIELD_LABELS } from '@/settings/data-model/constants/CompositeFieldSubFieldLabel';
|
||||
import { escapeCSVValue } from '@/spreadsheet-import/utils/escapeCSVValue';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@ -59,9 +60,9 @@ export const generateCsv: GenerateExport = ({
|
||||
const keys = columnsToExportWithIdColumn.flatMap((col) => {
|
||||
const column = {
|
||||
field: `${col.metadata.fieldName}${col.type === 'RELATION' ? 'Id' : ''}`,
|
||||
title: [col.label, col.type === 'RELATION' ? 'Id' : null]
|
||||
.filter(isDefined)
|
||||
.join(' '),
|
||||
title: escapeCSVValue(
|
||||
`${col.label}${col.type === 'RELATION' ? ' Id' : ''}`,
|
||||
),
|
||||
};
|
||||
|
||||
const columnType = col.type;
|
||||
|
||||
@ -1,97 +0,0 @@
|
||||
import {
|
||||
FieldActorValue,
|
||||
FieldAddressValue,
|
||||
FieldCurrencyValue,
|
||||
FieldEmailsValue,
|
||||
FieldFullNameValue,
|
||||
FieldLinksValue,
|
||||
FieldPhonesValue,
|
||||
FieldRichTextV2Value,
|
||||
} from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { CompositeFieldLabels } from '@/object-record/spreadsheet-import/types/CompositeFieldLabels';
|
||||
import { SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsCompositeFieldTypeConfigs';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const COMPOSITE_FIELD_IMPORT_LABELS = {
|
||||
[FieldMetadataType.FULL_NAME]: {
|
||||
firstNameLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.FULL_NAME.labelBySubField.firstName,
|
||||
lastNameLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.FULL_NAME.labelBySubField.lastName,
|
||||
} satisfies CompositeFieldLabels<FieldFullNameValue>,
|
||||
[FieldMetadataType.CURRENCY]: {
|
||||
currencyCodeLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.CURRENCY.labelBySubField
|
||||
.currencyCode,
|
||||
amountMicrosLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.CURRENCY.labelBySubField
|
||||
.amountMicros,
|
||||
} satisfies CompositeFieldLabels<FieldCurrencyValue>,
|
||||
[FieldMetadataType.ADDRESS]: {
|
||||
addressStreet1Label:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.ADDRESS.labelBySubField
|
||||
.addressStreet1,
|
||||
addressStreet2Label:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.ADDRESS.labelBySubField
|
||||
.addressStreet2,
|
||||
addressCityLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.ADDRESS.labelBySubField.addressCity,
|
||||
addressPostcodeLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.ADDRESS.labelBySubField
|
||||
.addressPostcode,
|
||||
addressStateLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.ADDRESS.labelBySubField
|
||||
.addressState,
|
||||
addressCountryLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.ADDRESS.labelBySubField
|
||||
.addressCountry,
|
||||
} satisfies Omit<
|
||||
CompositeFieldLabels<FieldAddressValue>,
|
||||
'addressLatLabel' | 'addressLngLabel'
|
||||
>,
|
||||
[FieldMetadataType.LINKS]: {
|
||||
primaryLinkUrlLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.LINKS.labelBySubField
|
||||
.primaryLinkUrl,
|
||||
primaryLinkLabelLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.LINKS.labelBySubField
|
||||
.primaryLinkLabel,
|
||||
secondaryLinksLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.LINKS.labelBySubField
|
||||
.secondaryLinks,
|
||||
} satisfies CompositeFieldLabels<FieldLinksValue>,
|
||||
[FieldMetadataType.EMAILS]: {
|
||||
primaryEmailLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.EMAILS.labelBySubField.primaryEmail,
|
||||
additionalEmailsLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.EMAILS.labelBySubField
|
||||
.additionalEmails,
|
||||
} satisfies CompositeFieldLabels<FieldEmailsValue>,
|
||||
[FieldMetadataType.PHONES]: {
|
||||
primaryPhoneCountryCodeLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.PHONES.labelBySubField
|
||||
.primaryPhoneCountryCode,
|
||||
primaryPhoneNumberLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.PHONES.labelBySubField
|
||||
.primaryPhoneNumber,
|
||||
primaryPhoneCallingCodeLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.PHONES.labelBySubField
|
||||
.primaryPhoneCallingCode,
|
||||
additionalPhonesLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.PHONES.labelBySubField
|
||||
.additionalPhones,
|
||||
} satisfies CompositeFieldLabels<FieldPhonesValue>,
|
||||
[FieldMetadataType.RICH_TEXT_V2]: {
|
||||
blocknoteLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.RICH_TEXT_V2.labelBySubField
|
||||
.blocknote,
|
||||
markdownLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.RICH_TEXT_V2.labelBySubField
|
||||
.markdown,
|
||||
} satisfies CompositeFieldLabels<FieldRichTextV2Value>,
|
||||
[FieldMetadataType.ACTOR]: {
|
||||
sourceLabel:
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.ACTOR.labelBySubField.source,
|
||||
nameLabel: SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS.ACTOR.labelBySubField.name,
|
||||
} satisfies Partial<CompositeFieldLabels<FieldActorValue>>,
|
||||
};
|
||||
@ -1,8 +1,8 @@
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
|
||||
import { COMPOSITE_FIELD_IMPORT_LABELS } from '@/object-record/spreadsheet-import/constants/CompositeFieldImportLabels';
|
||||
import { AvailableFieldForImport } from '@/object-record/spreadsheet-import/types/AvailableFieldForImport';
|
||||
import { getSpreadSheetFieldValidationDefinitions } from '@/object-record/spreadsheet-import/utils/getSpreadSheetFieldValidationDefinitions';
|
||||
import { SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsCompositeFieldTypeConfigs';
|
||||
import { CompositeFieldType } from '@/settings/data-model/types/CompositeFieldType';
|
||||
import { useIcons } from 'twenty-ui/display';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
@ -36,8 +36,9 @@ export const useBuildAvailableFieldsForImport = () => {
|
||||
fieldMetadataItem: FieldMetadataItem,
|
||||
fieldType: CompositeFieldType,
|
||||
) => {
|
||||
Object.entries(COMPOSITE_FIELD_IMPORT_LABELS[fieldType]).forEach(
|
||||
([subFieldKey, subFieldLabel]) => {
|
||||
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[fieldType].subFields.forEach(
|
||||
({ subFieldName, subFieldLabel, isImportable }) => {
|
||||
if (!isImportable) return;
|
||||
const label = `${fieldMetadataItem.label} / ${subFieldLabel}`;
|
||||
|
||||
availableFieldsForImport.push(
|
||||
@ -48,7 +49,7 @@ export const useBuildAvailableFieldsForImport = () => {
|
||||
getSpreadSheetFieldValidationDefinitions(
|
||||
fieldMetadataItem.type,
|
||||
label,
|
||||
subFieldKey,
|
||||
subFieldName,
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
@ -2,11 +2,12 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
|
||||
import { useCreateManyRecords } from '@/object-record/hooks/useCreateManyRecords';
|
||||
import { useBuildAvailableFieldsForImport } from '@/object-record/spreadsheet-import/hooks/useBuildAvailableFieldsForImport';
|
||||
import { buildRecordFromImportedStructuredRow } from '@/object-record/spreadsheet-import/utils/buildRecordFromImportedStructuredRow';
|
||||
import { spreadsheetImportFilterAvailableFieldMetadataItems } from '@/object-record/spreadsheet-import/utils/spreadsheetImportFilterAvailableFieldMetadataItems.ts';
|
||||
import { useOpenSpreadsheetImportDialog } from '@/spreadsheet-import/hooks/useOpenSpreadsheetImportDialog';
|
||||
import { SpreadsheetImportDialogOptions } from '@/spreadsheet-import/types';
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { FieldMetadataType, RelationType } from '~/generated-metadata/graphql';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const useOpenObjectRecordsSpreadsheetImportDialog = (
|
||||
objectNameSingular: string,
|
||||
@ -30,22 +31,20 @@ export const useOpenObjectRecordsSpreadsheetImportDialog = (
|
||||
'fields' | 'isOpen' | 'onClose'
|
||||
>,
|
||||
) => {
|
||||
const availableFieldMetadataItems = objectMetadataItem.fields
|
||||
.filter(
|
||||
(fieldMetadataItem) =>
|
||||
fieldMetadataItem.isActive &&
|
||||
(!fieldMetadataItem.isSystem || fieldMetadataItem.name === 'id') &&
|
||||
fieldMetadataItem.name !== 'createdAt' &&
|
||||
fieldMetadataItem.name !== 'updatedAt' &&
|
||||
(fieldMetadataItem.type !== FieldMetadataType.RELATION ||
|
||||
fieldMetadataItem.relation?.type === RelationType.MANY_TO_ONE),
|
||||
)
|
||||
.sort((fieldMetadataItemA, fieldMetadataItemB) =>
|
||||
fieldMetadataItemA.name.localeCompare(fieldMetadataItemB.name),
|
||||
//All fields that can be imported (included matchable and auto-filled)
|
||||
const availableFieldMetadataItemsToImport =
|
||||
spreadsheetImportFilterAvailableFieldMetadataItems(
|
||||
objectMetadataItem.fields,
|
||||
);
|
||||
|
||||
const availableFields = buildAvailableFieldsForImport(
|
||||
availableFieldMetadataItems,
|
||||
const availableFieldMetadataItemsForMatching =
|
||||
availableFieldMetadataItemsToImport.filter(
|
||||
(fieldMetadataItem) =>
|
||||
fieldMetadataItem.type !== FieldMetadataType.ACTOR,
|
||||
);
|
||||
|
||||
const availableFieldsForMatching = buildAvailableFieldsForImport(
|
||||
availableFieldMetadataItemsForMatching,
|
||||
);
|
||||
|
||||
openSpreadsheetImportDialog({
|
||||
@ -55,7 +54,7 @@ export const useOpenObjectRecordsSpreadsheetImportDialog = (
|
||||
const fieldMapping: Record<string, any> =
|
||||
buildRecordFromImportedStructuredRow({
|
||||
importedStructuredRow: record,
|
||||
fields: availableFieldMetadataItems,
|
||||
fields: availableFieldMetadataItemsToImport,
|
||||
});
|
||||
|
||||
return fieldMapping;
|
||||
@ -70,8 +69,8 @@ export const useOpenObjectRecordsSpreadsheetImportDialog = (
|
||||
});
|
||||
}
|
||||
},
|
||||
fields: availableFields,
|
||||
availableFieldMetadataItems,
|
||||
fields: availableFieldsForMatching,
|
||||
availableFieldMetadataItems: availableFieldMetadataItemsToImport,
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ import {
|
||||
FieldPhonesValue,
|
||||
FieldRichTextV2Value,
|
||||
} from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { COMPOSITE_FIELD_IMPORT_LABELS } from '@/object-record/spreadsheet-import/constants/CompositeFieldImportLabels';
|
||||
import { COMPOSITE_FIELD_SUB_FIELD_LABELS } from '@/settings/data-model/constants/CompositeFieldSubFieldLabel';
|
||||
import { ImportedStructuredRow } from '@/spreadsheet-import/types';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@ -85,25 +85,35 @@ export const buildRecordFromImportedStructuredRow = ({
|
||||
|
||||
const {
|
||||
ADDRESS: {
|
||||
addressCityLabel,
|
||||
addressCountryLabel,
|
||||
addressPostcodeLabel,
|
||||
addressStateLabel,
|
||||
addressStreet1Label,
|
||||
addressStreet2Label,
|
||||
addressCity: addressCityLabel,
|
||||
addressCountry: addressCountryLabel,
|
||||
addressPostcode: addressPostcodeLabel,
|
||||
addressState: addressStateLabel,
|
||||
addressStreet1: addressStreet1Label,
|
||||
addressStreet2: addressStreet2Label,
|
||||
},
|
||||
CURRENCY: {
|
||||
amountMicros: amountMicrosLabel,
|
||||
currencyCode: currencyCodeLabel,
|
||||
},
|
||||
FULL_NAME: { firstName: firstNameLabel, lastName: lastNameLabel },
|
||||
LINKS: {
|
||||
primaryLinkUrl: primaryLinkUrlLabel,
|
||||
primaryLinkLabel: primaryLinkLabelLabel,
|
||||
secondaryLinks: secondaryLinksLabel,
|
||||
},
|
||||
EMAILS: {
|
||||
primaryEmail: primaryEmailLabel,
|
||||
additionalEmails: additionalEmailsLabel,
|
||||
},
|
||||
CURRENCY: { amountMicrosLabel, currencyCodeLabel },
|
||||
FULL_NAME: { firstNameLabel, lastNameLabel },
|
||||
LINKS: { primaryLinkUrlLabel, primaryLinkLabelLabel, secondaryLinksLabel },
|
||||
EMAILS: { primaryEmailLabel, additionalEmailsLabel },
|
||||
PHONES: {
|
||||
primaryPhoneNumberLabel,
|
||||
primaryPhoneCountryCodeLabel,
|
||||
primaryPhoneCallingCodeLabel,
|
||||
additionalPhonesLabel,
|
||||
primaryPhoneNumber: primaryPhoneNumberLabel,
|
||||
primaryPhoneCountryCode: primaryPhoneCountryCodeLabel,
|
||||
primaryPhoneCallingCode: primaryPhoneCallingCodeLabel,
|
||||
additionalPhones: additionalPhonesLabel,
|
||||
},
|
||||
RICH_TEXT_V2: { blocknoteLabel, markdownLabel },
|
||||
} = COMPOSITE_FIELD_IMPORT_LABELS;
|
||||
RICH_TEXT_V2: { blocknote: blocknoteLabel, markdown: markdownLabel },
|
||||
} = COMPOSITE_FIELD_SUB_FIELD_LABELS;
|
||||
|
||||
for (const field of fields) {
|
||||
const importedFieldValue = importedStructuredRow[field.name];
|
||||
@ -274,10 +284,18 @@ export const buildRecordFromImportedStructuredRow = ({
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FieldMetadataType.UUID:
|
||||
if (
|
||||
isDefined(importedFieldValue) &&
|
||||
isNonEmptyString(importedFieldValue)
|
||||
) {
|
||||
recordToBuild[field.name] = importedFieldValue;
|
||||
}
|
||||
break;
|
||||
case FieldMetadataType.RELATION:
|
||||
if (
|
||||
isDefined(importedFieldValue) &&
|
||||
(isNonEmptyString(importedFieldValue) || importedFieldValue !== false)
|
||||
isNonEmptyString(importedFieldValue)
|
||||
) {
|
||||
recordToBuild[field.name + 'Id'] = importedFieldValue;
|
||||
}
|
||||
|
||||
@ -35,14 +35,14 @@ export const getSpreadSheetFieldValidationDefinitions = (
|
||||
];
|
||||
case FieldMetadataType.CURRENCY:
|
||||
switch (subFieldKey) {
|
||||
case 'amountMicrosLabel':
|
||||
case 'amountMicros':
|
||||
return [getNumberValidationDefinition(fieldName)];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
case FieldMetadataType.EMAILS:
|
||||
switch (subFieldKey) {
|
||||
case 'primaryEmailLabel':
|
||||
case 'primaryEmail':
|
||||
return [
|
||||
{
|
||||
rule: 'function',
|
||||
@ -51,7 +51,7 @@ export const getSpreadSheetFieldValidationDefinitions = (
|
||||
level: 'error',
|
||||
},
|
||||
];
|
||||
case 'additionalEmailsLabel':
|
||||
case 'additionalEmails':
|
||||
return [
|
||||
{
|
||||
rule: 'function',
|
||||
@ -77,7 +77,7 @@ export const getSpreadSheetFieldValidationDefinitions = (
|
||||
}
|
||||
case FieldMetadataType.LINKS:
|
||||
switch (subFieldKey) {
|
||||
case 'primaryLinkUrlLabel':
|
||||
case 'primaryLinkUrl':
|
||||
return [
|
||||
{
|
||||
rule: 'function',
|
||||
@ -89,7 +89,7 @@ export const getSpreadSheetFieldValidationDefinitions = (
|
||||
level: 'error',
|
||||
},
|
||||
];
|
||||
case 'secondaryLinksLabel':
|
||||
case 'secondaryLinks':
|
||||
return [
|
||||
{
|
||||
rule: 'function',
|
||||
@ -139,7 +139,7 @@ export const getSpreadSheetFieldValidationDefinitions = (
|
||||
];
|
||||
case FieldMetadataType.PHONES:
|
||||
switch (subFieldKey) {
|
||||
case 'primaryPhoneNumberLabel':
|
||||
case 'primaryPhoneNumber':
|
||||
return [
|
||||
{
|
||||
rule: 'regex',
|
||||
@ -148,7 +148,7 @@ export const getSpreadSheetFieldValidationDefinitions = (
|
||||
level: 'error',
|
||||
},
|
||||
];
|
||||
case 'additionalPhonesLabel':
|
||||
case 'additionalPhones':
|
||||
return [
|
||||
{
|
||||
rule: 'function',
|
||||
|
||||
@ -1,15 +1,19 @@
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { COMPOSITE_FIELD_IMPORT_LABELS } from '@/object-record/spreadsheet-import/constants/CompositeFieldImportLabels';
|
||||
import { isCompositeFieldType } from '@/object-record/object-filter-dropdown/utils/isCompositeFieldType';
|
||||
import { COMPOSITE_FIELD_SUB_FIELD_LABELS } from '@/settings/data-model/constants/CompositeFieldSubFieldLabel';
|
||||
|
||||
export const getSubFieldOptionKey = (
|
||||
fieldMetadataItem: FieldMetadataItem,
|
||||
subFieldName: string,
|
||||
) => {
|
||||
const subFieldNameLabelKey = `${subFieldName}Label`;
|
||||
if (!isCompositeFieldType(fieldMetadataItem.type)) {
|
||||
throw new Error(
|
||||
`getSubFieldOptionKey can only be called for composite field types. Received: ${fieldMetadataItem.type}`,
|
||||
);
|
||||
}
|
||||
|
||||
const subFieldLabel = (
|
||||
(COMPOSITE_FIELD_IMPORT_LABELS as any)[fieldMetadataItem.type] as any
|
||||
)[subFieldNameLabelKey];
|
||||
const subFieldLabel =
|
||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[fieldMetadataItem.type][subFieldName];
|
||||
|
||||
const subFieldKey = `${subFieldLabel} (${fieldMetadataItem.name})`;
|
||||
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { RelationType } from '~/generated-metadata/graphql';
|
||||
|
||||
export const spreadsheetImportFilterAvailableFieldMetadataItems = (
|
||||
fields: FieldMetadataItem[],
|
||||
) => {
|
||||
return fields
|
||||
.filter(
|
||||
(fieldMetadataItem) =>
|
||||
fieldMetadataItem.isActive &&
|
||||
(!fieldMetadataItem.isSystem || fieldMetadataItem.name === 'id') &&
|
||||
fieldMetadataItem.name !== 'createdAt' &&
|
||||
fieldMetadataItem.name !== 'updatedAt' &&
|
||||
(![FieldMetadataType.RELATION, FieldMetadataType.RICH_TEXT].includes(
|
||||
fieldMetadataItem.type,
|
||||
) ||
|
||||
fieldMetadataItem.relation?.type === RelationType.MANY_TO_ONE),
|
||||
)
|
||||
.sort((fieldMetadataItemA, fieldMetadataItemB) =>
|
||||
fieldMetadataItemA.name.localeCompare(fieldMetadataItemB.name),
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user