Import - add duplicate check on import (#12810)
<img width="1217" alt="Screenshot 2025-06-24 at 11 43 03" src="https://github.com/user-attachments/assets/de2bc12e-5e25-484f-a034-f52b0f237a3e" /> Test : - Add duplicate on id or on primaryEmail for people or primaryUrlLink on companies closes https://github.com/twentyhq/core-team-issues/issues/909
This commit is contained in:
@ -3,6 +3,7 @@ import { useBatchCreateManyRecords } from '@/object-record/hooks/useBatchCreateM
|
|||||||
import { useBuildAvailableFieldsForImport } from '@/object-record/spreadsheet-import/hooks/useBuildAvailableFieldsForImport';
|
import { useBuildAvailableFieldsForImport } from '@/object-record/spreadsheet-import/hooks/useBuildAvailableFieldsForImport';
|
||||||
import { buildRecordFromImportedStructuredRow } from '@/object-record/spreadsheet-import/utils/buildRecordFromImportedStructuredRow';
|
import { buildRecordFromImportedStructuredRow } from '@/object-record/spreadsheet-import/utils/buildRecordFromImportedStructuredRow';
|
||||||
import { spreadsheetImportFilterAvailableFieldMetadataItems } from '@/object-record/spreadsheet-import/utils/spreadsheetImportFilterAvailableFieldMetadataItems.ts';
|
import { spreadsheetImportFilterAvailableFieldMetadataItems } from '@/object-record/spreadsheet-import/utils/spreadsheetImportFilterAvailableFieldMetadataItems.ts';
|
||||||
|
import { spreadsheetImportGetUnicityRowHook } from '@/object-record/spreadsheet-import/utils/spreadsheetImportGetUnicityRowHook';
|
||||||
import { SpreadsheetImportCreateRecordsBatchSize } from '@/spreadsheet-import/constants/SpreadsheetImportCreateRecordsBatchSize';
|
import { SpreadsheetImportCreateRecordsBatchSize } from '@/spreadsheet-import/constants/SpreadsheetImportCreateRecordsBatchSize';
|
||||||
import { useOpenSpreadsheetImportDialog } from '@/spreadsheet-import/hooks/useOpenSpreadsheetImportDialog';
|
import { useOpenSpreadsheetImportDialog } from '@/spreadsheet-import/hooks/useOpenSpreadsheetImportDialog';
|
||||||
import { spreadsheetImportCreatedRecordsProgressState } from '@/spreadsheet-import/states/spreadsheetImportCreatedRecordsProgressState';
|
import { spreadsheetImportCreatedRecordsProgressState } from '@/spreadsheet-import/states/spreadsheetImportCreatedRecordsProgressState';
|
||||||
@ -88,6 +89,7 @@ export const useOpenObjectRecordsSpreadsheetImportDialog = (
|
|||||||
onAbortSubmit: () => {
|
onAbortSubmit: () => {
|
||||||
abortController.abort();
|
abortController.abort();
|
||||||
},
|
},
|
||||||
|
rowHook: spreadsheetImportGetUnicityRowHook(objectMetadataItem),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,175 @@
|
|||||||
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
|
import { spreadsheetImportGetUnicityRowHook } from '@/object-record/spreadsheet-import/utils/spreadsheetImportGetUnicityRowHook';
|
||||||
|
import { ImportedStructuredRow } from '@/spreadsheet-import/types';
|
||||||
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
|
import { IndexType } from '~/generated-metadata/graphql';
|
||||||
|
import { getMockCompanyObjectMetadataItem } from '~/testing/mock-data/companies';
|
||||||
|
|
||||||
|
describe('spreadsheetImportGetUnicityRowHook', () => {
|
||||||
|
const baseMockCompany = getMockCompanyObjectMetadataItem();
|
||||||
|
|
||||||
|
const nameField = baseMockCompany.fields.find(
|
||||||
|
(field) => field.name === 'name',
|
||||||
|
);
|
||||||
|
|
||||||
|
const domainNameField = baseMockCompany.fields.find(
|
||||||
|
(field) => field.name === 'domainName',
|
||||||
|
);
|
||||||
|
|
||||||
|
const employeesField = baseMockCompany.fields.find(
|
||||||
|
(field) => field.name === 'employees',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (
|
||||||
|
!isDefined(nameField) ||
|
||||||
|
!isDefined(domainNameField) ||
|
||||||
|
!isDefined(employeesField)
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
'Name, domainName or employees field not found in company metadata',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockObjectMetadataItem: ObjectMetadataItem = {
|
||||||
|
...baseMockCompany,
|
||||||
|
indexMetadatas: [
|
||||||
|
{
|
||||||
|
id: 'unique-name-index',
|
||||||
|
name: 'unique_name_idx',
|
||||||
|
indexType: IndexType.BTREE,
|
||||||
|
isUnique: true,
|
||||||
|
createdAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
indexFieldMetadatas: [
|
||||||
|
{
|
||||||
|
id: 'index-field-2',
|
||||||
|
fieldMetadataId: domainNameField.id,
|
||||||
|
order: 0,
|
||||||
|
createdAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'unique-domain-name-index',
|
||||||
|
name: 'unique_domain_name_idx',
|
||||||
|
indexType: IndexType.BTREE,
|
||||||
|
isUnique: true,
|
||||||
|
createdAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
indexFieldMetadatas: [
|
||||||
|
{
|
||||||
|
id: 'index-field-1',
|
||||||
|
fieldMetadataId: nameField.id,
|
||||||
|
order: 0,
|
||||||
|
createdAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'index-field-3',
|
||||||
|
fieldMetadataId: employeesField.id,
|
||||||
|
order: 1,
|
||||||
|
createdAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should return row with error if row is not unique - index on composite field', () => {
|
||||||
|
const hook = spreadsheetImportGetUnicityRowHook(mockObjectMetadataItem);
|
||||||
|
|
||||||
|
const testData: ImportedStructuredRow<string>[] = [
|
||||||
|
{ 'Link URL (domainName)': 'duplicaTe.com', id: '1' },
|
||||||
|
{ 'Link URL (domainName)': 'duplicate.com ', id: '2' },
|
||||||
|
{ 'Link URL (domainName)': 'other.com', id: '3' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const addErrorMock = jest.fn();
|
||||||
|
|
||||||
|
const result = hook(testData[1], addErrorMock, testData);
|
||||||
|
|
||||||
|
expect(addErrorMock).toHaveBeenCalledWith('Link URL (domainName)', {
|
||||||
|
message:
|
||||||
|
'This Link URL (domainName) value already exists in your import data',
|
||||||
|
level: 'error',
|
||||||
|
});
|
||||||
|
expect(result).toBe(testData[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return row with error if row is not unique - index on id', () => {
|
||||||
|
const hook = spreadsheetImportGetUnicityRowHook(mockObjectMetadataItem);
|
||||||
|
|
||||||
|
const testData: ImportedStructuredRow<string>[] = [
|
||||||
|
{ 'Link URL (domainName)': 'test.com', id: '1' },
|
||||||
|
{ 'Link URL (domainName)': 'test2.com', id: '1' },
|
||||||
|
{ 'Link URL (domainName)': 'test3.com', id: '3' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const addErrorMock = jest.fn();
|
||||||
|
|
||||||
|
const result = hook(testData[1], addErrorMock, testData);
|
||||||
|
|
||||||
|
expect(addErrorMock).toHaveBeenCalledWith('id', {
|
||||||
|
message: 'This id value already exists in your import data',
|
||||||
|
level: 'error',
|
||||||
|
});
|
||||||
|
expect(result).toBe(testData[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return row with error if row is not unique - multi fields index', () => {
|
||||||
|
const hook = spreadsheetImportGetUnicityRowHook(mockObjectMetadataItem);
|
||||||
|
|
||||||
|
const testData: ImportedStructuredRow<string>[] = [
|
||||||
|
{ name: 'test', employees: '100', id: '1' },
|
||||||
|
{ name: 'test', employees: '100', id: '2' },
|
||||||
|
{ name: 'test', employees: '101', id: '3' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const addErrorMock = jest.fn();
|
||||||
|
|
||||||
|
const result = hook(testData[1], addErrorMock, testData);
|
||||||
|
|
||||||
|
expect(addErrorMock).toHaveBeenCalledWith('name', {
|
||||||
|
message: 'This name value already exists in your import data',
|
||||||
|
level: 'error',
|
||||||
|
});
|
||||||
|
expect(addErrorMock).toHaveBeenCalledWith('employees', {
|
||||||
|
message: 'This employees value already exists in your import data',
|
||||||
|
level: 'error',
|
||||||
|
});
|
||||||
|
expect(result).toBe(testData[1]);
|
||||||
|
});
|
||||||
|
it('should not add error if row values are unique', () => {
|
||||||
|
const hook = spreadsheetImportGetUnicityRowHook(mockObjectMetadataItem);
|
||||||
|
|
||||||
|
const testData: ImportedStructuredRow<string>[] = [
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
'Link URL (domainName)': 'test.com',
|
||||||
|
employees: '100',
|
||||||
|
id: '1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
'Link URL (domainName)': 'test2.com',
|
||||||
|
employees: '101',
|
||||||
|
id: '2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'test',
|
||||||
|
'Link URL (domainName)': 'test3.com',
|
||||||
|
employees: '102',
|
||||||
|
id: '3',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const addErrorMock = jest.fn();
|
||||||
|
|
||||||
|
const result = hook(testData[1], addErrorMock, testData);
|
||||||
|
|
||||||
|
expect(addErrorMock).not.toHaveBeenCalled();
|
||||||
|
expect(result).toBe(testData[1]);
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||||
|
import { isCompositeFieldType } from '@/object-record/object-filter-dropdown/utils/isCompositeFieldType';
|
||||||
|
import { getSubFieldOptionKey } from '@/object-record/spreadsheet-import/utils/getSubFieldOptionKey';
|
||||||
|
import { SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsCompositeFieldTypeConfigs';
|
||||||
|
import {
|
||||||
|
ImportedStructuredRow,
|
||||||
|
SpreadsheetImportRowHook,
|
||||||
|
} from '@/spreadsheet-import/types';
|
||||||
|
import { isDefined } from 'twenty-shared/utils';
|
||||||
|
|
||||||
|
export const spreadsheetImportGetUnicityRowHook = (
|
||||||
|
objectMetadataItem: ObjectMetadataItem,
|
||||||
|
) => {
|
||||||
|
const uniqueConstraints = objectMetadataItem.indexMetadatas.filter(
|
||||||
|
(indexMetadata) => indexMetadata.isUnique,
|
||||||
|
);
|
||||||
|
|
||||||
|
const uniqueConstraintFields = [
|
||||||
|
['id'],
|
||||||
|
...uniqueConstraints.map((indexMetadata) =>
|
||||||
|
indexMetadata.indexFieldMetadatas.flatMap((indexField) => {
|
||||||
|
const field = objectMetadataItem.fields.find(
|
||||||
|
(objectField) => objectField.id === indexField.fieldMetadataId,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!field) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isCompositeFieldType(field.type)) {
|
||||||
|
const compositeTypeFieldConfig =
|
||||||
|
SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS[field.type];
|
||||||
|
|
||||||
|
const uniqueSubFields = compositeTypeFieldConfig.subFields.filter(
|
||||||
|
(subField) => subField.isIncludedInUniqueConstraint,
|
||||||
|
);
|
||||||
|
|
||||||
|
return uniqueSubFields.map((subField) =>
|
||||||
|
getSubFieldOptionKey(field, subField.subFieldName),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [field.name];
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
const rowHook: SpreadsheetImportRowHook<string> = (row, addError, table) => {
|
||||||
|
if (uniqueConstraints.length === 0) {
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
uniqueConstraintFields.forEach((uniqueConstraint) => {
|
||||||
|
const rowUniqueValues = getUniqueValues(row, uniqueConstraint);
|
||||||
|
|
||||||
|
const duplicateRows = table.filter(
|
||||||
|
(r) => getUniqueValues(r, uniqueConstraint) === rowUniqueValues,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (duplicateRows.length <= 1) {
|
||||||
|
return row;
|
||||||
|
}
|
||||||
|
|
||||||
|
uniqueConstraint.forEach((field) => {
|
||||||
|
if (isDefined(row[field])) {
|
||||||
|
addError(field, {
|
||||||
|
message: `This ${field} value already exists in your import data`,
|
||||||
|
level: 'error',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return row;
|
||||||
|
};
|
||||||
|
|
||||||
|
return rowHook;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getUniqueValues = (
|
||||||
|
row: ImportedStructuredRow<string>,
|
||||||
|
uniqueConstraint: string[],
|
||||||
|
) => {
|
||||||
|
return uniqueConstraint
|
||||||
|
.map((field) => row?.[field]?.toString().trim().toLowerCase())
|
||||||
|
.join('');
|
||||||
|
};
|
||||||
@ -25,11 +25,14 @@ import {
|
|||||||
} from 'twenty-ui/display';
|
} from 'twenty-ui/display';
|
||||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
|
//TODO : isIncludedInUniqueConstraint refactor - https://github.com/twentyhq/core-team-issues/issues/1097
|
||||||
|
|
||||||
type CompositeSubFieldConfig<T> = {
|
type CompositeSubFieldConfig<T> = {
|
||||||
subFieldName: keyof T;
|
subFieldName: keyof T;
|
||||||
subFieldLabel: string;
|
subFieldLabel: string;
|
||||||
isImportable: boolean;
|
isImportable: boolean;
|
||||||
isFilterable: boolean;
|
isFilterable: boolean;
|
||||||
|
isIncludedInUniqueConstraint: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SettingsCompositeFieldTypeConfig<T> = SettingsFieldTypeConfig<T> & {
|
export type SettingsCompositeFieldTypeConfig<T> = SettingsFieldTypeConfig<T> & {
|
||||||
@ -54,6 +57,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.amountMicros,
|
.amountMicros,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'currencyCode',
|
subFieldName: 'currencyCode',
|
||||||
@ -62,6 +66,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.currencyCode,
|
.currencyCode,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
exampleValues: [
|
exampleValues: [
|
||||||
@ -91,6 +96,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.primaryEmail,
|
.primaryEmail,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'additionalEmails',
|
subFieldName: 'additionalEmails',
|
||||||
@ -99,6 +105,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.additionalEmails,
|
.additionalEmails,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
exampleValues: [
|
exampleValues: [
|
||||||
@ -132,6 +139,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.primaryLinkUrl,
|
.primaryLinkUrl,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'primaryLinkLabel',
|
subFieldName: 'primaryLinkLabel',
|
||||||
@ -140,6 +148,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.primaryLinkLabel,
|
.primaryLinkLabel,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'secondaryLinks',
|
subFieldName: 'secondaryLinks',
|
||||||
@ -148,6 +157,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.secondaryLinks,
|
.secondaryLinks,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
exampleValues: [
|
exampleValues: [
|
||||||
@ -180,6 +190,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.primaryPhoneCallingCode,
|
.primaryPhoneCallingCode,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'primaryPhoneCountryCode',
|
subFieldName: 'primaryPhoneCountryCode',
|
||||||
@ -188,6 +199,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.primaryPhoneCountryCode,
|
.primaryPhoneCountryCode,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: false,
|
isFilterable: false,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'primaryPhoneNumber',
|
subFieldName: 'primaryPhoneNumber',
|
||||||
@ -196,6 +208,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.primaryPhoneNumber,
|
.primaryPhoneNumber,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'additionalPhones',
|
subFieldName: 'additionalPhones',
|
||||||
@ -204,6 +217,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.additionalPhones,
|
.additionalPhones,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
exampleValues: [
|
exampleValues: [
|
||||||
@ -244,6 +258,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.firstName,
|
.firstName,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'lastName',
|
subFieldName: 'lastName',
|
||||||
@ -252,6 +267,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.lastName,
|
.lastName,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
exampleValues: [
|
exampleValues: [
|
||||||
@ -272,6 +288,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.addressStreet1,
|
.addressStreet1,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'addressStreet2',
|
subFieldName: 'addressStreet2',
|
||||||
@ -280,6 +297,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.addressStreet2,
|
.addressStreet2,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'addressCity',
|
subFieldName: 'addressCity',
|
||||||
@ -288,6 +306,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.addressCity,
|
.addressCity,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'addressState',
|
subFieldName: 'addressState',
|
||||||
@ -296,6 +315,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.addressState,
|
.addressState,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'addressCountry',
|
subFieldName: 'addressCountry',
|
||||||
@ -304,6 +324,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.addressCountry,
|
.addressCountry,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'addressPostcode',
|
subFieldName: 'addressPostcode',
|
||||||
@ -312,6 +333,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.addressPostcode,
|
.addressPostcode,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'addressLat',
|
subFieldName: 'addressLat',
|
||||||
@ -320,6 +342,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.addressLat,
|
.addressLat,
|
||||||
isImportable: false,
|
isImportable: false,
|
||||||
isFilterable: false,
|
isFilterable: false,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'addressLng',
|
subFieldName: 'addressLng',
|
||||||
@ -328,6 +351,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.addressLng,
|
.addressLng,
|
||||||
isImportable: false,
|
isImportable: false,
|
||||||
isFilterable: false,
|
isFilterable: false,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
exampleValues: [
|
exampleValues: [
|
||||||
@ -375,6 +399,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].source,
|
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].source,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'name',
|
subFieldName: 'name',
|
||||||
@ -382,6 +407,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].name,
|
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].name,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: true,
|
isFilterable: true,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'workspaceMemberId',
|
subFieldName: 'workspaceMemberId',
|
||||||
@ -390,6 +416,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.workspaceMemberId,
|
.workspaceMemberId,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: false,
|
isFilterable: false,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'context',
|
subFieldName: 'context',
|
||||||
@ -397,6 +424,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].context,
|
COMPOSITE_FIELD_SUB_FIELD_LABELS[FieldMetadataType.ACTOR].context,
|
||||||
isImportable: true,
|
isImportable: true,
|
||||||
isFilterable: false,
|
isFilterable: false,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
exampleValues: [
|
exampleValues: [
|
||||||
@ -432,6 +460,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.blocknote,
|
.blocknote,
|
||||||
isImportable: false,
|
isImportable: false,
|
||||||
isFilterable: false,
|
isFilterable: false,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subFieldName: 'markdown',
|
subFieldName: 'markdown',
|
||||||
@ -440,6 +469,7 @@ export const SETTINGS_COMPOSITE_FIELD_TYPE_CONFIGS = {
|
|||||||
.markdown,
|
.markdown,
|
||||||
isImportable: false,
|
isImportable: false,
|
||||||
isFilterable: false,
|
isFilterable: false,
|
||||||
|
isIncludedInUniqueConstraint: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
exampleValues: [
|
exampleValues: [
|
||||||
|
|||||||
Reference in New Issue
Block a user