import type { CustomField, CustomFieldForm, CustomFieldType, DataExtensionState, FieldDraft, FieldManagement, FieldTypeOption, NonReferenceField, ReportBI, TranslationsKeys, } from '@wix/bex-core'; import { runInAction } from 'mobx'; export const CUSTOM_FIELD_TYPE_TO_PATTERNS: Record< CustomFieldType, NonReferenceField['type'] > = { shortText: 'SHORT_TEXT', longText: 'LONG_TEXT', url: 'URL', date: 'DATE', dateTime: 'DATETIME', integer: 'NUMBER', decimal: 'NUMBER', checkbox: 'BOOLEAN', dropdown: 'SHORT_TEXT', multiSelect: 'ARRAY', files: 'DOCUMENT', }; export const toPatternsFieldType = ( type: CustomFieldType, ): NonReferenceField['type'] => CUSTOM_FIELD_TYPE_TO_PATTERNS[type] ?? 'UNKNOWN'; const isCustomFieldType = (type: string): type is CustomFieldType => type in CUSTOM_FIELD_TYPE_TO_PATTERNS; const CREATABLE_TYPES: readonly { id: CustomFieldType; labelKey: TranslationsKeys; namePlaceholderKey: TranslationsKeys; }[] = [ { id: 'shortText', labelKey: 'cairo.customFields.fieldType.shortText', namePlaceholderKey: 'cairo.customFields.fieldType.shortText.Name.placeholder', }, { id: 'longText', labelKey: 'cairo.customFields.fieldType.longText', namePlaceholderKey: 'cairo.customFields.fieldType.longText.Name.placeholder', }, { id: 'date', labelKey: 'cairo.customFields.fieldType.date', namePlaceholderKey: 'cairo.customFields.fieldType.date.Name.placeholder', }, { id: 'dateTime', labelKey: 'cairo.customFields.fieldType.dateAndTime', namePlaceholderKey: 'cairo.customFields.fieldType.dateAndTime.Name.placeholder', }, { id: 'integer', labelKey: 'cairo.customFields.fieldType.numberInteger', namePlaceholderKey: 'cairo.customFields.fieldType.numberInteger.Name.placeholder', }, { id: 'decimal', labelKey: 'cairo.customFields.fieldType.numberDecimal', namePlaceholderKey: 'cairo.customFields.fieldType.numberDecimal.Name.placeholder', }, { id: 'checkbox', labelKey: 'cairo.customFields.fieldType.checkbox', namePlaceholderKey: 'cairo.customFields.fieldType.checkbox.Name.placeholder', }, { id: 'url', labelKey: 'cairo.customFields.fieldType.url', namePlaceholderKey: 'cairo.customFields.placeholder.url', }, ]; export interface DataExtensionFieldManagementParams { dataExtension: DataExtensionState; reportBi: ReportBI; } export const dataExtensionFieldManagement = ({ dataExtension, reportBi, }: DataExtensionFieldManagementParams): FieldManagement => { const customFieldFor = (id: string): CustomField | undefined => dataExtension.availableCustomFields.find((f) => f.id === id); const toCustomFieldForm = (draft: FieldDraft): CustomFieldForm => ({ ...draft, type: draft.type && isCustomFieldType(draft.type) ? draft.type : undefined, }); const upsertField = async (draft: FieldDraft) => { const { dataExtensionSchema } = await dataExtension.dataExtensionService.addCustomField({ form: toCustomFieldForm(draft), schema: dataExtension.userSchema, fqdn: dataExtension.fqdnString, filterable: dataExtension.filterable, }); runInAction(() => { if (dataExtensionSchema) { dataExtension._upsertSchema(dataExtensionSchema); } }); }; return { get canAddFields() { return !dataExtension.disableUserDefinedWriting; }, get addFieldDisabled() { return dataExtension.disableAddCustomField; }, get addFieldDisabledHint() { return dataExtension.disableAddCustomFieldContent || undefined; }, canEditField: (field) => customFieldFor(field.id)?.editable ?? false, deleteField: async (fieldId, origin) => { await dataExtension.deleteField({ id: fieldId, origin, reportBi, }); }, // Lazy: translate on access (after the container's i18n has loaded), not at // construction — the source is built before `load()` runs initTask, so an // eager map would freeze the raw translation keys. get creatableFieldTypes(): FieldTypeOption[] { const t = dataExtension.container.translate; return CREATABLE_TYPES.map((ft) => ({ id: ft.id, label: t(ft.labelKey), namePlaceholder: t(ft.namePlaceholderKey), patternsType: toPatternsFieldType(ft.id), })); }, get existingFieldKeys() { // All user fields, not just the available ones: duplicate-key detection // must also catch keys of fields that exist but aren't currently shown. return dataExtension.allUserCustomFields.map((f) => f.id); }, get maxReached() { return dataExtension.isReachedMaxCustomFields; }, get permissions() { return dataExtension.defaultPermissions; }, get supportsPii() { return dataExtension.containsPii; }, addField: upsertField, editField: (_fieldId, draft) => upsertField(draft), getFieldDraft: (fieldId) => dataExtension.extractFieldValuesFromSchema(fieldId), }; };