Improve CSV import sub-field selection (#11601)

This PR adds a better UX for selecting sub-fields when importing CSV
files.

Before : 

<img width="395" alt="image"
src="https://github.com/user-attachments/assets/5a599e7d-ed07-4531-8306-9d70e7cfa37d"
/>

After : 

<img width="298" alt="image"
src="https://github.com/user-attachments/assets/2be8a1df-d089-4341-970e-6db2b269141e"
/>

<img width="296" alt="image"
src="https://github.com/user-attachments/assets/584285f4-4e71-4abd-9adf-11819cab0dc5"
/>

- A util `getSubFieldOptionKey` has been made to be able to reference
the sub field in the `options` object of the spreadsheet import.
- New components have been created :
`MatchColumnSelectFieldSelectDropdownContent`,
`MatchColumnSelectSubFieldSelectDropdownContent` and
`MatchColumnSelectV2`
- Extracted the hard-coded option do not import into a constant
`DO_NOT_IMPORT_OPTION_KEY`
- Passed `availableFieldMetadataItems` to spreadsheet global options so
it's available anywhere in the hierarchy of components.

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
Co-authored-by: Charles Bochet <charlesBochet@users.noreply.github.com>
This commit is contained in:
Lucas Bordeau
2025-04-16 15:08:24 +02:00
committed by GitHub
parent b1c0613514
commit bf704bd1bc
17 changed files with 409 additions and 302 deletions

View File

@ -1,4 +1,5 @@
import {
FieldActorValue,
FieldAddressValue,
FieldCurrencyValue,
FieldEmailsValue,
@ -46,5 +47,5 @@ export const COMPOSITE_FIELD_IMPORT_LABELS = {
} satisfies Partial<CompositeFieldLabels<FieldRichTextV2Value>>,
[FieldMetadataType.ACTOR]: {
sourceLabel: 'Source',
},
} satisfies Partial<CompositeFieldLabels<FieldActorValue>>,
};

View File

@ -3,8 +3,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 { FieldMetadataType } from '~/generated-metadata/graphql';
import { useIcons } from 'twenty-ui/display';
import { FieldMetadataType } from '~/generated-metadata/graphql';
type CompositeFieldType = keyof typeof COMPOSITE_FIELD_IMPORT_LABELS;
@ -42,17 +42,17 @@ export const useBuildAvailableFieldsForImport = () => {
validationTypeResolver?: ValidationTypeResolver,
) => {
Object.entries(COMPOSITE_FIELD_IMPORT_LABELS[fieldType]).forEach(
([key, fieldLabel]) => {
const label = `${fieldLabel} (${fieldMetadataItem.label})`;
([key, subFieldLabel]) => {
const label = `${fieldMetadataItem.label} / ${subFieldLabel}`;
// Use the custom validation type if provided, otherwise use the field's type
const validationType = validationTypeResolver
? validationTypeResolver(key, fieldLabel)
? validationTypeResolver(key, subFieldLabel)
: fieldMetadataItem.type;
availableFieldsForImport.push(
createBaseField(fieldMetadataItem, {
label,
key: `${fieldLabel} (${fieldMetadataItem.name})`,
key: `${subFieldLabel} (${fieldMetadataItem.name})`,
fieldValidationDefinitions:
getSpreadSheetFieldValidationDefinitions(validationType, label),
}),
@ -137,6 +137,12 @@ export const useBuildAvailableFieldsForImport = () => {
currencyValidationResolver,
);
},
[FieldMetadataType.ACTOR]: (fieldMetadataItem) => {
handleCompositeFieldWithLabels(
fieldMetadataItem,
FieldMetadataType.ACTOR,
);
},
[FieldMetadataType.RELATION]: (fieldMetadataItem) => {
const label = `${fieldMetadataItem.label} (ID)`;
availableFieldsForImport.push(

View File

@ -74,6 +74,7 @@ export const useOpenObjectRecordsSpreadsheetImportDialog = (
}
},
fields: availableFields,
availableFieldMetadataItems,
});
};

View File

@ -0,0 +1,17 @@
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { COMPOSITE_FIELD_IMPORT_LABELS } from '@/object-record/spreadsheet-import/constants/CompositeFieldImportLabels';
export const getSubFieldOptionKey = (
fieldMetadataItem: FieldMetadataItem,
subFieldName: string,
) => {
const subFieldNameLabelKey = `${subFieldName}Label`;
const subFieldLabel = (
(COMPOSITE_FIELD_IMPORT_LABELS as any)[fieldMetadataItem.type] as any
)[subFieldNameLabelKey];
const subFieldKey = `${subFieldLabel} (${fieldMetadataItem.name})`;
return subFieldKey;
};