Migrate noteTarget and taskTarget to Morph. (#17476)
This PR migrates `noteTarget` and `taskTarget` to morph relations behind separate feature flags, following the Attachment/TimelineActivity pattern. It introduces the `IS_NOTE_TARGET_MIGRATED` and `IS_TASK_TARGET_MIGRATED` flags, updates standard field metadata and indexes to use morph relations, and adds two **1.17 workspace migrations** that: - rename `noteTarget.*Id` / `taskTarget.*Id` columns to `target*Id` - convert the corresponding field metadata to `MORPH_RELATION` with a shared `morphId` On the frontend, note/task target read and write paths switch to `target*Id` when the respective flag is enabled. Deleted targets are filtered on reload to prevent reappearing relations.
This commit is contained in:
@@ -1429,11 +1429,13 @@ export enum FeatureFlagKey {
|
||||
IS_JUNCTION_RELATIONS_ENABLED = 'IS_JUNCTION_RELATIONS_ENABLED',
|
||||
IS_MARKETPLACE_ENABLED = 'IS_MARKETPLACE_ENABLED',
|
||||
IS_NAVIGATION_MENU_ITEM_ENABLED = 'IS_NAVIGATION_MENU_ITEM_ENABLED',
|
||||
IS_NOTE_TARGET_MIGRATED = 'IS_NOTE_TARGET_MIGRATED',
|
||||
IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED',
|
||||
IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED = 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED',
|
||||
IS_RECORD_PAGE_LAYOUT_ENABLED = 'IS_RECORD_PAGE_LAYOUT_ENABLED',
|
||||
IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED = 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED',
|
||||
IS_SSE_DB_EVENTS_ENABLED = 'IS_SSE_DB_EVENTS_ENABLED',
|
||||
IS_TASK_TARGET_MIGRATED = 'IS_TASK_TARGET_MIGRATED',
|
||||
IS_TIMELINE_ACTIVITY_MIGRATED = 'IS_TIMELINE_ACTIVITY_MIGRATED',
|
||||
IS_UNIQUE_INDEXES_ENABLED = 'IS_UNIQUE_INDEXES_ENABLED'
|
||||
}
|
||||
|
||||
@@ -1401,11 +1401,13 @@ export enum FeatureFlagKey {
|
||||
IS_JUNCTION_RELATIONS_ENABLED = 'IS_JUNCTION_RELATIONS_ENABLED',
|
||||
IS_MARKETPLACE_ENABLED = 'IS_MARKETPLACE_ENABLED',
|
||||
IS_NAVIGATION_MENU_ITEM_ENABLED = 'IS_NAVIGATION_MENU_ITEM_ENABLED',
|
||||
IS_NOTE_TARGET_MIGRATED = 'IS_NOTE_TARGET_MIGRATED',
|
||||
IS_PUBLIC_DOMAIN_ENABLED = 'IS_PUBLIC_DOMAIN_ENABLED',
|
||||
IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED = 'IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED',
|
||||
IS_RECORD_PAGE_LAYOUT_ENABLED = 'IS_RECORD_PAGE_LAYOUT_ENABLED',
|
||||
IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED = 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED',
|
||||
IS_SSE_DB_EVENTS_ENABLED = 'IS_SSE_DB_EVENTS_ENABLED',
|
||||
IS_TASK_TARGET_MIGRATED = 'IS_TASK_TARGET_MIGRATED',
|
||||
IS_TIMELINE_ACTIVITY_MIGRATED = 'IS_TIMELINE_ACTIVITY_MIGRATED',
|
||||
IS_UNIQUE_INDEXES_ENABLED = 'IS_UNIQUE_INDEXES_ENABLED'
|
||||
}
|
||||
|
||||
+12
-2
@@ -6,6 +6,7 @@ import { type RecordGqlOperationSignatureFactory } from '@/object-record/graphql
|
||||
type FindActivitiesOperationSignatureFactory = {
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
objectNameSingular: CoreObjectNameSingular;
|
||||
isMorphRelation: boolean;
|
||||
};
|
||||
|
||||
export const findActivitiesOperationSignatureFactory: RecordGqlOperationSignatureFactory<
|
||||
@@ -13,6 +14,7 @@ export const findActivitiesOperationSignatureFactory: RecordGqlOperationSignatur
|
||||
> = ({
|
||||
objectMetadataItems,
|
||||
objectNameSingular,
|
||||
isMorphRelation,
|
||||
}: FindActivitiesOperationSignatureFactory) => {
|
||||
const body = {
|
||||
bodyV2: {
|
||||
@@ -62,9 +64,13 @@ export const findActivitiesOperationSignatureFactory: RecordGqlOperationSignatur
|
||||
__typename: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
deletedAt: true,
|
||||
note: true,
|
||||
noteId: true,
|
||||
...generateActivityTargetMorphFieldKeys(objectMetadataItems),
|
||||
...generateActivityTargetMorphFieldKeys(
|
||||
objectMetadataItems,
|
||||
isMorphRelation,
|
||||
),
|
||||
},
|
||||
}
|
||||
: {
|
||||
@@ -73,9 +79,13 @@ export const findActivitiesOperationSignatureFactory: RecordGqlOperationSignatur
|
||||
__typename: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
deletedAt: true,
|
||||
task: true,
|
||||
taskId: true,
|
||||
...generateActivityTargetMorphFieldKeys(objectMetadataItems),
|
||||
...generateActivityTargetMorphFieldKeys(
|
||||
objectMetadataItems,
|
||||
isMorphRelation,
|
||||
),
|
||||
},
|
||||
}),
|
||||
},
|
||||
|
||||
+20
-3
@@ -1,4 +1,5 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { type RecordGqlOperationOrderBy } from 'twenty-shared/types';
|
||||
|
||||
import { findActivityTargetsOperationSignatureFactory } from '@/activities/graphql/operation-signatures/factories/findActivityTargetsOperationSignatureFactory';
|
||||
import { type ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
@@ -6,9 +7,12 @@ import { type NoteTarget } from '@/activities/types/NoteTarget';
|
||||
import { type TaskTarget } from '@/activities/types/TaskTarget';
|
||||
import { getActivityTargetsFilter } from '@/activities/utils/getActivityTargetsFilter';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { type CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { type RecordGqlOperationOrderBy } from 'twenty-shared/types';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
|
||||
import { FeatureFlagKey } from '~/generated/graphql';
|
||||
|
||||
export const useActivityTargetsForTargetableObjects = ({
|
||||
objectNameSingular,
|
||||
@@ -28,12 +32,25 @@ export const useActivityTargetsForTargetableObjects = ({
|
||||
activityTargetsOrderByVariables: RecordGqlOperationOrderBy;
|
||||
limit: number;
|
||||
}) => {
|
||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||
const objectMetadataItems = useRecoilValue<ObjectMetadataItem[]>(
|
||||
objectMetadataItemsState,
|
||||
);
|
||||
const isNoteTargetMigrated = useIsFeatureEnabled(
|
||||
FeatureFlagKey.IS_NOTE_TARGET_MIGRATED,
|
||||
);
|
||||
const isTaskTargetMigrated = useIsFeatureEnabled(
|
||||
FeatureFlagKey.IS_TASK_TARGET_MIGRATED,
|
||||
);
|
||||
const isMorphRelation =
|
||||
objectNameSingular === CoreObjectNameSingular.Task
|
||||
? isTaskTargetMigrated
|
||||
: isNoteTargetMigrated;
|
||||
|
||||
const activityTargetsFilter = getActivityTargetsFilter({
|
||||
targetableObjects: targetableObjects,
|
||||
activityObjectNameSingular: objectNameSingular,
|
||||
objectMetadataItems,
|
||||
isMorphRelation,
|
||||
});
|
||||
|
||||
const FIND_ACTIVITY_TARGETS_OPERATION_SIGNATURE =
|
||||
|
||||
+13
-1
@@ -7,13 +7,15 @@ import { type TaskTarget } from '@/activities/types/TaskTarget';
|
||||
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
|
||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { type CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache';
|
||||
import { useUpsertFindManyRecordsQueryInCache } from '@/object-record/cache/hooks/useUpsertFindManyRecordsQueryInCache';
|
||||
import { getRecordFromCache } from '@/object-record/cache/utils/getRecordFromCache';
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FeatureFlagKey } from '~/generated/graphql';
|
||||
import { sortByAscString } from '~/utils/array/sortByAscString';
|
||||
|
||||
export const usePrepareFindManyActivitiesQuery = ({
|
||||
@@ -33,6 +35,12 @@ export const usePrepareFindManyActivitiesQuery = ({
|
||||
const cache = useApolloCoreClient().cache;
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
|
||||
const isNoteTargetMigrated = useIsFeatureEnabled(
|
||||
FeatureFlagKey.IS_NOTE_TARGET_MIGRATED,
|
||||
);
|
||||
const isTaskTargetMigrated = useIsFeatureEnabled(
|
||||
FeatureFlagKey.IS_TASK_TARGET_MIGRATED,
|
||||
);
|
||||
|
||||
const { upsertFindManyRecordsQueryInCache: upsertFindManyActivitiesInCache } =
|
||||
useUpsertFindManyRecordsQueryInCache({
|
||||
@@ -116,6 +124,10 @@ export const usePrepareFindManyActivitiesQuery = ({
|
||||
findActivitiesOperationSignatureFactory({
|
||||
objectNameSingular: activityObjectNameSingular,
|
||||
objectMetadataItems,
|
||||
isMorphRelation:
|
||||
activityObjectNameSingular === CoreObjectNameSingular.Task
|
||||
? isTaskTargetMigrated
|
||||
: isNoteTargetMigrated,
|
||||
});
|
||||
|
||||
upsertFindManyActivitiesInCache({
|
||||
|
||||
+22
-5
@@ -5,14 +5,17 @@ import { getActivityTargetFieldNameForObject } from '@/activities/utils/getActiv
|
||||
import { getJoinObjectNameSingular } from '@/activities/utils/getJoinObjectNameSingular';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
|
||||
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
||||
import { searchRecordStoreFamilyState } from '@/object-record/record-picker/multiple-record-picker/states/searchRecordStoreComponentFamilyState';
|
||||
import { type RecordPickerPickableMorphItem } from '@/object-record/record-picker/types/RecordPickerPickableMorphItem';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
import { FeatureFlagKey } from '~/generated/graphql';
|
||||
|
||||
type UpdateActivityTargetFromCellProps = {
|
||||
recordPickerInstanceId: string;
|
||||
@@ -50,6 +53,16 @@ export const useUpdateActivityTargetFromCell = ({
|
||||
? activityObjectNameSingular
|
||||
: joinObjectNameSingular,
|
||||
});
|
||||
const isNoteTargetMigrated = useIsFeatureEnabled(
|
||||
FeatureFlagKey.IS_NOTE_TARGET_MIGRATED,
|
||||
);
|
||||
const isTaskTargetMigrated = useIsFeatureEnabled(
|
||||
FeatureFlagKey.IS_TASK_TARGET_MIGRATED,
|
||||
);
|
||||
const isMorphRelation =
|
||||
activityObjectNameSingular === CoreObjectNameSingular.Task
|
||||
? isTaskTargetMigrated
|
||||
: isNoteTargetMigrated;
|
||||
|
||||
const setActivityFromStore = useSetRecoilState(
|
||||
recordStoreFamilyState(activityId),
|
||||
@@ -67,7 +80,7 @@ export const useUpdateActivityTargetFromCell = ({
|
||||
: 'note';
|
||||
|
||||
const objectMetadataItems = snapshot
|
||||
.getLoadable(objectMetadataItemsState)
|
||||
.getLoadable<ObjectMetadataItem[]>(objectMetadataItemsState)
|
||||
.getValue();
|
||||
|
||||
const pickedObjectMetadataItem = objectMetadataItems.find(
|
||||
@@ -83,6 +96,7 @@ export const useUpdateActivityTargetFromCell = ({
|
||||
activityObjectNameSingular,
|
||||
targetObjectMetadataId: morphItem.objectMetadataId,
|
||||
objectMetadataItems,
|
||||
isMorphRelation,
|
||||
});
|
||||
|
||||
if (!isDefined(targetFieldName)) {
|
||||
@@ -132,7 +146,7 @@ export const useUpdateActivityTargetFromCell = ({
|
||||
|
||||
const targetRecord = searchRecord.record;
|
||||
|
||||
const activityTarget =
|
||||
const activityTarget: NoteTarget | TaskTarget =
|
||||
activityObjectNameSingular === CoreObjectNameSingular.Task
|
||||
? {
|
||||
id: v4(),
|
||||
@@ -167,15 +181,17 @@ export const useUpdateActivityTargetFromCell = ({
|
||||
...activityTargetWithTargetRecords.map((activityTarget) => {
|
||||
return activityTarget.activityTarget;
|
||||
}),
|
||||
activityTarget as NoteTarget | TaskTarget,
|
||||
activityTarget,
|
||||
];
|
||||
|
||||
await createOneActivityTarget({
|
||||
const activityTargetInput: Partial<NoteTarget | TaskTarget> = {
|
||||
...activityTarget,
|
||||
[targetObjectName]: undefined,
|
||||
[targetFieldName]: undefined,
|
||||
[`${targetFieldName}Id`]: morphItem.recordId,
|
||||
} as Partial<NoteTarget | TaskTarget>);
|
||||
};
|
||||
|
||||
await createOneActivityTarget(activityTargetInput);
|
||||
}
|
||||
|
||||
setActivityFromStore((currentActivity) => {
|
||||
@@ -194,6 +210,7 @@ export const useUpdateActivityTargetFromCell = ({
|
||||
activityObjectNameSingular,
|
||||
createOneActivityTarget,
|
||||
deleteOneActivityTarget,
|
||||
isMorphRelation,
|
||||
setActivityFromStore,
|
||||
],
|
||||
);
|
||||
|
||||
+1
-1
@@ -41,7 +41,7 @@ export const Empty: Story = {};
|
||||
export const WithTasks: Story = {
|
||||
args: {
|
||||
targetableObject: {
|
||||
id: mockedTasks[0].taskTargets?.[0].personId,
|
||||
id: mockedTasks[0].taskTargets?.[0].targetPersonId,
|
||||
targetObjectNameSingular: 'person',
|
||||
} as ActivityTargetableObject,
|
||||
},
|
||||
|
||||
@@ -6,8 +6,13 @@ export type NoteTarget = {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
deletedAt?: string | null;
|
||||
companyId?: string | null;
|
||||
personId?: string | null;
|
||||
opportunityId?: string | null;
|
||||
targetCompanyId?: string | null;
|
||||
targetPersonId?: string | null;
|
||||
targetOpportunityId?: string | null;
|
||||
note: Pick<Note, 'id' | 'createdAt' | 'updatedAt' | '__typename'>;
|
||||
person?: Pick<Person, 'id' | 'name' | 'avatarUrl' | '__typename'> | null;
|
||||
company?: Pick<Company, 'id' | 'name' | 'domainName' | '__typename'> | null;
|
||||
|
||||
@@ -7,8 +7,13 @@ export type TaskTarget = {
|
||||
id: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
deletedAt?: string | null;
|
||||
companyId?: string | null;
|
||||
personId?: string | null;
|
||||
opportunityId?: string | null;
|
||||
targetCompanyId?: string | null;
|
||||
targetPersonId?: string | null;
|
||||
targetOpportunityId?: string | null;
|
||||
taskId: string | null;
|
||||
task: Pick<Task, 'id' | 'createdAt' | 'updatedAt' | '__typename'>;
|
||||
person?: Pick<Person, 'id' | 'name' | 'avatarUrl' | '__typename'> | null;
|
||||
|
||||
+23
-15
@@ -1,27 +1,35 @@
|
||||
import { getActivityTargetObjectFieldIdName } from '@/activities/utils/getActivityTargetObjectFieldIdName';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
|
||||
export const generateActivityTargetMorphFieldKeys = (
|
||||
objectMetadataItems: ObjectMetadataItem[],
|
||||
isMorphRelation: boolean,
|
||||
) => {
|
||||
const targetableObjectMetadataItems = objectMetadataItems.filter(
|
||||
(objectMetadataItem) =>
|
||||
objectMetadataItem.isActive && !objectMetadataItem.isSystem,
|
||||
);
|
||||
|
||||
const targetableObjects = Object.fromEntries(
|
||||
objectMetadataItems
|
||||
.filter(
|
||||
(objectMetadataItem) =>
|
||||
objectMetadataItem.isActive && !objectMetadataItem.isSystem,
|
||||
)
|
||||
.map((objectMetadataItem) => [objectMetadataItem.nameSingular, true]),
|
||||
targetableObjectMetadataItems.map((objectMetadataItem) => {
|
||||
const targetFieldIdName = getActivityTargetObjectFieldIdName({
|
||||
nameSingular: objectMetadataItem.nameSingular,
|
||||
isMorphRelation,
|
||||
});
|
||||
|
||||
return [targetFieldIdName.replace(/Id$/, ''), true];
|
||||
}),
|
||||
);
|
||||
|
||||
const targetableObjectIds = Object.fromEntries(
|
||||
objectMetadataItems
|
||||
.filter(
|
||||
(objectMetadataItem) =>
|
||||
objectMetadataItem.isActive && !objectMetadataItem.isSystem,
|
||||
)
|
||||
.map((objectMetadataItem) => [
|
||||
`${objectMetadataItem.nameSingular}Id`,
|
||||
true,
|
||||
]),
|
||||
targetableObjectMetadataItems.map((objectMetadataItem) => {
|
||||
const targetFieldIdName = getActivityTargetObjectFieldIdName({
|
||||
nameSingular: objectMetadataItem.nameSingular,
|
||||
isMorphRelation,
|
||||
});
|
||||
|
||||
return [targetFieldIdName, true];
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
+18
-4
@@ -1,3 +1,4 @@
|
||||
import { getActivityTargetObjectFieldIdName } from '@/activities/utils/getActivityTargetObjectFieldIdName';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -8,12 +9,14 @@ type GetActivityTargetFieldNameForObjectArgs = {
|
||||
| CoreObjectNameSingular.Task;
|
||||
targetObjectMetadataId: string;
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
isMorphRelation?: boolean;
|
||||
};
|
||||
|
||||
export const getActivityTargetFieldNameForObject = ({
|
||||
activityObjectNameSingular,
|
||||
targetObjectMetadataId,
|
||||
objectMetadataItems,
|
||||
isMorphRelation = false,
|
||||
}: GetActivityTargetFieldNameForObjectArgs): string | undefined => {
|
||||
const activityTargetObjectNameSingular =
|
||||
activityObjectNameSingular === CoreObjectNameSingular.Task
|
||||
@@ -29,10 +32,21 @@ export const getActivityTargetFieldNameForObject = ({
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const targetField = activityTargetObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.relation?.targetObjectMetadata.id === targetObjectMetadataId,
|
||||
const targetObjectMetadataItem = objectMetadataItems.find(
|
||||
(objectMetadataItem) => objectMetadataItem.id === targetObjectMetadataId,
|
||||
);
|
||||
|
||||
return targetField?.name;
|
||||
if (isMorphRelation && isDefined(targetObjectMetadataItem)) {
|
||||
const fieldIdName = getActivityTargetObjectFieldIdName({
|
||||
nameSingular: targetObjectMetadataItem.nameSingular,
|
||||
isMorphRelation: true,
|
||||
});
|
||||
|
||||
return fieldIdName.replace(/Id$/, '');
|
||||
}
|
||||
|
||||
return activityTargetObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.relation?.targetObjectMetadata.id === targetObjectMetadataId,
|
||||
)?.name;
|
||||
};
|
||||
|
||||
+82
-23
@@ -6,8 +6,8 @@ import { type TaskTarget } from '@/activities/types/TaskTarget';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||
import { type Nullable } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FieldMetadataType, type Nullable } from 'twenty-shared/types';
|
||||
import { computeMorphRelationFieldName, isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type GetActivityTargetObjectRecordsProps = {
|
||||
activityRecord: Note | Task;
|
||||
@@ -47,41 +47,100 @@ export const getActivityTargetObjectRecords = ({
|
||||
);
|
||||
|
||||
const activityTargetRelationFields =
|
||||
activityTargetObjectMetadata?.fields.filter(
|
||||
(field) =>
|
||||
isDefined(field.relation?.targetObjectMetadata.id) &&
|
||||
![CoreObjectNameSingular.Note, CoreObjectNameSingular.Task].includes(
|
||||
field.relation?.targetObjectMetadata
|
||||
.nameSingular as CoreObjectNameSingular,
|
||||
),
|
||||
) ?? [];
|
||||
activityTargetObjectMetadata?.fields.filter((field) => {
|
||||
if (
|
||||
field.type === FieldMetadataType.MORPH_RELATION &&
|
||||
isDefined(field.morphRelations) &&
|
||||
field.morphRelations.length > 0
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const targetObjectNameSingular =
|
||||
field.relation?.targetObjectMetadata.nameSingular;
|
||||
|
||||
if (!isDefined(field.relation?.targetObjectMetadata.id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isDefined(targetObjectNameSingular)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
targetObjectNameSingular !== CoreObjectNameSingular.Note &&
|
||||
targetObjectNameSingular !== CoreObjectNameSingular.Task
|
||||
);
|
||||
}) ?? [];
|
||||
|
||||
const activityTargetObjectRecords = targets
|
||||
.map<ActivityTargetWithTargetRecord | undefined>((activityTarget) => {
|
||||
if (!isDefined(activityTarget)) {
|
||||
throw new Error('Cannot find activity target');
|
||||
}
|
||||
const matchingField = activityTargetRelationFields.find((field) =>
|
||||
isDefined(activityTarget[field.name]),
|
||||
);
|
||||
|
||||
if (!matchingField || !matchingField.relation) {
|
||||
if (isDefined(activityTarget.deletedAt)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const correspondingObjectMetadataItem = objectMetadataItems.find(
|
||||
(objectMetadataItem) =>
|
||||
objectMetadataItem.id ===
|
||||
matchingField.relation?.targetObjectMetadata.id,
|
||||
);
|
||||
let matchingFieldName: string | undefined;
|
||||
let correspondingObjectMetadataItem: ObjectMetadataItem | undefined;
|
||||
|
||||
if (!correspondingObjectMetadataItem) {
|
||||
for (const field of activityTargetRelationFields) {
|
||||
if (
|
||||
field.type === FieldMetadataType.MORPH_RELATION &&
|
||||
isDefined(field.morphRelations)
|
||||
) {
|
||||
const matchingMorphRelation = field.morphRelations.find(
|
||||
(morphRelation) => {
|
||||
const morphFieldName = computeMorphRelationFieldName({
|
||||
fieldName: field.name,
|
||||
relationType: morphRelation.type,
|
||||
targetObjectMetadataNameSingular:
|
||||
morphRelation.targetObjectMetadata.nameSingular,
|
||||
targetObjectMetadataNamePlural:
|
||||
morphRelation.targetObjectMetadata.namePlural,
|
||||
});
|
||||
|
||||
return isDefined(activityTarget[morphFieldName]);
|
||||
},
|
||||
);
|
||||
|
||||
if (isDefined(matchingMorphRelation)) {
|
||||
matchingFieldName = computeMorphRelationFieldName({
|
||||
fieldName: field.name,
|
||||
relationType: matchingMorphRelation.type,
|
||||
targetObjectMetadataNameSingular:
|
||||
matchingMorphRelation.targetObjectMetadata.nameSingular,
|
||||
targetObjectMetadataNamePlural:
|
||||
matchingMorphRelation.targetObjectMetadata.namePlural,
|
||||
});
|
||||
correspondingObjectMetadataItem = objectMetadataItems.find(
|
||||
(objectMetadataItem) =>
|
||||
objectMetadataItem.id ===
|
||||
matchingMorphRelation.targetObjectMetadata.id,
|
||||
);
|
||||
break;
|
||||
}
|
||||
} else if (isDefined(activityTarget[field.name])) {
|
||||
matchingFieldName = field.name;
|
||||
correspondingObjectMetadataItem = objectMetadataItems.find(
|
||||
(objectMetadataItem) =>
|
||||
objectMetadataItem.id === field.relation?.targetObjectMetadata.id,
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!isDefined(matchingFieldName) ||
|
||||
!isDefined(correspondingObjectMetadataItem)
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const targetObjectRecord = activityTarget[matchingField.name] as
|
||||
| ObjectRecord
|
||||
| undefined;
|
||||
const targetObjectRecord: ObjectRecord | undefined =
|
||||
activityTarget[matchingFieldName];
|
||||
|
||||
if (!isDefined(targetObjectRecord)) {
|
||||
throw new Error(
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { type ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
|
||||
import { getActivityTargetObjectFieldIdName } from '@/activities/utils/getActivityTargetObjectFieldIdName';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@@ -7,12 +8,14 @@ export const getActivityTargetsFilter = ({
|
||||
targetableObjects,
|
||||
activityObjectNameSingular,
|
||||
objectMetadataItems,
|
||||
isMorphRelation = false,
|
||||
}: {
|
||||
targetableObjects: ActivityTargetableObject[];
|
||||
activityObjectNameSingular:
|
||||
| CoreObjectNameSingular.Note
|
||||
| CoreObjectNameSingular.Task;
|
||||
objectMetadataItems: ObjectMetadataItem[];
|
||||
isMorphRelation?: boolean;
|
||||
}) => {
|
||||
const activityTargetObjectNameSingular =
|
||||
activityObjectNameSingular === CoreObjectNameSingular.Task
|
||||
@@ -36,13 +39,16 @@ export const getActivityTargetsFilter = ({
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const targetField = activityTargetObjectMetadata?.fields.find(
|
||||
(field) =>
|
||||
field.relation?.targetObjectMetadata.id ===
|
||||
targetObjectMetadataItem.id,
|
||||
);
|
||||
|
||||
const joinColumnName = targetField?.settings?.joinColumnName;
|
||||
const joinColumnName = isMorphRelation
|
||||
? getActivityTargetObjectFieldIdName({
|
||||
nameSingular: targetObjectMetadataItem.nameSingular,
|
||||
isMorphRelation: true,
|
||||
})
|
||||
: activityTargetObjectMetadata?.fields.find(
|
||||
(field) =>
|
||||
field.relation?.targetObjectMetadata.id ===
|
||||
targetObjectMetadataItem.id,
|
||||
)?.settings?.joinColumnName;
|
||||
|
||||
if (!isDefined(joinColumnName)) {
|
||||
return undefined;
|
||||
|
||||
+299
@@ -0,0 +1,299 @@
|
||||
import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
|
||||
|
||||
// Maps indexName to its related field universal identifiers for each standard object
|
||||
export const STANDARD_INDEX_FIELD_UNIVERSAL_IDENTIFIERS: Record<
|
||||
string,
|
||||
Record<string, string[]>
|
||||
> = {
|
||||
attachment: {
|
||||
taskIdIndex: [
|
||||
STANDARD_OBJECTS.attachment.fields.targetTask.universalIdentifier,
|
||||
],
|
||||
noteIdIndex: [
|
||||
STANDARD_OBJECTS.attachment.fields.targetNote.universalIdentifier,
|
||||
],
|
||||
personIdIndex: [
|
||||
STANDARD_OBJECTS.attachment.fields.targetPerson.universalIdentifier,
|
||||
],
|
||||
companyIdIndex: [
|
||||
STANDARD_OBJECTS.attachment.fields.targetCompany.universalIdentifier,
|
||||
],
|
||||
opportunityIdIndex: [
|
||||
STANDARD_OBJECTS.attachment.fields.targetOpportunity.universalIdentifier,
|
||||
],
|
||||
dashboardIdIndex: [
|
||||
STANDARD_OBJECTS.attachment.fields.targetDashboard.universalIdentifier,
|
||||
],
|
||||
workflowIdIndex: [
|
||||
STANDARD_OBJECTS.attachment.fields.targetWorkflow.universalIdentifier,
|
||||
],
|
||||
},
|
||||
blocklist: {
|
||||
workspaceMemberIdIndex: [
|
||||
STANDARD_OBJECTS.blocklist.fields.workspaceMember.universalIdentifier,
|
||||
],
|
||||
},
|
||||
calendarChannelEventAssociation: {
|
||||
calendarChannelIdIndex: [
|
||||
STANDARD_OBJECTS.calendarChannelEventAssociation.fields.calendarChannel
|
||||
.universalIdentifier,
|
||||
],
|
||||
calendarEventIdIndex: [
|
||||
STANDARD_OBJECTS.calendarChannelEventAssociation.fields.calendarEvent
|
||||
.universalIdentifier,
|
||||
],
|
||||
},
|
||||
calendarChannel: {
|
||||
connectedAccountIdIndex: [
|
||||
STANDARD_OBJECTS.calendarChannel.fields.connectedAccount
|
||||
.universalIdentifier,
|
||||
],
|
||||
},
|
||||
calendarEventParticipant: {
|
||||
calendarEventIdIndex: [
|
||||
STANDARD_OBJECTS.calendarEventParticipant.fields.calendarEvent
|
||||
.universalIdentifier,
|
||||
],
|
||||
personIdIndex: [
|
||||
STANDARD_OBJECTS.calendarEventParticipant.fields.person
|
||||
.universalIdentifier,
|
||||
],
|
||||
workspaceMemberIdIndex: [
|
||||
STANDARD_OBJECTS.calendarEventParticipant.fields.workspaceMember
|
||||
.universalIdentifier,
|
||||
],
|
||||
},
|
||||
company: {
|
||||
accountOwnerIdIndex: [
|
||||
STANDARD_OBJECTS.company.fields.accountOwner.universalIdentifier,
|
||||
],
|
||||
domainNameUniqueIndex: [
|
||||
STANDARD_OBJECTS.company.fields.domainName.universalIdentifier,
|
||||
],
|
||||
searchVectorGinIndex: [
|
||||
STANDARD_OBJECTS.company.fields.searchVector.universalIdentifier,
|
||||
],
|
||||
},
|
||||
connectedAccount: {
|
||||
accountOwnerIdIndex: [
|
||||
STANDARD_OBJECTS.connectedAccount.fields.accountOwner.universalIdentifier,
|
||||
],
|
||||
},
|
||||
dashboard: {
|
||||
searchVectorGinIndex: [
|
||||
STANDARD_OBJECTS.dashboard.fields.searchVector.universalIdentifier,
|
||||
],
|
||||
},
|
||||
favorite: {
|
||||
forWorkspaceMemberIdIndex: [
|
||||
STANDARD_OBJECTS.favorite.fields.forWorkspaceMember.universalIdentifier,
|
||||
],
|
||||
personIdIndex: [
|
||||
STANDARD_OBJECTS.favorite.fields.person.universalIdentifier,
|
||||
],
|
||||
companyIdIndex: [
|
||||
STANDARD_OBJECTS.favorite.fields.company.universalIdentifier,
|
||||
],
|
||||
favoriteFolderIdIndex: [
|
||||
STANDARD_OBJECTS.favorite.fields.favoriteFolder.universalIdentifier,
|
||||
],
|
||||
opportunityIdIndex: [
|
||||
STANDARD_OBJECTS.favorite.fields.opportunity.universalIdentifier,
|
||||
],
|
||||
workflowIdIndex: [
|
||||
STANDARD_OBJECTS.favorite.fields.workflow.universalIdentifier,
|
||||
],
|
||||
workflowVersionIdIndex: [
|
||||
STANDARD_OBJECTS.favorite.fields.workflowVersion.universalIdentifier,
|
||||
],
|
||||
workflowRunIdIndex: [
|
||||
STANDARD_OBJECTS.favorite.fields.workflowRun.universalIdentifier,
|
||||
],
|
||||
taskIdIndex: [STANDARD_OBJECTS.favorite.fields.task.universalIdentifier],
|
||||
noteIdIndex: [STANDARD_OBJECTS.favorite.fields.note.universalIdentifier],
|
||||
dashboardIdIndex: [
|
||||
STANDARD_OBJECTS.favorite.fields.dashboard.universalIdentifier,
|
||||
],
|
||||
},
|
||||
messageChannelMessageAssociation: {
|
||||
messageChannelIdIndex: [
|
||||
STANDARD_OBJECTS.messageChannelMessageAssociation.fields.messageChannel
|
||||
.universalIdentifier,
|
||||
],
|
||||
messageIdIndex: [
|
||||
STANDARD_OBJECTS.messageChannelMessageAssociation.fields.message
|
||||
.universalIdentifier,
|
||||
],
|
||||
messageChannelIdMessageIdUniqueIndex: [
|
||||
STANDARD_OBJECTS.messageChannelMessageAssociation.fields.messageChannel
|
||||
.universalIdentifier,
|
||||
STANDARD_OBJECTS.messageChannelMessageAssociation.fields.message
|
||||
.universalIdentifier,
|
||||
],
|
||||
},
|
||||
messageChannel: {
|
||||
connectedAccountIdIndex: [
|
||||
STANDARD_OBJECTS.messageChannel.fields.connectedAccount
|
||||
.universalIdentifier,
|
||||
],
|
||||
},
|
||||
messageFolder: {
|
||||
messageChannelIdIndex: [
|
||||
STANDARD_OBJECTS.messageFolder.fields.messageChannel.universalIdentifier,
|
||||
],
|
||||
},
|
||||
messageParticipant: {
|
||||
messageIdIndex: [
|
||||
STANDARD_OBJECTS.messageParticipant.fields.message.universalIdentifier,
|
||||
],
|
||||
personIdIndex: [
|
||||
STANDARD_OBJECTS.messageParticipant.fields.person.universalIdentifier,
|
||||
],
|
||||
workspaceMemberIdIndex: [
|
||||
STANDARD_OBJECTS.messageParticipant.fields.workspaceMember
|
||||
.universalIdentifier,
|
||||
],
|
||||
},
|
||||
message: {
|
||||
messageThreadIdIndex: [
|
||||
STANDARD_OBJECTS.message.fields.messageThread.universalIdentifier,
|
||||
],
|
||||
},
|
||||
note: {
|
||||
searchVectorGinIndex: [
|
||||
STANDARD_OBJECTS.note.fields.searchVector.universalIdentifier,
|
||||
],
|
||||
},
|
||||
noteTarget: {
|
||||
noteIdIndex: [STANDARD_OBJECTS.noteTarget.fields.note.universalIdentifier],
|
||||
personIdIndex: [
|
||||
STANDARD_OBJECTS.noteTarget.fields.targetPerson.universalIdentifier,
|
||||
],
|
||||
companyIdIndex: [
|
||||
STANDARD_OBJECTS.noteTarget.fields.targetCompany.universalIdentifier,
|
||||
],
|
||||
opportunityIdIndex: [
|
||||
STANDARD_OBJECTS.noteTarget.fields.targetOpportunity.universalIdentifier,
|
||||
],
|
||||
},
|
||||
opportunity: {
|
||||
pointOfContactIdIndex: [
|
||||
STANDARD_OBJECTS.opportunity.fields.pointOfContact.universalIdentifier,
|
||||
],
|
||||
companyIdIndex: [
|
||||
STANDARD_OBJECTS.opportunity.fields.company.universalIdentifier,
|
||||
],
|
||||
stageIndex: [STANDARD_OBJECTS.opportunity.fields.stage.universalIdentifier],
|
||||
searchVectorGinIndex: [
|
||||
STANDARD_OBJECTS.opportunity.fields.searchVector.universalIdentifier,
|
||||
],
|
||||
},
|
||||
person: {
|
||||
companyIdIndex: [
|
||||
STANDARD_OBJECTS.person.fields.company.universalIdentifier,
|
||||
],
|
||||
emailsUniqueIndex: [
|
||||
STANDARD_OBJECTS.person.fields.emails.universalIdentifier,
|
||||
],
|
||||
searchVectorGinIndex: [
|
||||
STANDARD_OBJECTS.person.fields.searchVector.universalIdentifier,
|
||||
],
|
||||
},
|
||||
task: {
|
||||
assigneeIdIndex: [
|
||||
STANDARD_OBJECTS.task.fields.assignee.universalIdentifier,
|
||||
],
|
||||
searchVectorGinIndex: [
|
||||
STANDARD_OBJECTS.task.fields.searchVector.universalIdentifier,
|
||||
],
|
||||
},
|
||||
taskTarget: {
|
||||
taskIdIndex: [STANDARD_OBJECTS.taskTarget.fields.task.universalIdentifier],
|
||||
personIdIndex: [
|
||||
STANDARD_OBJECTS.taskTarget.fields.targetPerson.universalIdentifier,
|
||||
],
|
||||
companyIdIndex: [
|
||||
STANDARD_OBJECTS.taskTarget.fields.targetCompany.universalIdentifier,
|
||||
],
|
||||
opportunityIdIndex: [
|
||||
STANDARD_OBJECTS.taskTarget.fields.targetOpportunity.universalIdentifier,
|
||||
],
|
||||
},
|
||||
timelineActivity: {
|
||||
workspaceMemberIdIndex: [
|
||||
STANDARD_OBJECTS.timelineActivity.fields.workspaceMember
|
||||
.universalIdentifier,
|
||||
],
|
||||
personIdIndex: [
|
||||
STANDARD_OBJECTS.timelineActivity.fields.targetPerson.universalIdentifier,
|
||||
],
|
||||
companyIdIndex: [
|
||||
STANDARD_OBJECTS.timelineActivity.fields.targetCompany
|
||||
.universalIdentifier,
|
||||
],
|
||||
opportunityIdIndex: [
|
||||
STANDARD_OBJECTS.timelineActivity.fields.targetOpportunity
|
||||
.universalIdentifier,
|
||||
],
|
||||
noteIdIndex: [
|
||||
STANDARD_OBJECTS.timelineActivity.fields.targetNote.universalIdentifier,
|
||||
],
|
||||
taskIdIndex: [
|
||||
STANDARD_OBJECTS.timelineActivity.fields.targetTask.universalIdentifier,
|
||||
],
|
||||
workflowIdIndex: [
|
||||
STANDARD_OBJECTS.timelineActivity.fields.targetWorkflow
|
||||
.universalIdentifier,
|
||||
],
|
||||
workflowVersionIdIndex: [
|
||||
STANDARD_OBJECTS.timelineActivity.fields.targetWorkflowVersion
|
||||
.universalIdentifier,
|
||||
],
|
||||
workflowRunIdIndex: [
|
||||
STANDARD_OBJECTS.timelineActivity.fields.targetWorkflowRun
|
||||
.universalIdentifier,
|
||||
],
|
||||
dashboardIdIndex: [
|
||||
STANDARD_OBJECTS.timelineActivity.fields.targetDashboard
|
||||
.universalIdentifier,
|
||||
],
|
||||
},
|
||||
workflow: {
|
||||
searchVectorGinIndex: [
|
||||
STANDARD_OBJECTS.workflow.fields.searchVector.universalIdentifier,
|
||||
],
|
||||
},
|
||||
workflowAutomatedTrigger: {
|
||||
workflowIdIndex: [
|
||||
STANDARD_OBJECTS.workflowAutomatedTrigger.fields.workflow
|
||||
.universalIdentifier,
|
||||
],
|
||||
},
|
||||
workflowRun: {
|
||||
workflowVersionIdIndex: [
|
||||
STANDARD_OBJECTS.workflowRun.fields.workflowVersion.universalIdentifier,
|
||||
],
|
||||
workflowIdIndex: [
|
||||
STANDARD_OBJECTS.workflowRun.fields.workflow.universalIdentifier,
|
||||
],
|
||||
searchVectorGinIndex: [
|
||||
STANDARD_OBJECTS.workflowRun.fields.searchVector.universalIdentifier,
|
||||
],
|
||||
},
|
||||
workflowVersion: {
|
||||
workflowIdIndex: [
|
||||
STANDARD_OBJECTS.workflowVersion.fields.workflow.universalIdentifier,
|
||||
],
|
||||
searchVectorGinIndex: [
|
||||
STANDARD_OBJECTS.workflowVersion.fields.searchVector.universalIdentifier,
|
||||
],
|
||||
},
|
||||
workspaceMember: {
|
||||
userEmailUniqueIndex: [
|
||||
STANDARD_OBJECTS.workspaceMember.fields.userEmail.universalIdentifier,
|
||||
],
|
||||
searchVectorGinIndex: [
|
||||
STANDARD_OBJECTS.workspaceMember.fields.searchVector.universalIdentifier,
|
||||
],
|
||||
},
|
||||
};
|
||||
+12
-5
@@ -289,11 +289,18 @@ export class MigrateAttachmentToMorphRelationsCommand extends ActiveOrSuspendedW
|
||||
this.logger.log(`Flush cache for workspace ${workspaceId}`);
|
||||
await this.workspaceCacheStorageService.flush(workspaceId);
|
||||
} catch (error) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
this.logger.error(
|
||||
`Error migrating attachment to morph relations (rolled transaction back on ${workspaceId})`,
|
||||
error,
|
||||
);
|
||||
if (queryRunner.isTransactionActive) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
this.logger.error(
|
||||
`Error migrating attachment to morph relations (rolled transaction back on ${workspaceId})`,
|
||||
error,
|
||||
);
|
||||
} else {
|
||||
this.logger.error(
|
||||
`Error migrating attachment to morph relations after commit on ${workspaceId}`,
|
||||
error,
|
||||
);
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
type FieldMetadataSettings,
|
||||
} from 'twenty-shared/types';
|
||||
import { capitalize } from 'twenty-shared/utils';
|
||||
import { DataSource, Repository } from 'typeorm';
|
||||
|
||||
import { ActiveOrSuspendedWorkspacesMigrationCommandRunner } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspaces-migration.command-runner';
|
||||
import { getFlatFieldsFromFlatObjectMetadata } from 'src/engine/api/graphql/workspace-schema-builder/utils/get-flat-fields-for-flat-object-metadata.util';
|
||||
import { type FlatApplicationCacheMaps } from 'src/engine/core-modules/application/types/flat-application-cache-maps.type';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { computeMorphOrRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-or-relation-field-join-column-name.util';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { getMetadataRelatedMetadataNames } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-related-metadata-names.util';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { type WorkspaceCacheKeyName } from 'src/engine/workspace-cache/types/workspace-cache-key.type';
|
||||
import { getWorkspaceSchemaName } from 'src/engine/workspace-datasource/utils/get-workspace-schema-name.util';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
|
||||
|
||||
type RelationFieldMetadataSettings =
|
||||
FieldMetadataSettings<FieldMetadataType.RELATION>;
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:1-17:migrate-note-target-to-morph-relations',
|
||||
description:
|
||||
'Migrate noteTarget relations to morph relation fields and set feature flag',
|
||||
})
|
||||
export class MigrateNoteTargetToMorphRelationsCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
private readonly featureFlagService: FeatureFlagService,
|
||||
@InjectDataSource()
|
||||
private readonly coreDataSource: DataSource,
|
||||
private readonly twentyORMGlobalManager: GlobalWorkspaceOrmManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager, dataSourceService);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
workspaceId,
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
const isMigrated = await this.featureFlagService.isFeatureEnabled(
|
||||
FeatureFlagKey.IS_NOTE_TARGET_MIGRATED,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
this.logger.log(`Migrating noteTarget for workspace ${workspaceId}`);
|
||||
|
||||
if (isMigrated) {
|
||||
this.logger.log(`NoteTarget migration already completed. Skipping...`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.dryRun) {
|
||||
this.logger.log(
|
||||
`Would have migrated noteTarget for workspace ${workspaceId}. Skipping...`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const queryRunner = this.coreDataSource.createQueryRunner();
|
||||
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
try {
|
||||
const schemaName = getWorkspaceSchemaName(workspaceId);
|
||||
const tableName = 'noteTarget';
|
||||
|
||||
const {
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps,
|
||||
flatApplicationMaps,
|
||||
} = await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatObjectMetadataMaps',
|
||||
'flatFieldMetadataMaps',
|
||||
'flatApplicationMaps',
|
||||
]);
|
||||
|
||||
const noteTargetFieldUniversalIdentifiers = new Set<string>([
|
||||
STANDARD_OBJECTS.noteTarget.fields.targetPerson.universalIdentifier,
|
||||
STANDARD_OBJECTS.noteTarget.fields.targetCompany.universalIdentifier,
|
||||
STANDARD_OBJECTS.noteTarget.fields.targetOpportunity
|
||||
.universalIdentifier,
|
||||
]);
|
||||
|
||||
const noteTargetObjectMetadata =
|
||||
findFlatEntityByUniversalIdentifier<FlatObjectMetadata>({
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
universalIdentifier: STANDARD_OBJECTS.noteTarget.universalIdentifier,
|
||||
});
|
||||
|
||||
if (!noteTargetObjectMetadata) {
|
||||
this.logger.error(
|
||||
`🟥 ${tableName} object metadata not found for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const noteTargetFieldMetadatas = getFlatFieldsFromFlatObjectMetadata(
|
||||
noteTargetObjectMetadata,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
|
||||
const noteTargetRelationFields = noteTargetFieldMetadatas
|
||||
.filter(isMorphOrRelationFlatFieldMetadata)
|
||||
.filter((field) => field.type === FieldMetadataType.RELATION)
|
||||
.filter((field) => {
|
||||
const isStandardAppField = this.isTwentyStandardApplicationField({
|
||||
field,
|
||||
flatApplicationMaps,
|
||||
workspaceId,
|
||||
});
|
||||
const isStandardTarget =
|
||||
isStandardAppField &&
|
||||
noteTargetFieldUniversalIdentifiers.has(field.universalIdentifier);
|
||||
const targetObjectMetadata = field.relationTargetObjectMetadataId
|
||||
? findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
flatEntityId: field.relationTargetObjectMetadataId,
|
||||
})
|
||||
: undefined;
|
||||
const isCustomTarget =
|
||||
!isStandardAppField && targetObjectMetadata?.isCustom === true;
|
||||
|
||||
return isStandardTarget || isCustomTarget;
|
||||
});
|
||||
|
||||
const fieldMigrations = noteTargetRelationFields.map((field) => {
|
||||
const newFieldName = `target${capitalize(field.name)}`;
|
||||
const relationSettings: RelationFieldMetadataSettings = field.settings;
|
||||
const oldJoinColumnName =
|
||||
relationSettings?.joinColumnName ??
|
||||
computeMorphOrRelationFieldJoinColumnName({ name: field.name });
|
||||
const newJoinColumnName = computeMorphOrRelationFieldJoinColumnName({
|
||||
name: newFieldName,
|
||||
});
|
||||
|
||||
return {
|
||||
field,
|
||||
newFieldName,
|
||||
oldJoinColumnName,
|
||||
newJoinColumnName,
|
||||
};
|
||||
});
|
||||
|
||||
// Rename columns
|
||||
for (const { oldJoinColumnName, newJoinColumnName } of fieldMigrations) {
|
||||
if (oldJoinColumnName === newJoinColumnName) {
|
||||
this.logger.log(
|
||||
`Column "${oldJoinColumnName}" already renamed. Skipping...`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "${schemaName}"."${tableName}"
|
||||
RENAME COLUMN "${oldJoinColumnName}" TO "${newJoinColumnName}"`,
|
||||
);
|
||||
this.logger.log(
|
||||
`Renamed column "${oldJoinColumnName}" to "${newJoinColumnName}" for "${tableName}"`,
|
||||
);
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Error renaming column "${oldJoinColumnName}" to "${newJoinColumnName}" for "${tableName}" in workspace ${workspaceId}`,
|
||||
error,
|
||||
);
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.log(`✅ Successfully migrated ${tableName} records`);
|
||||
|
||||
const morphId =
|
||||
STANDARD_OBJECTS.noteTarget.morphIds.targetMorphId.morphId;
|
||||
|
||||
// Update field metadata
|
||||
for (const {
|
||||
field: fieldToMigrate,
|
||||
newFieldName,
|
||||
newJoinColumnName,
|
||||
} of fieldMigrations) {
|
||||
const settings = {
|
||||
...fieldToMigrate.settings,
|
||||
joinColumnName: newJoinColumnName,
|
||||
};
|
||||
|
||||
try {
|
||||
const result = await queryRunner.query(
|
||||
`UPDATE core."fieldMetadata"
|
||||
SET name = $1, type = $5, "morphId" = $3, settings = $4
|
||||
WHERE id = $2`,
|
||||
[
|
||||
newFieldName,
|
||||
fieldToMigrate.id,
|
||||
morphId,
|
||||
settings,
|
||||
FieldMetadataType.MORPH_RELATION,
|
||||
],
|
||||
);
|
||||
|
||||
const rowsUpdated = result[1] || 0;
|
||||
|
||||
if (rowsUpdated > 0) {
|
||||
this.logger.log(
|
||||
`Updated fieldMetadata: ${fieldToMigrate.name} → ${newFieldName} (type: MORPH_RELATION)`,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Error updating fieldMetadata for field "${fieldToMigrate.name}" in workspace ${workspaceId}`,
|
||||
error,
|
||||
);
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.log(`✅ Successfully migrated ${tableName} fieldmetadata`);
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
|
||||
await this.featureFlagService.enableFeatureFlags(
|
||||
[FeatureFlagKey.IS_NOTE_TARGET_MIGRATED],
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
const relatedMetadataNames =
|
||||
getMetadataRelatedMetadataNames('fieldMetadata');
|
||||
const relatedCacheKeysToInvalidate: WorkspaceCacheKeyName[] =
|
||||
relatedMetadataNames.map(getMetadataFlatEntityMapsKey);
|
||||
const cacheKeysToInvalidate: WorkspaceCacheKeyName[] = [
|
||||
'flatFieldMetadataMaps',
|
||||
...relatedCacheKeysToInvalidate,
|
||||
'featureFlagsMap',
|
||||
];
|
||||
|
||||
this.logger.log(
|
||||
`Invalidating caches: ${cacheKeysToInvalidate.join(' ')}`,
|
||||
);
|
||||
|
||||
await this.workspaceCacheService.invalidateAndRecompute(
|
||||
workspaceId,
|
||||
cacheKeysToInvalidate,
|
||||
);
|
||||
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
this.logger.log(`Cache flushed`);
|
||||
|
||||
this.logger.log(
|
||||
`Set IS_NOTE_TARGET_MIGRATED feature flag for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
this.logger.log(`Flush cache for workspace ${workspaceId}`);
|
||||
await this.workspaceCacheStorageService.flush(workspaceId);
|
||||
} catch (error) {
|
||||
if (queryRunner.isTransactionActive) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
this.logger.error(
|
||||
`Error migrating noteTarget to morph relations (rolled transaction back on ${workspaceId})`,
|
||||
error,
|
||||
);
|
||||
} else {
|
||||
this.logger.error(
|
||||
`Error migrating noteTarget to morph relations after commit on ${workspaceId}`,
|
||||
error,
|
||||
);
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
private isTwentyStandardApplicationField({
|
||||
field,
|
||||
flatApplicationMaps,
|
||||
workspaceId,
|
||||
}: {
|
||||
field: { id: string; name: string; applicationId: string };
|
||||
flatApplicationMaps: FlatApplicationCacheMaps;
|
||||
workspaceId: string;
|
||||
}): boolean {
|
||||
const application = flatApplicationMaps.byId[field.applicationId];
|
||||
|
||||
if (!application) {
|
||||
this.logger.error(
|
||||
`🟥 Application not found for field "${field.name}" (${field.id}) in workspace ${workspaceId} (applicationId: ${field.applicationId})`,
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
application.universalIdentifier ===
|
||||
TWENTY_STANDARD_APPLICATION.universalIdentifier
|
||||
);
|
||||
}
|
||||
}
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
|
||||
import {
|
||||
FieldMetadataType,
|
||||
type FieldMetadataSettings,
|
||||
} from 'twenty-shared/types';
|
||||
import { capitalize } from 'twenty-shared/utils';
|
||||
import { DataSource, Repository } from 'typeorm';
|
||||
|
||||
import { ActiveOrSuspendedWorkspacesMigrationCommandRunner } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspaces-migration.command-runner';
|
||||
import { getFlatFieldsFromFlatObjectMetadata } from 'src/engine/api/graphql/workspace-schema-builder/utils/get-flat-fields-for-flat-object-metadata.util';
|
||||
import { type FlatApplicationCacheMaps } from 'src/engine/core-modules/application/types/flat-application-cache-maps.type';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { computeMorphOrRelationFieldJoinColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-morph-or-relation-field-join-column-name.util';
|
||||
import { findFlatEntityByUniversalIdentifier } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { getMetadataRelatedMetadataNames } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-related-metadata-names.util';
|
||||
import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-morph-or-relation-flat-field-metadata.util';
|
||||
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { type WorkspaceCacheKeyName } from 'src/engine/workspace-cache/types/workspace-cache-key.type';
|
||||
import { getWorkspaceSchemaName } from 'src/engine/workspace-datasource/utils/get-workspace-schema-name.util';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/twenty-standard-application/constants/twenty-standard-applications';
|
||||
|
||||
type RelationFieldMetadataSettings =
|
||||
FieldMetadataSettings<FieldMetadataType.RELATION>;
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:1-17:migrate-task-target-to-morph-relations',
|
||||
description:
|
||||
'Migrate taskTarget relations to morph relation fields and set feature flag',
|
||||
})
|
||||
export class MigrateTaskTargetToMorphRelationsCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
private readonly featureFlagService: FeatureFlagService,
|
||||
@InjectDataSource()
|
||||
private readonly coreDataSource: DataSource,
|
||||
private readonly twentyORMGlobalManager: GlobalWorkspaceOrmManager,
|
||||
protected readonly dataSourceService: DataSourceService,
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager, dataSourceService);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
workspaceId,
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
const isMigrated = await this.featureFlagService.isFeatureEnabled(
|
||||
FeatureFlagKey.IS_TASK_TARGET_MIGRATED,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
this.logger.log(`Migrating taskTarget for workspace ${workspaceId}`);
|
||||
|
||||
if (isMigrated) {
|
||||
this.logger.log(`TaskTarget migration already completed. Skipping...`);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.dryRun) {
|
||||
this.logger.log(
|
||||
`Would have migrated taskTarget for workspace ${workspaceId}. Skipping...`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const queryRunner = this.coreDataSource.createQueryRunner();
|
||||
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
try {
|
||||
const schemaName = getWorkspaceSchemaName(workspaceId);
|
||||
const tableName = 'taskTarget';
|
||||
|
||||
const {
|
||||
flatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps,
|
||||
flatApplicationMaps,
|
||||
} = await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatObjectMetadataMaps',
|
||||
'flatFieldMetadataMaps',
|
||||
'flatApplicationMaps',
|
||||
]);
|
||||
|
||||
const taskTargetFieldUniversalIdentifiers = new Set<string>([
|
||||
STANDARD_OBJECTS.taskTarget.fields.targetPerson.universalIdentifier,
|
||||
STANDARD_OBJECTS.taskTarget.fields.targetCompany.universalIdentifier,
|
||||
STANDARD_OBJECTS.taskTarget.fields.targetOpportunity
|
||||
.universalIdentifier,
|
||||
]);
|
||||
|
||||
const taskTargetObjectMetadata =
|
||||
findFlatEntityByUniversalIdentifier<FlatObjectMetadata>({
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
universalIdentifier: STANDARD_OBJECTS.taskTarget.universalIdentifier,
|
||||
});
|
||||
|
||||
if (!taskTargetObjectMetadata) {
|
||||
this.logger.error(
|
||||
`🟥 ${tableName} object metadata not found for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const taskTargetFieldMetadatas = getFlatFieldsFromFlatObjectMetadata(
|
||||
taskTargetObjectMetadata,
|
||||
flatFieldMetadataMaps,
|
||||
);
|
||||
|
||||
const taskTargetRelationFields = taskTargetFieldMetadatas
|
||||
.filter(isMorphOrRelationFlatFieldMetadata)
|
||||
.filter((field) => field.type === FieldMetadataType.RELATION)
|
||||
.filter((field) => {
|
||||
const isStandardAppField = this.isTwentyStandardApplicationField({
|
||||
field,
|
||||
flatApplicationMaps,
|
||||
workspaceId,
|
||||
});
|
||||
const isStandardTarget =
|
||||
isStandardAppField &&
|
||||
taskTargetFieldUniversalIdentifiers.has(field.universalIdentifier);
|
||||
const targetObjectMetadata = field.relationTargetObjectMetadataId
|
||||
? findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityMaps: flatObjectMetadataMaps,
|
||||
flatEntityId: field.relationTargetObjectMetadataId,
|
||||
})
|
||||
: undefined;
|
||||
const isCustomTarget =
|
||||
!isStandardAppField && targetObjectMetadata?.isCustom === true;
|
||||
|
||||
return isStandardTarget || isCustomTarget;
|
||||
});
|
||||
|
||||
const fieldMigrations = taskTargetRelationFields.map((field) => {
|
||||
const newFieldName = `target${capitalize(field.name)}`;
|
||||
const relationSettings: RelationFieldMetadataSettings = field.settings;
|
||||
const oldJoinColumnName =
|
||||
relationSettings?.joinColumnName ??
|
||||
computeMorphOrRelationFieldJoinColumnName({ name: field.name });
|
||||
const newJoinColumnName = computeMorphOrRelationFieldJoinColumnName({
|
||||
name: newFieldName,
|
||||
});
|
||||
|
||||
return {
|
||||
field,
|
||||
newFieldName,
|
||||
oldJoinColumnName,
|
||||
newJoinColumnName,
|
||||
};
|
||||
});
|
||||
|
||||
// Rename columns
|
||||
for (const { oldJoinColumnName, newJoinColumnName } of fieldMigrations) {
|
||||
if (oldJoinColumnName === newJoinColumnName) {
|
||||
this.logger.log(
|
||||
`Column "${oldJoinColumnName}" already renamed. Skipping...`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "${schemaName}"."${tableName}"
|
||||
RENAME COLUMN "${oldJoinColumnName}" TO "${newJoinColumnName}"`,
|
||||
);
|
||||
this.logger.log(
|
||||
`Renamed column "${oldJoinColumnName}" to "${newJoinColumnName}" for "${tableName}"`,
|
||||
);
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Error renaming column "${oldJoinColumnName}" to "${newJoinColumnName}" for "${tableName}" in workspace ${workspaceId}`,
|
||||
error,
|
||||
);
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.log(`✅ Successfully migrated ${tableName} records`);
|
||||
|
||||
const morphId =
|
||||
STANDARD_OBJECTS.taskTarget.morphIds.targetMorphId.morphId;
|
||||
|
||||
// Update field metadata
|
||||
for (const {
|
||||
field: fieldToMigrate,
|
||||
newFieldName,
|
||||
newJoinColumnName,
|
||||
} of fieldMigrations) {
|
||||
const settings = {
|
||||
...fieldToMigrate.settings,
|
||||
joinColumnName: newJoinColumnName,
|
||||
};
|
||||
|
||||
try {
|
||||
const result = await queryRunner.query(
|
||||
`UPDATE core."fieldMetadata"
|
||||
SET name = $1, type = $5, "morphId" = $3, settings = $4
|
||||
WHERE id = $2`,
|
||||
[
|
||||
newFieldName,
|
||||
fieldToMigrate.id,
|
||||
morphId,
|
||||
settings,
|
||||
FieldMetadataType.MORPH_RELATION,
|
||||
],
|
||||
);
|
||||
|
||||
const rowsUpdated = result[1] || 0;
|
||||
|
||||
if (rowsUpdated > 0) {
|
||||
this.logger.log(
|
||||
`Updated fieldMetadata: ${fieldToMigrate.name} → ${newFieldName} (type: MORPH_RELATION)`,
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(
|
||||
`Error updating fieldMetadata for field "${fieldToMigrate.name}" in workspace ${workspaceId}`,
|
||||
error,
|
||||
);
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.log(`✅ Successfully migrated ${tableName} fieldmetadata`);
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
|
||||
await this.featureFlagService.enableFeatureFlags(
|
||||
[FeatureFlagKey.IS_TASK_TARGET_MIGRATED],
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
const relatedMetadataNames =
|
||||
getMetadataRelatedMetadataNames('fieldMetadata');
|
||||
const relatedCacheKeysToInvalidate: WorkspaceCacheKeyName[] =
|
||||
relatedMetadataNames.map(getMetadataFlatEntityMapsKey);
|
||||
const cacheKeysToInvalidate: WorkspaceCacheKeyName[] = [
|
||||
'flatFieldMetadataMaps',
|
||||
...relatedCacheKeysToInvalidate,
|
||||
'featureFlagsMap',
|
||||
];
|
||||
|
||||
this.logger.log(
|
||||
`Invalidating caches: ${cacheKeysToInvalidate.join(' ')}`,
|
||||
);
|
||||
|
||||
await this.workspaceCacheService.invalidateAndRecompute(
|
||||
workspaceId,
|
||||
cacheKeysToInvalidate,
|
||||
);
|
||||
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
this.logger.log(`Cache flushed`);
|
||||
|
||||
this.logger.log(
|
||||
`Set IS_TASK_TARGET_MIGRATED feature flag for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
this.logger.log(`Flush cache for workspace ${workspaceId}`);
|
||||
await this.workspaceCacheStorageService.flush(workspaceId);
|
||||
} catch (error) {
|
||||
if (queryRunner.isTransactionActive) {
|
||||
await queryRunner.rollbackTransaction();
|
||||
this.logger.error(
|
||||
`Error migrating taskTarget to morph relations (rolled transaction back on ${workspaceId})`,
|
||||
error,
|
||||
);
|
||||
} else {
|
||||
this.logger.error(
|
||||
`Error migrating taskTarget to morph relations after commit on ${workspaceId}`,
|
||||
error,
|
||||
);
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
private isTwentyStandardApplicationField({
|
||||
field,
|
||||
flatApplicationMaps,
|
||||
workspaceId,
|
||||
}: {
|
||||
field: { id: string; name: string; applicationId: string };
|
||||
flatApplicationMaps: FlatApplicationCacheMaps;
|
||||
workspaceId: string;
|
||||
}): boolean {
|
||||
const application = flatApplicationMaps.byId[field.applicationId];
|
||||
|
||||
if (!application) {
|
||||
this.logger.error(
|
||||
`🟥 Application not found for field "${field.name}" (${field.id}) in workspace ${workspaceId} (applicationId: ${field.applicationId})`,
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return (
|
||||
application.universalIdentifier ===
|
||||
TWENTY_STANDARD_APPLICATION.universalIdentifier
|
||||
);
|
||||
}
|
||||
}
|
||||
+10
@@ -6,7 +6,9 @@ import { DeleteFileRecordsCommand } from 'src/database/commands/upgrade-version-
|
||||
import { IdentifyWebhookMetadataCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-identify-webhook-metadata.command';
|
||||
import { MakeWebhookUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-make-webhook-universal-identifier-and-application-id-not-nullable-migration.command';
|
||||
import { MigrateAttachmentToMorphRelationsCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-migrate-attachment-to-morph-relations.command';
|
||||
import { MigrateNoteTargetToMorphRelationsCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-migrate-note-target-to-morph-relations.command';
|
||||
import { MigrateSendEmailRecipientsCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-migrate-send-email-recipients.command';
|
||||
import { MigrateTaskTargetToMorphRelationsCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-migrate-task-target-to-morph-relations.command';
|
||||
import { MigrateWorkflowCodeStepsCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-migrate-workflow-code-steps.command';
|
||||
import { SeedWorkflowV1_16Command } from 'src/database/commands/upgrade-version-command/1-17/1-17-seed-workflow-v1-16.command';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
@@ -30,6 +32,8 @@ import { GlobalWorkspaceDataSourceModule } from 'src/engine/twenty-orm/global-wo
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
|
||||
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
|
||||
import { NoteTargetWorkspaceEntity } from 'src/modules/note/standard-objects/note-target.workspace-entity';
|
||||
import { TaskTargetWorkspaceEntity } from 'src/modules/task/standard-objects/task-target.workspace-entity';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -40,6 +44,8 @@ import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objec
|
||||
FeatureFlagEntity,
|
||||
AttachmentWorkspaceEntity,
|
||||
WebhookEntity,
|
||||
NoteTargetWorkspaceEntity,
|
||||
TaskTargetWorkspaceEntity,
|
||||
FileEntity,
|
||||
LogicFunctionEntity,
|
||||
]),
|
||||
@@ -59,6 +65,8 @@ import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objec
|
||||
],
|
||||
providers: [
|
||||
MigrateAttachmentToMorphRelationsCommand,
|
||||
MigrateNoteTargetToMorphRelationsCommand,
|
||||
MigrateTaskTargetToMorphRelationsCommand,
|
||||
IdentifyWebhookMetadataCommand,
|
||||
MakeWebhookUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
|
||||
DeleteFileRecordsCommand,
|
||||
@@ -69,6 +77,8 @@ import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objec
|
||||
],
|
||||
exports: [
|
||||
MigrateAttachmentToMorphRelationsCommand,
|
||||
MigrateNoteTargetToMorphRelationsCommand,
|
||||
MigrateTaskTargetToMorphRelationsCommand,
|
||||
IdentifyWebhookMetadataCommand,
|
||||
MakeWebhookUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
|
||||
DeleteFileRecordsCommand,
|
||||
|
||||
+6
@@ -14,6 +14,8 @@ import { DeleteFileRecordsCommand } from 'src/database/commands/upgrade-version-
|
||||
import { IdentifyWebhookMetadataCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-identify-webhook-metadata.command';
|
||||
import { MakeWebhookUniversalIdentifierAndApplicationIdNotNullableMigrationCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-make-webhook-universal-identifier-and-application-id-not-nullable-migration.command';
|
||||
import { MigrateAttachmentToMorphRelationsCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-migrate-attachment-to-morph-relations.command';
|
||||
import { MigrateNoteTargetToMorphRelationsCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-migrate-note-target-to-morph-relations.command';
|
||||
import { MigrateTaskTargetToMorphRelationsCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-migrate-task-target-to-morph-relations.command';
|
||||
import { MigrateWorkflowCodeStepsCommand } from 'src/database/commands/upgrade-version-command/1-17/1-17-migrate-workflow-code-steps.command';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
@@ -38,6 +40,8 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
protected readonly backfillApplicationPackageFilesCommand: BackfillApplicationPackageFilesCommand,
|
||||
protected readonly deleteFileRecordsCommand: DeleteFileRecordsCommand,
|
||||
protected readonly migrateAttachmentToMorphRelationsCommand: MigrateAttachmentToMorphRelationsCommand,
|
||||
protected readonly migrateNoteTargetToMorphRelationsCommand: MigrateNoteTargetToMorphRelationsCommand,
|
||||
protected readonly migrateTaskTargetToMorphRelationsCommand: MigrateTaskTargetToMorphRelationsCommand,
|
||||
protected readonly identifyWebhookMetadataCommand: IdentifyWebhookMetadataCommand,
|
||||
protected readonly makeWebhookUniversalIdentifierAndApplicationIdNotNullableMigrationCommand: MakeWebhookUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
|
||||
protected readonly migrateWorkflowCodeStepsCommand: MigrateWorkflowCodeStepsCommand,
|
||||
@@ -54,6 +58,8 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
|
||||
const commands_1170: VersionCommands = [
|
||||
this.migrateAttachmentToMorphRelationsCommand,
|
||||
this.migrateNoteTargetToMorphRelationsCommand,
|
||||
this.migrateTaskTargetToMorphRelationsCommand,
|
||||
this.identifyWebhookMetadataCommand,
|
||||
this
|
||||
.makeWebhookUniversalIdentifierAndApplicationIdNotNullableMigrationCommand,
|
||||
|
||||
+2
@@ -12,6 +12,8 @@ export enum FeatureFlagKey {
|
||||
IS_DASHBOARD_V2_ENABLED = 'IS_DASHBOARD_V2_ENABLED',
|
||||
IS_TIMELINE_ACTIVITY_MIGRATED = 'IS_TIMELINE_ACTIVITY_MIGRATED',
|
||||
IS_ATTACHMENT_MIGRATED = 'IS_ATTACHMENT_MIGRATED',
|
||||
IS_NOTE_TARGET_MIGRATED = 'IS_NOTE_TARGET_MIGRATED',
|
||||
IS_TASK_TARGET_MIGRATED = 'IS_TASK_TARGET_MIGRATED',
|
||||
IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED = 'IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED',
|
||||
IS_JUNCTION_RELATIONS_ENABLED = 'IS_JUNCTION_RELATIONS_ENABLED',
|
||||
IS_SSE_DB_EVENTS_ENABLED = 'IS_SSE_DB_EVENTS_ENABLED',
|
||||
|
||||
+6
-2
@@ -32,8 +32,8 @@ const morphIdByRelationObjectNameSingular = {
|
||||
STANDARD_OBJECTS.timelineActivity.morphIds.targetMorphId.morphId,
|
||||
favorite: null,
|
||||
attachment: STANDARD_OBJECTS.attachment.morphIds.targetMorphId.morphId,
|
||||
noteTarget: null,
|
||||
taskTarget: null,
|
||||
noteTarget: STANDARD_OBJECTS.noteTarget.morphIds.targetMorphId.morphId,
|
||||
taskTarget: STANDARD_OBJECTS.taskTarget.morphIds.targetMorphId.morphId,
|
||||
} satisfies Record<
|
||||
(typeof DEFAULT_RELATIONS_OBJECTS_STANDARD_IDS)[number],
|
||||
string | null
|
||||
@@ -97,6 +97,10 @@ export const buildDefaultRelationFlatFieldMetadatasForCustomObject = ({
|
||||
]) ||
|
||||
(objectMetadataNameSingular === 'attachment' &&
|
||||
existingFeatureFlagsMap[FeatureFlagKey.IS_ATTACHMENT_MIGRATED]) ||
|
||||
(objectMetadataNameSingular === 'noteTarget' &&
|
||||
existingFeatureFlagsMap[FeatureFlagKey.IS_NOTE_TARGET_MIGRATED]) ||
|
||||
(objectMetadataNameSingular === 'taskTarget' &&
|
||||
existingFeatureFlagsMap[FeatureFlagKey.IS_TASK_TARGET_MIGRATED]) ||
|
||||
false;
|
||||
const isObjectMigratedToMorphRelations =
|
||||
isObjectMigratedFromOlderReleases || isFeatureFlagEnabled;
|
||||
|
||||
+2
@@ -231,6 +231,8 @@ describe('WorkspaceEntityManager', () => {
|
||||
IS_EMAILING_DOMAIN_ENABLED: false,
|
||||
IS_DASHBOARD_V2_ENABLED: false,
|
||||
IS_ATTACHMENT_MIGRATED: false,
|
||||
IS_NOTE_TARGET_MIGRATED: false,
|
||||
IS_TASK_TARGET_MIGRATED: false,
|
||||
IS_TIMELINE_ACTIVITY_MIGRATED: false,
|
||||
IS_GLOBAL_WORKSPACE_DATASOURCE_ENABLED: false,
|
||||
IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED: false,
|
||||
|
||||
+10
@@ -66,6 +66,16 @@ export const seedFeatureFlags = async ({
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_NOTE_TARGET_MIGRATED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_TASK_TARGET_MIGRATED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_ROW_LEVEL_PERMISSION_PREDICATES_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
|
||||
+12
-12
@@ -5,17 +5,17 @@ import { PERSON_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/da
|
||||
type NoteTargetDataSeed = {
|
||||
id: string;
|
||||
noteId: string | null;
|
||||
personId: string | null;
|
||||
companyId: string | null;
|
||||
opportunityId: string | null;
|
||||
targetPersonId: string | null;
|
||||
targetCompanyId: string | null;
|
||||
targetOpportunityId: string | null;
|
||||
};
|
||||
|
||||
export const NOTE_TARGET_DATA_SEED_COLUMNS: (keyof NoteTargetDataSeed)[] = [
|
||||
'id',
|
||||
'noteId',
|
||||
'personId',
|
||||
'companyId',
|
||||
'opportunityId',
|
||||
'targetPersonId',
|
||||
'targetCompanyId',
|
||||
'targetOpportunityId',
|
||||
];
|
||||
|
||||
const GENERATE_NOTE_TARGET_IDS = (): Record<string, string> => {
|
||||
@@ -47,12 +47,12 @@ const GENERATE_NOTE_TARGET_SEEDS = (): NoteTargetDataSeed[] => {
|
||||
NOTE_TARGET_SEEDS.push({
|
||||
id: NOTE_TARGET_DATA_SEED_IDS[`ID_${INDEX}`],
|
||||
noteId: NOTE_DATA_SEED_IDS[`ID_${INDEX}`],
|
||||
personId:
|
||||
targetPersonId:
|
||||
PERSON_DATA_SEED_IDS[
|
||||
`ID_${INDEX}` as keyof typeof PERSON_DATA_SEED_IDS
|
||||
],
|
||||
companyId: null,
|
||||
opportunityId: null,
|
||||
targetCompanyId: null,
|
||||
targetOpportunityId: null,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -62,12 +62,12 @@ const GENERATE_NOTE_TARGET_SEEDS = (): NoteTargetDataSeed[] => {
|
||||
NOTE_TARGET_SEEDS.push({
|
||||
id: NOTE_TARGET_DATA_SEED_IDS[`ID_${INDEX}`],
|
||||
noteId: NOTE_DATA_SEED_IDS[`ID_${INDEX}`],
|
||||
personId: null,
|
||||
companyId:
|
||||
targetPersonId: null,
|
||||
targetCompanyId:
|
||||
COMPANY_DATA_SEED_IDS[
|
||||
`ID_${COMPANY_INDEX}` as keyof typeof COMPANY_DATA_SEED_IDS
|
||||
],
|
||||
opportunityId: null,
|
||||
targetOpportunityId: null,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+12
-12
@@ -5,17 +5,17 @@ import { TASK_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data
|
||||
type TaskTargetDataSeed = {
|
||||
id: string;
|
||||
taskId: string | null;
|
||||
personId: string | null;
|
||||
companyId: string | null;
|
||||
opportunityId: string | null;
|
||||
targetPersonId: string | null;
|
||||
targetCompanyId: string | null;
|
||||
targetOpportunityId: string | null;
|
||||
};
|
||||
|
||||
export const TASK_TARGET_DATA_SEED_COLUMNS: (keyof TaskTargetDataSeed)[] = [
|
||||
'id',
|
||||
'taskId',
|
||||
'personId',
|
||||
'companyId',
|
||||
'opportunityId',
|
||||
'targetPersonId',
|
||||
'targetCompanyId',
|
||||
'targetOpportunityId',
|
||||
];
|
||||
|
||||
// Generate all task target IDs
|
||||
@@ -52,12 +52,12 @@ const GENERATE_TASK_TARGET_SEEDS = (): TaskTargetDataSeed[] => {
|
||||
TASK_TARGET_SEEDS.push({
|
||||
id: TASK_TARGET_DATA_SEED_IDS[`ID_${INDEX}`],
|
||||
taskId: TASK_DATA_SEED_IDS[`ID_${INDEX}`],
|
||||
personId:
|
||||
targetPersonId:
|
||||
PERSON_DATA_SEED_IDS[
|
||||
`ID_${INDEX}` as keyof typeof PERSON_DATA_SEED_IDS
|
||||
],
|
||||
companyId: null,
|
||||
opportunityId: null,
|
||||
targetCompanyId: null,
|
||||
targetOpportunityId: null,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -68,12 +68,12 @@ const GENERATE_TASK_TARGET_SEEDS = (): TaskTargetDataSeed[] => {
|
||||
TASK_TARGET_SEEDS.push({
|
||||
id: TASK_TARGET_DATA_SEED_IDS[`ID_${INDEX}`],
|
||||
taskId: TASK_DATA_SEED_IDS[`ID_${INDEX}`],
|
||||
personId: null,
|
||||
companyId:
|
||||
targetPersonId: null,
|
||||
targetCompanyId:
|
||||
COMPANY_DATA_SEED_IDS[
|
||||
`ID_${COMPANY_INDEX}` as keyof typeof COMPANY_DATA_SEED_IDS
|
||||
],
|
||||
opportunityId: null,
|
||||
targetOpportunityId: null,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -463,9 +463,9 @@ export class TimelineActivitySeederService {
|
||||
}
|
||||
|
||||
const targetChecks = [
|
||||
{ id: noteTargetSeed.personId, type: 'person' },
|
||||
{ id: noteTargetSeed.companyId, type: 'company' },
|
||||
{ id: noteTargetSeed.opportunityId, type: 'opportunity' },
|
||||
{ id: noteTargetSeed.targetPersonId, type: 'person' },
|
||||
{ id: noteTargetSeed.targetCompanyId, type: 'company' },
|
||||
{ id: noteTargetSeed.targetOpportunityId, type: 'opportunity' },
|
||||
];
|
||||
|
||||
for (const { id, type } of targetChecks) {
|
||||
@@ -487,9 +487,9 @@ export class TimelineActivitySeederService {
|
||||
}
|
||||
|
||||
const targetChecks = [
|
||||
{ id: taskTargetSeed.personId, type: 'person' },
|
||||
{ id: taskTargetSeed.companyId, type: 'company' },
|
||||
{ id: taskTargetSeed.opportunityId, type: 'opportunity' },
|
||||
{ id: taskTargetSeed.targetPersonId, type: 'person' },
|
||||
{ id: taskTargetSeed.targetCompanyId, type: 'company' },
|
||||
{ id: taskTargetSeed.targetOpportunityId, type: 'opportunity' },
|
||||
];
|
||||
|
||||
for (const { id, type } of targetChecks) {
|
||||
|
||||
+10
-10
@@ -979,9 +979,6 @@ exports[`getStandardObjectMetadataRelatedEntityIds should return standard object
|
||||
},
|
||||
"noteTarget": {
|
||||
"fields": {
|
||||
"company": {
|
||||
"id": "00000000-0000-0000-0000-000000000306",
|
||||
},
|
||||
"createdAt": {
|
||||
"id": "00000000-0000-0000-0000-000000000301",
|
||||
},
|
||||
@@ -994,10 +991,13 @@ exports[`getStandardObjectMetadataRelatedEntityIds should return standard object
|
||||
"note": {
|
||||
"id": "00000000-0000-0000-0000-000000000304",
|
||||
},
|
||||
"opportunity": {
|
||||
"targetCompany": {
|
||||
"id": "00000000-0000-0000-0000-000000000306",
|
||||
},
|
||||
"targetOpportunity": {
|
||||
"id": "00000000-0000-0000-0000-000000000307",
|
||||
},
|
||||
"person": {
|
||||
"targetPerson": {
|
||||
"id": "00000000-0000-0000-0000-000000000305",
|
||||
},
|
||||
"updatedAt": {
|
||||
@@ -1417,9 +1417,6 @@ exports[`getStandardObjectMetadataRelatedEntityIds should return standard object
|
||||
},
|
||||
"taskTarget": {
|
||||
"fields": {
|
||||
"company": {
|
||||
"id": "00000000-0000-0000-0000-000000000440",
|
||||
},
|
||||
"createdAt": {
|
||||
"id": "00000000-0000-0000-0000-000000000435",
|
||||
},
|
||||
@@ -1429,10 +1426,13 @@ exports[`getStandardObjectMetadataRelatedEntityIds should return standard object
|
||||
"id": {
|
||||
"id": "00000000-0000-0000-0000-000000000434",
|
||||
},
|
||||
"opportunity": {
|
||||
"targetCompany": {
|
||||
"id": "00000000-0000-0000-0000-000000000440",
|
||||
},
|
||||
"targetOpportunity": {
|
||||
"id": "00000000-0000-0000-0000-000000000441",
|
||||
},
|
||||
"person": {
|
||||
"targetPerson": {
|
||||
"id": "00000000-0000-0000-0000-000000000439",
|
||||
},
|
||||
"task": {
|
||||
|
||||
+2
-2
@@ -393,7 +393,7 @@ export const buildCompanyStandardFlatFieldMetadatas = ({
|
||||
isUIReadOnly: true,
|
||||
isNullable: true,
|
||||
targetObjectName: 'taskTarget',
|
||||
targetFieldName: 'company',
|
||||
targetFieldName: 'targetCompany',
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
@@ -416,7 +416,7 @@ export const buildCompanyStandardFlatFieldMetadatas = ({
|
||||
isUIReadOnly: true,
|
||||
isNullable: true,
|
||||
targetObjectName: 'noteTarget',
|
||||
targetFieldName: 'company',
|
||||
targetFieldName: 'targetCompany',
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
|
||||
+16
-15
@@ -1,3 +1,4 @@
|
||||
import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
|
||||
import {
|
||||
DateDisplayFormat,
|
||||
FieldMetadataType,
|
||||
@@ -133,13 +134,13 @@ export const buildNoteTargetStandardFlatFieldMetadatas = ({
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
person: createStandardRelationFieldFlatMetadata({
|
||||
targetPerson: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'person',
|
||||
type: FieldMetadataType.MORPH_RELATION,
|
||||
morphId: STANDARD_OBJECTS.noteTarget.morphIds.targetMorphId.morphId,
|
||||
fieldName: 'targetPerson',
|
||||
label: 'Person',
|
||||
description: 'NoteTarget person',
|
||||
icon: 'IconUser',
|
||||
@@ -150,7 +151,7 @@ export const buildNoteTargetStandardFlatFieldMetadatas = ({
|
||||
settings: {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
joinColumnName: 'personId',
|
||||
joinColumnName: 'targetPersonId',
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
@@ -158,13 +159,13 @@ export const buildNoteTargetStandardFlatFieldMetadatas = ({
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
company: createStandardRelationFieldFlatMetadata({
|
||||
targetCompany: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'company',
|
||||
type: FieldMetadataType.MORPH_RELATION,
|
||||
morphId: STANDARD_OBJECTS.noteTarget.morphIds.targetMorphId.morphId,
|
||||
fieldName: 'targetCompany',
|
||||
label: 'Company',
|
||||
description: 'NoteTarget company',
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
@@ -175,7 +176,7 @@ export const buildNoteTargetStandardFlatFieldMetadatas = ({
|
||||
settings: {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
joinColumnName: 'companyId',
|
||||
joinColumnName: 'targetCompanyId',
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
@@ -183,13 +184,13 @@ export const buildNoteTargetStandardFlatFieldMetadatas = ({
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
opportunity: createStandardRelationFieldFlatMetadata({
|
||||
targetOpportunity: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'opportunity',
|
||||
type: FieldMetadataType.MORPH_RELATION,
|
||||
morphId: STANDARD_OBJECTS.noteTarget.morphIds.targetMorphId.morphId,
|
||||
fieldName: 'targetOpportunity',
|
||||
label: 'Opportunity',
|
||||
description: 'NoteTarget opportunity',
|
||||
icon: 'IconTargetArrow',
|
||||
@@ -200,7 +201,7 @@ export const buildNoteTargetStandardFlatFieldMetadatas = ({
|
||||
settings: {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
joinColumnName: 'opportunityId',
|
||||
joinColumnName: 'targetOpportunityId',
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
|
||||
+2
-2
@@ -363,7 +363,7 @@ export const buildOpportunityStandardFlatFieldMetadatas = ({
|
||||
isUIReadOnly: true,
|
||||
isNullable: true,
|
||||
targetObjectName: 'taskTarget',
|
||||
targetFieldName: 'opportunity',
|
||||
targetFieldName: 'targetOpportunity',
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
@@ -386,7 +386,7 @@ export const buildOpportunityStandardFlatFieldMetadatas = ({
|
||||
isUIReadOnly: true,
|
||||
isNullable: true,
|
||||
targetObjectName: 'noteTarget',
|
||||
targetFieldName: 'opportunity',
|
||||
targetFieldName: 'targetOpportunity',
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
|
||||
+2
-2
@@ -370,7 +370,7 @@ export const buildPersonStandardFlatFieldMetadatas = ({
|
||||
isUIReadOnly: true,
|
||||
isNullable: true,
|
||||
targetObjectName: 'taskTarget',
|
||||
targetFieldName: 'person',
|
||||
targetFieldName: 'targetPerson',
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
@@ -393,7 +393,7 @@ export const buildPersonStandardFlatFieldMetadatas = ({
|
||||
isUIReadOnly: true,
|
||||
isNullable: true,
|
||||
targetObjectName: 'noteTarget',
|
||||
targetFieldName: 'person',
|
||||
targetFieldName: 'targetPerson',
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
|
||||
+16
-15
@@ -1,3 +1,4 @@
|
||||
import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
|
||||
import {
|
||||
DateDisplayFormat,
|
||||
FieldMetadataType,
|
||||
@@ -133,13 +134,13 @@ export const buildTaskTargetStandardFlatFieldMetadatas = ({
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
person: createStandardRelationFieldFlatMetadata({
|
||||
targetPerson: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'person',
|
||||
type: FieldMetadataType.MORPH_RELATION,
|
||||
morphId: STANDARD_OBJECTS.taskTarget.morphIds.targetMorphId.morphId,
|
||||
fieldName: 'targetPerson',
|
||||
label: 'Person',
|
||||
description: 'TaskTarget person',
|
||||
icon: 'IconUser',
|
||||
@@ -150,7 +151,7 @@ export const buildTaskTargetStandardFlatFieldMetadatas = ({
|
||||
settings: {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
joinColumnName: 'personId',
|
||||
joinColumnName: 'targetPersonId',
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
@@ -158,13 +159,13 @@ export const buildTaskTargetStandardFlatFieldMetadatas = ({
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
company: createStandardRelationFieldFlatMetadata({
|
||||
targetCompany: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'company',
|
||||
type: FieldMetadataType.MORPH_RELATION,
|
||||
morphId: STANDARD_OBJECTS.taskTarget.morphIds.targetMorphId.morphId,
|
||||
fieldName: 'targetCompany',
|
||||
label: 'Company',
|
||||
description: 'TaskTarget company',
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
@@ -175,7 +176,7 @@ export const buildTaskTargetStandardFlatFieldMetadatas = ({
|
||||
settings: {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
joinColumnName: 'companyId',
|
||||
joinColumnName: 'targetCompanyId',
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
@@ -183,13 +184,13 @@ export const buildTaskTargetStandardFlatFieldMetadatas = ({
|
||||
twentyStandardApplicationId,
|
||||
now,
|
||||
}),
|
||||
opportunity: createStandardRelationFieldFlatMetadata({
|
||||
targetOpportunity: createStandardRelationFieldFlatMetadata({
|
||||
objectName,
|
||||
workspaceId,
|
||||
context: {
|
||||
type: FieldMetadataType.RELATION,
|
||||
morphId: null,
|
||||
fieldName: 'opportunity',
|
||||
type: FieldMetadataType.MORPH_RELATION,
|
||||
morphId: STANDARD_OBJECTS.taskTarget.morphIds.targetMorphId.morphId,
|
||||
fieldName: 'targetOpportunity',
|
||||
label: 'Opportunity',
|
||||
description: 'TaskTarget opportunity',
|
||||
icon: 'IconTargetArrow',
|
||||
@@ -200,7 +201,7 @@ export const buildTaskTargetStandardFlatFieldMetadatas = ({
|
||||
settings: {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
onDelete: RelationOnDeleteAction.CASCADE,
|
||||
joinColumnName: 'opportunityId',
|
||||
joinColumnName: 'targetOpportunityId',
|
||||
},
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
|
||||
+3
-3
@@ -33,7 +33,7 @@ export const buildNoteTargetStandardFlatIndexMetadatas = ({
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'personIdIndex',
|
||||
relatedFieldNames: ['person'],
|
||||
relatedFieldNames: ['targetPerson'],
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
@@ -45,7 +45,7 @@ export const buildNoteTargetStandardFlatIndexMetadatas = ({
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'companyIdIndex',
|
||||
relatedFieldNames: ['company'],
|
||||
relatedFieldNames: ['targetCompany'],
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
@@ -57,7 +57,7 @@ export const buildNoteTargetStandardFlatIndexMetadatas = ({
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'opportunityIdIndex',
|
||||
relatedFieldNames: ['opportunity'],
|
||||
relatedFieldNames: ['targetOpportunity'],
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
+3
-3
@@ -33,7 +33,7 @@ export const buildTaskTargetStandardFlatIndexMetadatas = ({
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'personIdIndex',
|
||||
relatedFieldNames: ['person'],
|
||||
relatedFieldNames: ['targetPerson'],
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
@@ -45,7 +45,7 @@ export const buildTaskTargetStandardFlatIndexMetadatas = ({
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'companyIdIndex',
|
||||
relatedFieldNames: ['company'],
|
||||
relatedFieldNames: ['targetCompany'],
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
@@ -57,7 +57,7 @@ export const buildTaskTargetStandardFlatIndexMetadatas = ({
|
||||
workspaceId,
|
||||
context: {
|
||||
indexName: 'opportunityIdIndex',
|
||||
relatedFieldNames: ['opportunity'],
|
||||
relatedFieldNames: ['targetOpportunity'],
|
||||
},
|
||||
standardObjectMetadataRelatedEntityIds,
|
||||
dependencyFlatEntityMaps,
|
||||
|
||||
+2
@@ -3,5 +3,7 @@ import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/featu
|
||||
export const DEFAULT_FEATURE_FLAGS = [
|
||||
FeatureFlagKey.IS_TIMELINE_ACTIVITY_MIGRATED,
|
||||
FeatureFlagKey.IS_ATTACHMENT_MIGRATED,
|
||||
FeatureFlagKey.IS_NOTE_TARGET_MIGRATED,
|
||||
FeatureFlagKey.IS_TASK_TARGET_MIGRATED,
|
||||
FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_ENABLED,
|
||||
] as const satisfies FeatureFlagKey[];
|
||||
|
||||
+591
@@ -0,0 +1,591 @@
|
||||
/**
|
||||
* /!\ DO NOT EDIT THE IDS OF THIS FILE /!\
|
||||
* This file contains static ids for standard objects.
|
||||
* These ids are used to identify standard objects in the database and compare them even when renamed.
|
||||
* For readability keys can be edited but the values should not be changed.
|
||||
*/
|
||||
|
||||
// TODO: check if this can be deleted
|
||||
export const ACTIVITY_TARGET_STANDARD_FIELD_IDS = {
|
||||
activity: '20202020-ca58-478c-a4f5-ae825671c30e',
|
||||
person: '20202020-4afd-4ae7-99c2-de57d795a93f',
|
||||
company: '20202020-7cc0-44a1-8068-f11171fdd02e',
|
||||
opportunity: '20202020-1fc2-4af1-8c91-7901ee0fd38b',
|
||||
custom: '20202020-7f21-442f-94be-32462281b1ca',
|
||||
} as const;
|
||||
|
||||
// TODO: check if this can be deleted
|
||||
export const ACTIVITY_STANDARD_FIELD_IDS = {
|
||||
title: '20202020-24a1-4d94-a071-617f3eeed7b0',
|
||||
body: '20202020-209b-440a-b2a8-043fa36a7d37',
|
||||
type: '20202020-0f2b-4aab-8827-ee5d3f07d993',
|
||||
reminderAt: '20202020-eb06-43e2-ba06-336be0e665a3',
|
||||
dueAt: '20202020-0336-4511-ba79-565b12801bd9',
|
||||
completedAt: '20202020-0f4d-4fca-9f2f-6309d9ecb85f',
|
||||
activityTargets: '20202020-7253-42cb-8586-8cf950e70b79',
|
||||
attachments: '20202020-5547-4197-bc2e-a07dfc4559ca',
|
||||
comments: '20202020-6b2e-4d29-bbd1-ecddb330e71a',
|
||||
author: '20202020-455f-44f2-8e89-1b0ef01cb7fb',
|
||||
assignee: '20202020-4259-48e4-9e77-6b92991906d5',
|
||||
} as const;
|
||||
|
||||
export const ATTACHMENT_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-87a5-48f8-bbf7-ade388825a57',
|
||||
fullPath: '20202020-0d19-453d-8e8d-fbcda8ca3747',
|
||||
type: '20202020-a417-49b8-a40b-f6a7874caa0d',
|
||||
fileCategory: '20202020-8c3f-4d9e-9a1b-2e5f7a8c9d0e',
|
||||
createdBy: '395be3bd-a5c9-463d-aafe-9bc3bbec3f15',
|
||||
updatedBy: '376239d1-3e65-4cb6-b5d8-e0917d43cc93',
|
||||
author: '20202020-6501-4ac5-a4ef-b2f8522ef6cd',
|
||||
activity: '20202020-b569-481b-a13f-9b94e47e54fe',
|
||||
targetTask: '20202020-51e5-4621-9cf8-215487951c4b',
|
||||
targetNote: '20202020-4f4b-4503-a6fc-6b982f3dffb5',
|
||||
targetPerson: '20202020-0158-4aa2-965c-5cdafe21ffa2',
|
||||
targetCompany: '20202020-ceab-4a28-b546-73b06b4c08d5',
|
||||
targetOpportunity: '20202020-7374-499d-bea3-9354890755b5',
|
||||
targetDashboard: '20202020-5324-43f3-9dbf-1a33e7de0ce6',
|
||||
targetWorkflow: '20202020-f1e8-4c9d-8a7b-3f5e1d2c9a8b',
|
||||
targetCustom: '20202020-302d-43b3-9aea-aa4f89282a9f',
|
||||
targetMorphId: '20202020-f634-435d-ab8d-e1168b375c69',
|
||||
} as const;
|
||||
|
||||
export const BASE_OBJECT_STANDARD_FIELD_IDS = {
|
||||
id: '20202020-eda0-4cee-9577-3eb357e3c22b',
|
||||
createdAt: '20202020-66ac-4502-9975-e4d959c50311',
|
||||
updatedAt: '20202020-d767-4622-bdcf-d8a084834d86',
|
||||
deletedAt: '20202020-b9a7-48d8-8387-b9a3090a50ec',
|
||||
} as const;
|
||||
|
||||
export const BLOCKLIST_STANDARD_FIELD_IDS = {
|
||||
handle: '20202020-eef3-44ed-aa32-4641d7fd4a3e',
|
||||
workspaceMember: '20202020-548d-4084-a947-fa20a39f7c06',
|
||||
} as const;
|
||||
|
||||
export const CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS = {
|
||||
calendarChannel: '20202020-93ee-4da4-8d58-0282c4a9cb7d',
|
||||
calendarEvent: '20202020-5aa5-437e-bb86-f42d457783e3',
|
||||
eventExternalId: '20202020-9ec8-48bb-b279-21d0734a75a1',
|
||||
recurringEventExternalId: '20202020-c58f-4c69-9bf8-9518fa31aa50',
|
||||
} as const;
|
||||
|
||||
export const CALENDAR_CHANNEL_STANDARD_FIELD_IDS = {
|
||||
connectedAccount: '20202020-95b1-4f44-82dc-61b042ae2414',
|
||||
handle: '20202020-1d08-420a-9aa7-22e0f298232d',
|
||||
visibility: '20202020-1b07-4796-9f01-d626bab7ca4d',
|
||||
isContactAutoCreationEnabled: '20202020-50fb-404b-ba28-369911a3793a',
|
||||
contactAutoCreationPolicy: '20202020-b55d-447d-b4df-226319058775',
|
||||
isSyncEnabled: '20202020-fe19-4818-8854-21f7b1b43395',
|
||||
syncCursor: '20202020-bac2-4852-a5cb-7a7898992b70',
|
||||
calendarChannelEventAssociations: '20202020-afb0-4a9f-979f-2d5087d71d09',
|
||||
throttleFailureCount: '20202020-525c-4b76-b9bd-0dd57fd11d61',
|
||||
syncStatus: '20202020-7116-41da-8b4b-035975c4eb6a',
|
||||
syncStage: '20202020-6246-42e6-b5cd-003bd921782c',
|
||||
syncStageStartedAt: '20202020-a934-46f1-a8e7-9568b1e3a53e',
|
||||
syncedAt: '20202020-2ff5-4f70-953a-3d0d36357576',
|
||||
} as const;
|
||||
|
||||
export const CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS = {
|
||||
calendarEvent: '20202020-fe3a-401c-b889-af4f4657a861',
|
||||
handle: '20202020-8692-4580-8210-9e09cbd031a7',
|
||||
displayName: '20202020-ee1e-4f9f-8ac1-5c0b2f69691e',
|
||||
isOrganizer: '20202020-66e7-4e00-9e06-d06c92650580',
|
||||
responseStatus: '20202020-cec0-4be8-8fba-c366abc23147',
|
||||
person: '20202020-5761-4842-8186-e1898ef93966',
|
||||
workspaceMember: '20202020-20e4-4591-93ed-aeb17a4dcbd2',
|
||||
} as const;
|
||||
|
||||
export const CALENDAR_EVENT_STANDARD_FIELD_IDS = {
|
||||
title: '20202020-080e-49d1-b21d-9702a7e2525c',
|
||||
isCanceled: '20202020-335b-4e04-b470-43b84b64863c',
|
||||
isFullDay: '20202020-551c-402c-bb6d-dfe9efe86bcb',
|
||||
startsAt: '20202020-2c57-4c75-93c5-2ac950a6ed67',
|
||||
endsAt: '20202020-2554-4ee1-a617-17907f6bab21',
|
||||
externalCreatedAt: '20202020-9f03-4058-a898-346c62181599',
|
||||
externalUpdatedAt: '20202020-b355-4c18-8825-ef42c8a5a755',
|
||||
description: '20202020-52c4-4266-a98f-e90af0b4d271',
|
||||
location: '20202020-641a-4ffe-960d-c3c186d95b17',
|
||||
iCalUid: '20202020-f24b-45f4-b6a3-d2f9fcb98714',
|
||||
conferenceSolution: '20202020-1c3f-4b5a-b526-5411a82179eb',
|
||||
conferenceLink: '20202020-35da-43ef-9ca0-e936e9dc237b',
|
||||
calendarChannelEventAssociations: '20202020-bdf8-4572-a2cc-ecbb6bcc3a02',
|
||||
calendarEventParticipants: '20202020-e07e-4ccb-88f5-6f3d00458eec',
|
||||
} as const;
|
||||
|
||||
// TODO: check if this can be deleted
|
||||
export const COMMENT_STANDARD_FIELD_IDS = {
|
||||
body: '20202020-d5eb-49d2-b3e0-1ed04145ebb7',
|
||||
author: '20202020-2ab1-427e-a981-cf089de3a9bd',
|
||||
activity: '20202020-c8d9-4c30-a35e-dc7f44388070',
|
||||
} as const;
|
||||
|
||||
export const COMPANY_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-4d99-4e2e-a84c-4a27837b1ece',
|
||||
domainName: '20202020-0c28-43d8-8ba5-3659924d3489',
|
||||
address_deprecated: '20202020-a82a-4ee2-96cc-a18a3259d953',
|
||||
address: '20202020-c5ce-4adc-b7b6-9c0979fc55e7',
|
||||
employees: '20202020-8965-464a-8a75-74bafc152a0b',
|
||||
linkedinLink: '20202020-ebeb-4beb-b9ad-6848036fb451',
|
||||
xLink: '20202020-6f64-4fd9-9580-9c1991c7d8c3',
|
||||
annualRecurringRevenue: '20202020-602a-495c-9776-f5d5b11d227b',
|
||||
idealCustomerProfile: '20202020-ba6b-438a-8213-2c5ba28d76a2',
|
||||
position: '20202020-9b4e-462b-991d-a0ee33326454',
|
||||
createdBy: '20202020-fabc-451d-ab7d-412170916baa',
|
||||
updatedBy: '7444022e-b38f-4d4f-801b-cd664abc4834',
|
||||
people: '20202020-3213-4ddf-9494-6422bcff8d7c',
|
||||
accountOwner: '20202020-95b8-4e10-9881-edb5d4765f9d',
|
||||
// TODO: check if activityTargets field can be deleted
|
||||
activityTargets: '20202020-c2a5-4c9b-9d9a-582bcd57fbc8',
|
||||
taskTargets: '20202020-cb17-4a61-8f8f-3be6730480de',
|
||||
noteTargets: '20202020-bae0-4556-a74a-a9c686f77a88',
|
||||
opportunities: '20202020-add3-4658-8e23-d70dccb6d0ec',
|
||||
favorites: '20202020-4d1d-41ac-b13b-621631298d55',
|
||||
attachments: '20202020-c1b5-4120-b0f0-987ca401ed53',
|
||||
timelineActivities: '20202020-0414-4daf-9c0d-64fe7b27f89f',
|
||||
searchVector: '85c71601-72f9-4b7b-b343-d46100b2c74d',
|
||||
} as const;
|
||||
|
||||
export const CONNECTED_ACCOUNT_STANDARD_FIELD_IDS = {
|
||||
handle: '20202020-c804-4a50-bb05-b3a9e24f1dec',
|
||||
provider: '20202020-ebb0-4516-befc-a9e95935efd5',
|
||||
accessToken: '20202020-707b-4a0a-8753-2ad42efe1e29',
|
||||
refreshToken: '20202020-532d-48bd-80a5-c4be6e7f6e49',
|
||||
accountOwner: '20202020-3517-4896-afac-b1d0aa362af6',
|
||||
lastSyncHistoryId: '20202020-115c-4a87-b50f-ac4367a971b9',
|
||||
authFailedAt: '20202020-d268-4c6b-baff-400d402b430a',
|
||||
lastCredentialsRefreshedAt: '20202020-aa5e-4e85-903b-fdf90a941941',
|
||||
messageChannels: '20202020-24f7-4362-8468-042204d1e445',
|
||||
calendarChannels: '20202020-af4a-47bb-99ec-51911c1d3977',
|
||||
handleAliases: '20202020-8a3d-46be-814f-6228af16c47b',
|
||||
scopes: '20202020-8a3d-46be-814f-6228af16c47c',
|
||||
connectionParameters: '20202020-a1b2-46be-814f-6228af16c481',
|
||||
} as const;
|
||||
|
||||
export const TIMELINE_ACTIVITY_STANDARD_FIELD_IDS = {
|
||||
happensAt: '20202020-9526-4993-b339-c4318c4d39f0',
|
||||
type: '20202020-5e7b-4ccd-8b8a-86b94b474134',
|
||||
name: '20202020-7207-46e8-9dab-849505ae8497',
|
||||
properties: '20202020-f142-4b04-b91b-6a2b4af3bf11',
|
||||
workspaceMember: '20202020-af23-4479-9a30-868edc474b36',
|
||||
targetPerson: '20202020-c414-45b9-a60a-ac27aa96229f',
|
||||
targetCompany: '20202020-04ad-4221-a744-7a8278a5ce21',
|
||||
targetOpportunity: '20202020-7664-4a35-a3df-580d389fd527',
|
||||
targetTask: '20202020-b2f5-415c-9135-a31dfe49501b',
|
||||
targetNote: '20202020-ec55-4135-8da5-3a20badc0156',
|
||||
targetWorkflow: '20202020-616c-4ad3-a2e9-c477c341e295',
|
||||
targetWorkflowVersion: '20202020-74f1-4711-a129-e14ca0ecd744',
|
||||
targetWorkflowRun: '20202020-96f0-401b-9186-a3a0759225ac',
|
||||
targetDashboard: '20202020-7864-48f5-af7c-9e4b60140948',
|
||||
targetCustom: '20202020-4a71-41b0-9f83-9cdcca3f8b14',
|
||||
linkedRecordCachedName: '20202020-cfdb-4bef-bbce-a29f41230934',
|
||||
linkedRecordId: '20202020-2e0e-48c0-b445-ee6c1e61687d',
|
||||
linkedObjectMetadataId: '20202020-c595-449d-9f89-562758c9ee69',
|
||||
targetMorphId: '20202020-9a2b-4c3d-a4e5-f6a7b8c9d0e1',
|
||||
} as const;
|
||||
|
||||
export const FAVORITE_STANDARD_FIELD_IDS = {
|
||||
position: '20202020-dd26-42c6-8c3c-2a7598c204f6',
|
||||
forWorkspaceMember: '20202020-ce63-49cb-9676-fdc0c45892cd',
|
||||
person: '20202020-c428-4f40-b6f3-86091511c41c',
|
||||
company: '20202020-cff5-4682-8bf9-069169e08279',
|
||||
opportunity: '20202020-dabc-48e1-8318-2781a2b32aa2',
|
||||
workflow: '20202020-b11b-4dc8-999a-6bd0a947b463',
|
||||
workflowVersion: '20202020-e1b8-4caf-b55a-3ab4d4cbcd21',
|
||||
workflowRun: '20202020-db5a-4fe4-9a13-9afa22b1e762',
|
||||
task: '20202020-1b1b-4b3b-8b1b-7f8d6a1d7d5c',
|
||||
note: '20202020-1f25-43fe-8b00-af212fdde824',
|
||||
view: '20202020-5a93-4fa9-acce-e73481a0bbdf',
|
||||
custom: '20202020-855a-4bc8-9861-79deef37011f',
|
||||
favoriteFolder: '20202020-f658-4d12-8b4d-248356aa4bd9',
|
||||
dashboard: '20202020-6ef9-45e4-b440-cc986f687c91',
|
||||
} as const;
|
||||
|
||||
export const FAVORITE_FOLDER_STANDARD_FIELD_IDS = {
|
||||
position: '20202020-5278-4bde-8909-2cec74d43744',
|
||||
name: '20202020-82a3-4537-8ff0-dbce7eec35d6',
|
||||
favorites: '20202020-b5e3-4b42-8af2-03cd4fd2e4d2',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS = {
|
||||
messageChannel: '20202020-b658-408f-bd46-3bd2d15d7e52',
|
||||
message: '20202020-da5d-4ac5-8743-342ab0a0336b',
|
||||
messageExternalId: '20202020-37d6-438f-b6fd-6503596c8f34',
|
||||
messageThread: '20202020-fac8-42a8-94dd-44dbc920ae16',
|
||||
messageThreadExternalId: '20202020-35fb-421e-afa0-0b8e8f7f9018',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_CHANNEL_STANDARD_FIELD_IDS = {
|
||||
visibility: '20202020-6a6b-4532-9767-cbc61b469453',
|
||||
handle: '20202020-2c96-43c3-93e3-ed6b1acb69bc',
|
||||
connectedAccount: '20202020-49a2-44a4-b470-282c0440d15d',
|
||||
type: '20202020-ae95-42d9-a3f1-797a2ea22122',
|
||||
isContactAutoCreationEnabled: '20202020-fabd-4f14-b7c6-3310f6d132c6',
|
||||
contactAutoCreationPolicy: '20202020-fc0e-4ba6-b259-a66ca89cfa38',
|
||||
excludeNonProfessionalEmails: '20202020-1df5-445d-b4f3-2413ad178431',
|
||||
excludeGroupEmails: '20202020-45a0-4be4-9164-5820a6a109fb',
|
||||
messageChannelMessageAssociations: '20202020-49b8-4766-88fd-75f1e21b3d5f',
|
||||
messageFolders: '20202020-cc39-4432-9fe8-ec8ab8bbed94',
|
||||
messageFolderImportPolicy: '20202020-cc39-4432-9fe8-ec8ab8bbed95',
|
||||
pendingGroupEmailsAction: '20202020-17c5-4e9f-bc50-af46a89fdd42',
|
||||
isSyncEnabled: '20202020-d9a6-48e9-990b-b97fdf22e8dd',
|
||||
syncCursor: '20202020-79d1-41cf-b738-bcf5ed61e256',
|
||||
syncedAt: '20202020-263d-4c6b-ad51-137ada56f7d4',
|
||||
syncStatus: '20202020-56a1-4f7e-9880-a8493bb899cc',
|
||||
syncStage: '20202020-7979-4b08-89fe-99cb5e698767',
|
||||
syncStageStartedAt: '20202020-8c61-4a42-ae63-73c1c3c52e06',
|
||||
throttleFailureCount: '20202020-0291-42be-9ad0-d578a51684ab',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_FOLDER_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-7cf8-40bc-a681-b80b771449b7',
|
||||
parentFolderId: '20202020-e45d-49de-a4aa-587bbf9601f3',
|
||||
messageChannel: '20202020-b658-408f-bd46-3bd2d15d7e52',
|
||||
syncCursor: '20202020-98cd-49ed-8dfc-cb5796400e64',
|
||||
isSentFolder: '20202020-2af5-4a25-b2de-3c9386da941b',
|
||||
isSynced: '20202020-764f-4e09-8f95-cd46b6bfe3c4',
|
||||
externalId: '20202020-f3a8-4d2b-9c7e-1b5f9a8e4c6d',
|
||||
pendingSyncAction: '20202020-4f97-4c79-9517-16387fe237f7',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS = {
|
||||
message: '20202020-985b-429a-9db9-9e55f4898a2a',
|
||||
role: '20202020-65d1-42f4-8729-c9ec1f52aecd',
|
||||
handle: '20202020-2456-464e-b422-b965a4db4a0b',
|
||||
displayName: '20202020-36dd-4a4f-ac02-228425be9fac',
|
||||
person: '20202020-249d-4e0f-82cd-1b9df5cd3da2',
|
||||
workspaceMember: '20202020-77a7-4845-99ed-1bcbb478be6f',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_THREAD_STANDARD_FIELD_IDS = {
|
||||
messages: '20202020-3115-404f-aade-e1154b28e35a',
|
||||
messageChannelMessageAssociations: '20202020-314e-40a4-906d-a5d5d6c285f6',
|
||||
messageThreadSubscribers: '20202020-3b3b-4b3b-8b3b-7f8d6a1d7d5b',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_THREAD_SUBSCRIBER_STANDARD_FIELD_IDS = {
|
||||
messageThread: '20202020-2c8f-4f3e-8b9a-7f8d6a1c7d5b',
|
||||
workspaceMember: '20202020-7f7b-4b3b-8b3b-7f8d6a1d7d5a',
|
||||
} as const;
|
||||
|
||||
export const MESSAGE_STANDARD_FIELD_IDS = {
|
||||
headerMessageId: '20202020-72b5-416d-aed8-b55609067d01',
|
||||
messageThread: '20202020-30f2-4ccd-9f5c-e41bb9d26214',
|
||||
direction: '20202020-0203-4118-8e2a-05b9bdae6dab',
|
||||
subject: '20202020-52d1-4036-b9ae-84bd722bb37a',
|
||||
text: '20202020-d2ee-4e7e-89de-9a0a9044a143',
|
||||
receivedAt: '20202020-140a-4a2a-9f86-f13b6a979afc',
|
||||
messageParticipants: '20202020-7cff-4a74-b63c-73228448cbd9',
|
||||
messageChannelMessageAssociations: '20202020-3cef-43a3-82c6-50e7cfbc9ae4',
|
||||
} as const;
|
||||
|
||||
export const NOTE_STANDARD_FIELD_IDS = {
|
||||
position: '20202020-368d-4dc2-943f-ed8a49c7fdfb',
|
||||
title: '20202020-faeb-4c76-8ba6-ccbb0b4a965f',
|
||||
body: '20202020-e63d-4e70-95be-a78cd9abe7ef',
|
||||
bodyV2: '20202020-a7bb-4d94-be51-8f25181502c8',
|
||||
createdBy: '20202020-0d79-4e21-ab77-5a394eff97be',
|
||||
updatedBy: '9b446e89-2484-4044-a3b5-420f6b578c0c',
|
||||
noteTargets: '20202020-1f25-43fe-8b00-af212fdde823',
|
||||
attachments: '20202020-4986-4c92-bf19-39934b149b16',
|
||||
timelineActivities: '20202020-7030-42f8-929c-1a57b25d6bce',
|
||||
favorites: '20202020-4d1d-41ac-b13b-621631298d67',
|
||||
searchVector: '20202020-7ea8-44d4-9d4c-51dd2a757950',
|
||||
} as const;
|
||||
|
||||
export const NOTE_TARGET_STANDARD_FIELD_IDS = {
|
||||
note: '20202020-57f3-4f50-9599-fc0f671df003',
|
||||
targetPerson: '20202020-38ca-4aab-92f5-8a605ca2e4c5',
|
||||
targetCompany: 'c500fbc0-d6f2-4982-a959-5a755431696c',
|
||||
targetOpportunity: '20202020-4e42-417a-a705-76581c9ade79',
|
||||
targetCustom: '20202020-3d12-4579-94ee-7117c1bad492',
|
||||
targetMorphId: '20202020-f635-435d-ab8d-e1168b375c70',
|
||||
} as const;
|
||||
|
||||
export const OPPORTUNITY_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-8609-4f65-a2d9-44009eb422b5',
|
||||
amount: '20202020-583e-4642-8533-db761d5fa82f',
|
||||
closeDate: '20202020-527e-44d6-b1ac-c4158d307b97',
|
||||
probabilityDeprecated: '20202020-69d4-45f3-9703-690b09fafcf0',
|
||||
stage: '20202020-6f76-477d-8551-28cd65b2b4b9',
|
||||
position: '20202020-806d-493a-bbc6-6313e62958e2',
|
||||
createdBy: '20202020-a63e-4a62-8e63-42a51828f831',
|
||||
updatedBy: '3c8a6095-3f64-4e81-a59e-66c2bd181e11',
|
||||
pointOfContact: '20202020-8dfb-42fc-92b6-01afb759ed16',
|
||||
company: '20202020-cbac-457e-b565-adece5fc815f',
|
||||
favorites: '20202020-a1c2-4500-aaae-83ba8a0e827a',
|
||||
// TODO: check if activityTargets field can be deleted
|
||||
activityTargets: '20202020-220a-42d6-8261-b2102d6eab35',
|
||||
taskTargets: '20202020-59c0-4179-a208-4a255f04a5be',
|
||||
noteTargets: '20202020-dd3f-42d5-a382-db58aabf43d3',
|
||||
attachments: '20202020-87c7-4118-83d6-2f4031005209',
|
||||
timelineActivities: '20202020-30e2-421f-96c7-19c69d1cf631',
|
||||
searchVector: '428a0da5-4b2e-4ce3-b695-89a8b384e6e3',
|
||||
} as const;
|
||||
|
||||
export const PERSON_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-3875-44d5-8c33-a6239011cab8',
|
||||
email: '20202020-a740-42bb-8849-8980fb3f12e1',
|
||||
emails: '20202020-3c51-43fa-8b6e-af39e29368ab',
|
||||
linkedinLink: '20202020-f1af-48f7-893b-2007a73dd508',
|
||||
xLink: '20202020-8fc2-487c-b84a-55a99b145cfd',
|
||||
jobTitle: '20202020-b0d0-415a-bef9-640a26dacd9b',
|
||||
phone: '20202020-4564-4b8b-a09f-05445f2e0bce',
|
||||
phones: '20202020-0638-448e-8825-439134618022',
|
||||
city: '20202020-5243-4ffb-afc5-2c675da41346',
|
||||
avatarUrl: '20202020-b8a6-40df-961c-373dc5d2ec21',
|
||||
position: '20202020-fcd5-4231-aff5-fff583eaa0b1',
|
||||
createdBy: '20202020-f6ab-4d98-af24-a3d5b664148a',
|
||||
updatedBy: 'e9e0dd35-184c-4742-84da-afadf45ce59a',
|
||||
company: '20202020-e2f3-448e-b34c-2d625f0025fd',
|
||||
pointOfContactForOpportunities: '20202020-911b-4a7d-b67b-918aa9a5b33a',
|
||||
// TODO: check if activityTargets field can be deleted
|
||||
activityTargets: '20202020-dee7-4b7f-b50a-1f50bd3be452',
|
||||
taskTargets: '20202020-584b-4d3e-88b6-53ab1fa03c3a',
|
||||
noteTargets: '20202020-c8fc-4258-8250-15905d3fcfec',
|
||||
favorites: '20202020-4073-4117-9cf1-203bcdc91cbd',
|
||||
attachments: '20202020-cd97-451f-87fa-bcb789bdbf3a',
|
||||
messageParticipants: '20202020-498e-4c61-8158-fa04f0638334',
|
||||
calendarEventParticipants: '20202020-52ee-45e9-a702-b64b3753e3a9',
|
||||
timelineActivities: '20202020-a43e-4873-9c23-e522de906ce5',
|
||||
searchVector: '57d1d7ad-fa10-44fc-82f3-ad0959ec2534',
|
||||
} as const;
|
||||
|
||||
export const TASK_STANDARD_FIELD_IDS = {
|
||||
position: '20202020-7d47-4690-8a98-98b9a0c05dd8',
|
||||
title: '20202020-b386-4cb7-aa5a-08d4a4d92680',
|
||||
body: '20202020-ce13-43f4-8821-69388fe1fd26',
|
||||
bodyV2: '20202020-4aa0-4ae8-898d-7df0afd47ab1',
|
||||
dueAt: '20202020-fd99-40da-951b-4cb9a352fce3',
|
||||
status: '20202020-70bc-48f9-89c5-6aa730b151e0',
|
||||
createdBy: '20202020-1a04-48ab-a567-576965ae5387',
|
||||
updatedBy: '9e8bf518-f4ab-433e-9674-efb75fba2802',
|
||||
taskTargets: '20202020-de9c-4d0e-a452-713d4a3e5fc7',
|
||||
attachments: '20202020-794d-4783-a8ff-cecdb15be139',
|
||||
assignee: '20202020-065a-4f42-a906-e20422c1753f',
|
||||
timelineActivities: '20202020-c778-4278-99ee-23a2837aee64',
|
||||
favorites: '20202020-4d1d-41ac-b13b-621631298d65',
|
||||
searchVector: '20202020-4746-4e2f-870c-52b02c67c90d',
|
||||
} as const;
|
||||
|
||||
export const TASK_TARGET_STANDARD_FIELD_IDS = {
|
||||
task: '20202020-e881-457a-8758-74aaef4ae78a',
|
||||
targetPerson: '20202020-c8a0-4e85-a016-87e2349cfbec',
|
||||
targetCompany: '20202020-4703-4a4e-948c-487b0c60a92c',
|
||||
targetOpportunity: '20202020-6cb2-4c01-a9a5-aca3dbc11d41',
|
||||
targetCustom: '20202020-41c1-4c9a-8c75-be0971ef89af',
|
||||
targetMorphId: '20202020-f636-435d-ab8d-e1168b375c71',
|
||||
} as const;
|
||||
|
||||
export const VIEW_FIELD_STANDARD_FIELD_IDS = {
|
||||
fieldMetadataId: '20202020-135f-4c5b-b361-15f24870473c',
|
||||
isVisible: '20202020-e966-473c-9c18-f00d3347e0ba',
|
||||
size: '20202020-6fab-4bd0-ae72-20f3ee39d581',
|
||||
position: '20202020-19e5-4e4c-8c15-3a96d1fd0650',
|
||||
view: '20202020-e8da-4521-afab-d6d231f9fa18',
|
||||
aggregateOperation: '20202020-2cd7-4f94-ae83-4a14f5731a04',
|
||||
} as const;
|
||||
|
||||
export const VIEW_GROUP_STANDARD_FIELD_IDS = {
|
||||
fieldMetadataId: '20202020-8f26-46ae-afed-fdacd7778682',
|
||||
fieldValue: '20202020-175e-4596-b7a4-1cd9d14e5a30',
|
||||
isVisible: '20202020-0fed-4b44-88fd-a064c4fcfce4',
|
||||
position: '20202020-748e-4645-8f32-84aae7726c04',
|
||||
view: '20202020-5bc7-4110-b23f-fb851fb133b4',
|
||||
} as const;
|
||||
|
||||
export const VIEW_FILTER_STANDARD_FIELD_IDS = {
|
||||
fieldMetadataId: '20202020-c9aa-4c94-8d0e-9592f5008fb0',
|
||||
operand: '20202020-bd23-48c4-9fab-29d1ffb80310',
|
||||
value: '20202020-1e55-4a1e-a1d2-fefb86a5fce5',
|
||||
displayValue: '20202020-1270-4ebf-9018-c0ec10d5038e',
|
||||
view: '20202020-4f5b-487e-829c-3d881c163611',
|
||||
viewFilterGroupId: '20202020-2580-420a-8328-cab1635c0296',
|
||||
positionInViewFilterGroup: '20202020-3bb0-4f66-a537-a46fe0dc468f',
|
||||
subFieldName: '20202020-3bb0-4f66-a537-a46fe0dc469a',
|
||||
} as const;
|
||||
|
||||
export const VIEW_FILTER_GROUP_STANDARD_FIELD_IDS = {
|
||||
view: '20202020-ff7a-4b54-8be5-aa0249047b74',
|
||||
parentViewFilterGroupId: '20202020-edbf-4929-8ede-64f48d6bf2a7',
|
||||
logicalOperator: '20202020-64d9-4bc5-85ba-c250796ce9aa',
|
||||
positionInViewFilterGroup: '20202020-90d6-4299-ad87-d05ddd3a0a3f',
|
||||
} as const;
|
||||
|
||||
export const VIEW_SORT_STANDARD_FIELD_IDS = {
|
||||
fieldMetadataId: '20202020-8240-4657-aee4-7f0df8e94eca',
|
||||
direction: '20202020-b06e-4eb3-9b58-0a62e5d79836',
|
||||
view: '20202020-bd6c-422b-9167-5c105f2d02c8',
|
||||
} as const;
|
||||
|
||||
export const VIEW_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-12c6-4f37-b588-c9b9bf57328d',
|
||||
objectMetadataId: '20202020-d6de-4fd5-84dd-47f9e730368b',
|
||||
type: '20202020-dd11-4607-9ec7-c57217262a7f',
|
||||
key: '20202020-298e-49fa-9f4a-7b416b110443',
|
||||
icon: '20202020-1f08-4fd9-929b-cbc07f317166',
|
||||
kanbanFieldMetadataId: '20202020-d09b-4f65-ac42-06a2f20ba0e8',
|
||||
kanbanAggregateOperation: '20202020-8da2-45de-a731-61bed84b17a8',
|
||||
kanbanAggregateOperationFieldMetadataId:
|
||||
'20202020-b1b3-4bf3-85e4-dc7d58aa9b02',
|
||||
mainGroupByFieldMetadataId: '20202020-f782-4f89-96eb-083a02cca887',
|
||||
position: '20202020-e9db-4303-b271-e8250c450172',
|
||||
isCompact: '20202020-674e-4314-994d-05754ea7b22b',
|
||||
openRecordIn: '20202020-086d-4eef-9f03-56c6392eacb8',
|
||||
viewFields: '20202020-542b-4bdc-b177-b63175d48edf',
|
||||
viewGroups: '20202020-e1a1-419f-ac81-1986a5ea59a8',
|
||||
viewFilters: '20202020-ff23-4154-b63c-21fb36cd0967',
|
||||
viewFilterGroups: '20202020-0318-474a-84a1-bac895ceaa5a',
|
||||
viewSorts: '20202020-891b-45c3-9fe1-80a75b4aa043',
|
||||
favorites: '20202020-c818-4a86-8284-9ec0ef0a59a5',
|
||||
anyFieldFilterValue: '20202020-3143-46c0-bb05-034063ce0703',
|
||||
} as const;
|
||||
|
||||
export const WORKFLOW_AUTOMATED_TRIGGER_STANDARD_FIELD_IDS = {
|
||||
type: '20202020-3319-4234-a34c-3f92c1ab56e7',
|
||||
settings: '20202020-3319-4234-a34c-bac8f903de12',
|
||||
workflow: '20202020-3319-4234-a34c-8e1a4d2f7c03',
|
||||
} as const;
|
||||
|
||||
export const WORKFLOW_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-b3d3-478f-acc0-5d901e725b20',
|
||||
lastPublishedVersionId: '20202020-326a-4fba-8639-3456c0a169e8',
|
||||
statuses: '20202020-357c-4432-8c50-8c31b4a552d9',
|
||||
position: '20202020-39b0-4d8c-8c5f-33c2326deb5f',
|
||||
versions: '20202020-9432-416e-8f3c-27ee3153d099',
|
||||
runs: '20202020-759b-4340-b58b-e73595c4df4f',
|
||||
eventListeners: '20202020-0229-4c66-832e-035c67579a38',
|
||||
automatedTriggers: '20202020-3319-4234-a34c-117ecad2b8a9',
|
||||
favorites: '20202020-c554-4c41-be7a-cf9cd4b0d512',
|
||||
timelineActivities: '20202020-906e-486a-a798-131a5f081faf',
|
||||
attachments: '20202020-4a8c-4e2d-9b1c-7e5f3a2b4c6d',
|
||||
createdBy: '20202020-6007-401a-8aa5-e6f48581a6f3',
|
||||
updatedBy: '3559831e-caf2-4eb5-9db1-b47bf968c774',
|
||||
searchVector: '20202020-535d-4ffa-b7f3-4fa0d5da1b7a',
|
||||
} as const;
|
||||
|
||||
export const WORKFLOW_RUN_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-b840-4253-aef9-4e5013694587',
|
||||
workflowVersion: '20202020-2f52-4ba8-8dc4-d0d6adb9578d',
|
||||
workflow: '20202020-8c57-4e7f-84f5-f373f68e1b82',
|
||||
enqueuedAt: '20202020-f1e3-4de1-a461-b5c4fdbc861d',
|
||||
startedAt: '20202020-a234-4e2d-bd15-85bcea6bb183',
|
||||
endedAt: '20202020-e1c1-4b6b-bbbd-b2beaf2e159e',
|
||||
status: '20202020-6b3e-4f9c-8c2b-2e5b8e6d6f3b',
|
||||
position: '20202020-7802-4c40-ae89-1f506fe3365c',
|
||||
createdBy: '20202020-6007-401a-8aa5-e6f38581a6f3',
|
||||
updatedBy: '730dc1c9-34f5-4c22-84a6-bcb55b7604e2',
|
||||
output: '20202020-7be4-4db2-8ac6-3ff0d740843d',
|
||||
context: '20202020-189c-478a-b867-d72feaf5926a',
|
||||
state: '20202020-611f-45f3-9cde-d64927e8ec57',
|
||||
favorites: '20202020-4baf-4604-b899-2f7fcfbbf90d',
|
||||
timelineActivities: '20202020-af4d-4eb0-babc-eb960a45b356',
|
||||
searchVector: '20202020-0b91-4ded-b1ac-cbd5efa58cb9',
|
||||
} as const;
|
||||
|
||||
export const WORKFLOW_VERSION_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-a12f-4cca-9937-a2e40cc65509',
|
||||
workflow: '20202020-afa3-46c3-91b0-0631ca6aa1c8',
|
||||
trigger: '20202020-4eae-43e7-86e0-212b41a30b48',
|
||||
status: '20202020-5a34-440e-8a25-39d8c3d1d4cf',
|
||||
position: '20202020-791d-4950-ab28-0e704767ae1c',
|
||||
runs: '20202020-1d08-46df-901a-85045f18099a',
|
||||
steps: '20202020-5988-4a64-b94a-1f9b7b989039',
|
||||
favorites: '20202020-b8e0-4e57-928d-b51671cc71f2',
|
||||
timelineActivities: '20202020-fcb0-4695-b17e-3b43a421c633',
|
||||
searchVector: '20202020-3f17-44ef-b8c1-b282ae8469b2',
|
||||
} as const;
|
||||
|
||||
export const WORKSPACE_MEMBER_STANDARD_FIELD_IDS = {
|
||||
position: '20202020-1810-4591-a93c-d0df97dca843',
|
||||
name: '20202020-e914-43a6-9c26-3603c59065f4',
|
||||
colorScheme: '20202020-66bc-47f2-adac-f2ef7c598b63',
|
||||
locale: '20202020-402e-4695-b169-794fa015afbe',
|
||||
avatarUrl: '20202020-0ced-4c4f-a376-c98a966af3f6',
|
||||
userEmail: '20202020-4c5f-4e09-bebc-9e624e21ecf4',
|
||||
userId: '20202020-75a9-4dfc-bf25-2e4b43e89820',
|
||||
authoredActivities: '20202020-f139-4f13-a82f-a65a8d290a74',
|
||||
assignedActivities: '20202020-5c97-42b6-8ca9-c07622cbb33f',
|
||||
assignedTasks: '20202020-61dc-4a1c-99e8-38ebf8d2bbeb',
|
||||
favorites: '20202020-f3c1-4faf-b343-cf7681038757',
|
||||
accountOwnerForCompanies: '20202020-dc29-4bd4-a3c1-29eafa324bee',
|
||||
authoredAttachments: '20202020-000f-4947-917f-1b09851024fe',
|
||||
authoredComments: '20202020-5536-4f59-b837-51c45ef43b05',
|
||||
connectedAccounts: '20202020-e322-4bde-a525-727079b4a100',
|
||||
messageParticipants: '20202020-8f99-48bc-a5eb-edd33dd54188',
|
||||
blocklist: '20202020-6cb2-4161-9f29-a4b7f1283859',
|
||||
calendarEventParticipants: '20202020-0dbc-4841-9ce1-3e793b5b3512',
|
||||
timelineActivities: '20202020-e15b-47b8-94fe-8200e3c66615',
|
||||
auditLogs: '20202020-2f54-4739-a5e2-99563385e83d',
|
||||
messageThreadSubscribers: '20202020-4b3b-4b3b-9b3b-3b3b3b3b3b3b',
|
||||
timeZone: '20202020-2d33-4c21-a86e-5943b050dd54',
|
||||
dateFormat: '20202020-af13-4e11-b1e7-b8cf5ea13dc0',
|
||||
timeFormat: '20202020-8acb-4cf8-a851-a6ed443c8d81',
|
||||
searchVector: '20202020-46d0-4e7f-bc26-74c0edaeb619',
|
||||
calendarStartDay: '20202020-92d0-1d7f-a126-25ededa6b142',
|
||||
numberFormat: '20202020-7f40-4e7f-b126-11c0eda6b141',
|
||||
} as const;
|
||||
export const CUSTOM_OBJECT_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-ba07-4ffd-ba63-009491f5749c',
|
||||
position: '20202020-c2bd-4e16-bb9a-c8b0411bf49d',
|
||||
createdBy: '20202020-be0e-4971-865b-32ca87cbb315',
|
||||
updatedBy: 'd047ccb4-9469-4514-a982-29c4ae49317d',
|
||||
// TODO: check if activityTargets field can be deleted
|
||||
activityTargets: '20202020-7f42-40ae-b96c-c8a61acc83bf',
|
||||
noteTargets: '20202020-01fd-4f37-99dc-9427a444018a',
|
||||
taskTargets: '20202020-0860-4566-b865-bff3c626c303',
|
||||
favorites: '20202020-a4a7-4686-b296-1c6c3482ee21',
|
||||
attachments: '20202020-8d59-46ca-b7b2-73d167712134',
|
||||
timelineActivities: '20202020-f1ef-4ba4-8f33-1a4577afa477',
|
||||
searchVector: '70e56537-18ef-4811-b1c7-0a444006b815',
|
||||
} as const;
|
||||
|
||||
export const DASHBOARD_STANDARD_FIELD_IDS = {
|
||||
title: '20202020-20ee-4091-95dc-44b57eda3a89',
|
||||
position: '20202020-38af-409b-95f0-7f08aa5f420f',
|
||||
pageLayoutId: '20202020-bb53-4648-aa36-1d9d54e6f7f2',
|
||||
createdBy: '20202020-ff32-4fa1-b7ad-407cc6aa0734',
|
||||
updatedBy: '53ee42e7-f157-42b5-b278-a5fa9b378307',
|
||||
timelineActivities: '20202020-9b0c-5d6e-7f8a-9b0c1d2e3f4a',
|
||||
favorites: '20202020-f032-478f-88fa-6426ff6f1e4c',
|
||||
attachments: '20202020-bf6f-4220-8c55-2764f1175870',
|
||||
searchVector: '20202020-0bcc-47a4-8360-2e35a7133f7a',
|
||||
} as const;
|
||||
|
||||
export const STANDARD_OBJECT_FIELD_IDS = {
|
||||
activityTarget: ACTIVITY_TARGET_STANDARD_FIELD_IDS,
|
||||
activity: ACTIVITY_STANDARD_FIELD_IDS,
|
||||
attachment: ATTACHMENT_STANDARD_FIELD_IDS,
|
||||
blocklist: BLOCKLIST_STANDARD_FIELD_IDS,
|
||||
calendarChannelEventAssociation:
|
||||
CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS,
|
||||
calendarChannel: CALENDAR_CHANNEL_STANDARD_FIELD_IDS,
|
||||
calendarEventParticipant: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS,
|
||||
calendarEvent: CALENDAR_EVENT_STANDARD_FIELD_IDS,
|
||||
comment: COMMENT_STANDARD_FIELD_IDS,
|
||||
company: COMPANY_STANDARD_FIELD_IDS,
|
||||
connectedAccount: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS,
|
||||
dashboard: DASHBOARD_STANDARD_FIELD_IDS,
|
||||
favorite: FAVORITE_STANDARD_FIELD_IDS,
|
||||
messageChannelMessageAssociation:
|
||||
MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS,
|
||||
messageChannel: MESSAGE_CHANNEL_STANDARD_FIELD_IDS,
|
||||
messageParticipant: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS,
|
||||
messageThread: MESSAGE_THREAD_STANDARD_FIELD_IDS,
|
||||
messageThreadSubscriber: MESSAGE_THREAD_SUBSCRIBER_STANDARD_FIELD_IDS,
|
||||
message: MESSAGE_STANDARD_FIELD_IDS,
|
||||
note: NOTE_STANDARD_FIELD_IDS,
|
||||
noteTarget: NOTE_TARGET_STANDARD_FIELD_IDS,
|
||||
opportunity: OPPORTUNITY_STANDARD_FIELD_IDS,
|
||||
person: PERSON_STANDARD_FIELD_IDS,
|
||||
task: TASK_STANDARD_FIELD_IDS,
|
||||
taskTarget: TASK_TARGET_STANDARD_FIELD_IDS,
|
||||
timelineActivity: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS,
|
||||
viewField: VIEW_FIELD_STANDARD_FIELD_IDS,
|
||||
viewGroup: VIEW_GROUP_STANDARD_FIELD_IDS,
|
||||
viewFilter: VIEW_FILTER_STANDARD_FIELD_IDS,
|
||||
viewSort: VIEW_SORT_STANDARD_FIELD_IDS,
|
||||
view: VIEW_STANDARD_FIELD_IDS,
|
||||
workflow: WORKFLOW_STANDARD_FIELD_IDS,
|
||||
workflowRun: WORKFLOW_RUN_STANDARD_FIELD_IDS,
|
||||
workflowVersion: WORKFLOW_VERSION_STANDARD_FIELD_IDS,
|
||||
workspaceMember: WORKSPACE_MEMBER_STANDARD_FIELD_IDS,
|
||||
} as const;
|
||||
+6
-6
@@ -9,11 +9,11 @@ import { type PersonWorkspaceEntity } from 'src/modules/person/standard-objects/
|
||||
export class NoteTargetWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
note: EntityRelation<NoteWorkspaceEntity> | null;
|
||||
noteId: string | null;
|
||||
person: EntityRelation<PersonWorkspaceEntity> | null;
|
||||
personId: string | null;
|
||||
company: EntityRelation<CompanyWorkspaceEntity> | null;
|
||||
companyId: string | null;
|
||||
opportunity: EntityRelation<OpportunityWorkspaceEntity> | null;
|
||||
opportunityId: string | null;
|
||||
targetPerson: EntityRelation<PersonWorkspaceEntity> | null;
|
||||
targetPersonId: string | null;
|
||||
targetCompany: EntityRelation<CompanyWorkspaceEntity> | null;
|
||||
targetCompanyId: string | null;
|
||||
targetOpportunity: EntityRelation<OpportunityWorkspaceEntity> | null;
|
||||
targetOpportunityId: string | null;
|
||||
custom: EntityRelation<CustomWorkspaceEntity>;
|
||||
}
|
||||
|
||||
+6
-6
@@ -9,11 +9,11 @@ import { type TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task
|
||||
export class TaskTargetWorkspaceEntity extends BaseWorkspaceEntity {
|
||||
task: EntityRelation<TaskWorkspaceEntity> | null;
|
||||
taskId: string | null;
|
||||
person: EntityRelation<PersonWorkspaceEntity> | null;
|
||||
personId: string | null;
|
||||
company: EntityRelation<CompanyWorkspaceEntity> | null;
|
||||
companyId: string | null;
|
||||
opportunity: EntityRelation<OpportunityWorkspaceEntity> | null;
|
||||
opportunityId: string | null;
|
||||
targetPerson: EntityRelation<PersonWorkspaceEntity> | null;
|
||||
targetPersonId: string | null;
|
||||
targetCompany: EntityRelation<CompanyWorkspaceEntity> | null;
|
||||
targetCompanyId: string | null;
|
||||
targetOpportunity: EntityRelation<OpportunityWorkspaceEntity> | null;
|
||||
targetOpportunityId: string | null;
|
||||
custom: EntityRelation<CustomWorkspaceEntity>;
|
||||
}
|
||||
|
||||
+10
-10
@@ -15,11 +15,11 @@ describe('noteTargetsResolver (e2e)', () => {
|
||||
updatedAt
|
||||
deletedAt
|
||||
noteId
|
||||
personId
|
||||
companyId
|
||||
opportunityId
|
||||
petId
|
||||
surveyResultId
|
||||
targetPersonId
|
||||
targetCompanyId
|
||||
targetOpportunityId
|
||||
targetPetId
|
||||
targetSurveyResultId
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,11 +52,11 @@ describe('noteTargetsResolver (e2e)', () => {
|
||||
expect(noteTargets).toHaveProperty('updatedAt');
|
||||
expect(noteTargets).toHaveProperty('deletedAt');
|
||||
expect(noteTargets).toHaveProperty('noteId');
|
||||
expect(noteTargets).toHaveProperty('personId');
|
||||
expect(noteTargets).toHaveProperty('companyId');
|
||||
expect(noteTargets).toHaveProperty('opportunityId');
|
||||
expect(noteTargets).toHaveProperty('petId');
|
||||
expect(noteTargets).toHaveProperty('surveyResultId');
|
||||
expect(noteTargets).toHaveProperty('targetPersonId');
|
||||
expect(noteTargets).toHaveProperty('targetCompanyId');
|
||||
expect(noteTargets).toHaveProperty('targetOpportunityId');
|
||||
expect(noteTargets).toHaveProperty('targetPetId');
|
||||
expect(noteTargets).toHaveProperty('targetSurveyResultId');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+10
-10
@@ -15,11 +15,11 @@ describe('taskTargetsResolver (e2e)', () => {
|
||||
updatedAt
|
||||
deletedAt
|
||||
taskId
|
||||
personId
|
||||
companyId
|
||||
opportunityId
|
||||
petId
|
||||
surveyResultId
|
||||
targetPersonId
|
||||
targetCompanyId
|
||||
targetOpportunityId
|
||||
targetPetId
|
||||
targetSurveyResultId
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,11 +52,11 @@ describe('taskTargetsResolver (e2e)', () => {
|
||||
expect(taskTargets).toHaveProperty('updatedAt');
|
||||
expect(taskTargets).toHaveProperty('deletedAt');
|
||||
expect(taskTargets).toHaveProperty('taskId');
|
||||
expect(taskTargets).toHaveProperty('personId');
|
||||
expect(taskTargets).toHaveProperty('companyId');
|
||||
expect(taskTargets).toHaveProperty('opportunityId');
|
||||
expect(taskTargets).toHaveProperty('petId');
|
||||
expect(taskTargets).toHaveProperty('surveyResultId');
|
||||
expect(taskTargets).toHaveProperty('targetPersonId');
|
||||
expect(taskTargets).toHaveProperty('targetCompanyId');
|
||||
expect(taskTargets).toHaveProperty('targetOpportunityId');
|
||||
expect(taskTargets).toHaveProperty('targetPetId');
|
||||
expect(taskTargets).toHaveProperty('targetSurveyResultId');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
+8
-8
@@ -35,22 +35,22 @@ export const TOO_MANY_RELATION_QUERY_GQL_FIELDS = `
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
company {
|
||||
targetCompany {
|
||||
id
|
||||
}
|
||||
note {
|
||||
id
|
||||
}
|
||||
person {
|
||||
targetPerson {
|
||||
id
|
||||
company {
|
||||
id
|
||||
}
|
||||
}
|
||||
company {
|
||||
targetCompany {
|
||||
id
|
||||
}
|
||||
opportunity {
|
||||
targetOpportunity {
|
||||
id
|
||||
}
|
||||
}
|
||||
@@ -60,19 +60,19 @@ export const TOO_MANY_RELATION_QUERY_GQL_FIELDS = `
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
company {
|
||||
targetCompany {
|
||||
id
|
||||
}
|
||||
person {
|
||||
targetPerson {
|
||||
id
|
||||
company {
|
||||
id
|
||||
}
|
||||
}
|
||||
company {
|
||||
targetCompany {
|
||||
id
|
||||
}
|
||||
opportunity {
|
||||
targetOpportunity {
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
+42
-78
@@ -322,7 +322,7 @@ exports[`Object metadata creation should fail v2 when labelPlural contains only
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -340,7 +340,7 @@ exports[`Object metadata creation should fail v2 when labelPlural contains only
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -1029,7 +1029,7 @@ exports[`Object metadata creation should fail v2 when labelPlural exceeds maximu
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -1047,7 +1047,7 @@ exports[`Object metadata creation should fail v2 when labelPlural exceeds maximu
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -1747,7 +1747,7 @@ exports[`Object metadata creation should fail v2 when labelSingular contains onl
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -1765,7 +1765,7 @@ exports[`Object metadata creation should fail v2 when labelSingular contains onl
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -2454,7 +2454,7 @@ exports[`Object metadata creation should fail v2 when labelSingular exceeds maxi
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -2472,7 +2472,7 @@ exports[`Object metadata creation should fail v2 when labelSingular exceeds maxi
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -3172,7 +3172,7 @@ exports[`Object metadata creation should fail v2 when labels are identical 1`] =
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -3190,7 +3190,7 @@ exports[`Object metadata creation should fail v2 when labels are identical 1`] =
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -3879,7 +3879,7 @@ exports[`Object metadata creation should fail v2 when labels with whitespaces re
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -3897,7 +3897,7 @@ exports[`Object metadata creation should fail v2 when labels with whitespaces re
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -4600,7 +4600,7 @@ exports[`Object metadata creation should fail v2 when name exceeds maximum lengt
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is too long",
|
||||
"userFriendlyMessage": "Name is too long",
|
||||
"value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"value": "targetAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
},
|
||||
{
|
||||
"code": "OBJECT_METADATA_NOT_FOUND",
|
||||
@@ -4610,7 +4610,7 @@ exports[`Object metadata creation should fail v2 when name exceeds maximum lengt
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"name": "targetAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -4624,7 +4624,7 @@ exports[`Object metadata creation should fail v2 when name exceeds maximum lengt
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is too long",
|
||||
"userFriendlyMessage": "Name is too long",
|
||||
"value": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"value": "targetAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
},
|
||||
{
|
||||
"code": "OBJECT_METADATA_NOT_FOUND",
|
||||
@@ -4634,7 +4634,7 @@ exports[`Object metadata creation should fail v2 when name exceeds maximum lengt
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"name": "targetAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -5323,7 +5323,7 @@ exports[`Object metadata creation should fail v2 when namePlural has invalid cha
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -5341,7 +5341,7 @@ exports[`Object metadata creation should fail v2 when namePlural has invalid cha
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -6030,7 +6030,7 @@ exports[`Object metadata creation should fail v2 when namePlural is a reserved k
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -6048,7 +6048,7 @@ exports[`Object metadata creation should fail v2 when namePlural is a reserved k
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -6748,7 +6748,7 @@ exports[`Object metadata creation should fail v2 when namePlural is not camelCas
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -6766,7 +6766,7 @@ exports[`Object metadata creation should fail v2 when namePlural is not camelCas
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "listinga",
|
||||
"name": "targetListinga",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -7469,7 +7469,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"value": "a a",
|
||||
"value": "targetA a",
|
||||
},
|
||||
{
|
||||
"code": "OBJECT_METADATA_NOT_FOUND",
|
||||
@@ -7479,7 +7479,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "a a",
|
||||
"name": "targetA a",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -7493,7 +7493,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"value": "a a",
|
||||
"value": "targetA a",
|
||||
},
|
||||
{
|
||||
"code": "OBJECT_METADATA_NOT_FOUND",
|
||||
@@ -7503,7 +7503,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "a a",
|
||||
"name": "targetA a",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -8196,18 +8196,6 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only
|
||||
},
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is too short",
|
||||
"userFriendlyMessage": "Name is too short",
|
||||
"value": "",
|
||||
},
|
||||
{
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"value": "",
|
||||
},
|
||||
{
|
||||
"code": "OBJECT_METADATA_NOT_FOUND",
|
||||
"message": "Relation target object metadata not found",
|
||||
@@ -8216,7 +8204,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "",
|
||||
"name": "target",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -8226,18 +8214,6 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only
|
||||
},
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is too short",
|
||||
"userFriendlyMessage": "Name is too short",
|
||||
"value": "",
|
||||
},
|
||||
{
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"value": "",
|
||||
},
|
||||
{
|
||||
"code": "OBJECT_METADATA_NOT_FOUND",
|
||||
"message": "Relation target object metadata not found",
|
||||
@@ -8246,7 +8222,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "",
|
||||
"name": "target",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -8955,7 +8931,7 @@ exports[`Object metadata creation should fail v2 when nameSingular has invalid c
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"value": "μ",
|
||||
"value": "targetΜ",
|
||||
},
|
||||
{
|
||||
"code": "OBJECT_METADATA_NOT_FOUND",
|
||||
@@ -8965,7 +8941,7 @@ exports[`Object metadata creation should fail v2 when nameSingular has invalid c
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "μ",
|
||||
"name": "targetΜ",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -8979,7 +8955,7 @@ exports[`Object metadata creation should fail v2 when nameSingular has invalid c
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"value": "μ",
|
||||
"value": "targetΜ",
|
||||
},
|
||||
{
|
||||
"code": "OBJECT_METADATA_NOT_FOUND",
|
||||
@@ -8989,7 +8965,7 @@ exports[`Object metadata creation should fail v2 when nameSingular has invalid c
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "μ",
|
||||
"name": "targetΜ",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -9676,12 +9652,6 @@ exports[`Object metadata creation should fail v2 when nameSingular is a reserved
|
||||
},
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "This name is reserved. Use a different name or the system will add "Custom" suffix.",
|
||||
"userFriendlyMessage": "This name is reserved. Use a different name or the system will add "Custom" suffix.",
|
||||
"value": "user",
|
||||
},
|
||||
{
|
||||
"code": "OBJECT_METADATA_NOT_FOUND",
|
||||
"message": "Relation target object metadata not found",
|
||||
@@ -9690,7 +9660,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is a reserved
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "user",
|
||||
"name": "targetUser",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -9700,12 +9670,6 @@ exports[`Object metadata creation should fail v2 when nameSingular is a reserved
|
||||
},
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "This name is reserved. Use a different name or the system will add "Custom" suffix.",
|
||||
"userFriendlyMessage": "This name is reserved. Use a different name or the system will add "Custom" suffix.",
|
||||
"value": "user",
|
||||
},
|
||||
{
|
||||
"code": "OBJECT_METADATA_NOT_FOUND",
|
||||
"message": "Relation target object metadata not found",
|
||||
@@ -9714,7 +9678,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is a reserved
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "user",
|
||||
"name": "targetUser",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -10428,7 +10392,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is not camelC
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"value": "Not_Camel_Case",
|
||||
"value": "targetNot_Camel_Case",
|
||||
},
|
||||
{
|
||||
"code": "OBJECT_METADATA_NOT_FOUND",
|
||||
@@ -10438,7 +10402,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is not camelC
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "Not_Camel_Case",
|
||||
"name": "targetNot_Camel_Case",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -10452,7 +10416,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is not camelC
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"value": "Not_Camel_Case",
|
||||
"value": "targetNot_Camel_Case",
|
||||
},
|
||||
{
|
||||
"code": "OBJECT_METADATA_NOT_FOUND",
|
||||
@@ -10462,7 +10426,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is not camelC
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "Not_Camel_Case",
|
||||
"name": "targetNot_Camel_Case",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -11151,7 +11115,7 @@ exports[`Object metadata creation should fail v2 when names are identical 1`] =
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "fooBar",
|
||||
"name": "targetFooBar",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -11169,7 +11133,7 @@ exports[`Object metadata creation should fail v2 when names are identical 1`] =
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "fooBar",
|
||||
"name": "targetFooBar",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -11858,7 +11822,7 @@ exports[`Object metadata creation should fail v2 when names with whitespaces res
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "fooBar",
|
||||
"name": "targetFooBar",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
@@ -11876,7 +11840,7 @@ exports[`Object metadata creation should fail v2 when names with whitespaces res
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "fooBar",
|
||||
"name": "targetFooBar",
|
||||
"objectMetadataId": Any<String>,
|
||||
"universalIdentifier": Any<String>,
|
||||
},
|
||||
|
||||
@@ -1048,12 +1048,19 @@ export const STANDARD_OBJECTS = {
|
||||
universalIdentifier: '20202020-c02d-4124-9d24-ef123456789b',
|
||||
},
|
||||
note: { universalIdentifier: '20202020-57f3-4f50-9599-fc0f671df003' },
|
||||
person: { universalIdentifier: '20202020-38ca-4aab-92f5-8a605ca2e4c5' },
|
||||
company: { universalIdentifier: 'c500fbc0-d6f2-4982-a959-5a755431696c' },
|
||||
opportunity: {
|
||||
targetPerson: {
|
||||
universalIdentifier: '20202020-38ca-4aab-92f5-8a605ca2e4c5',
|
||||
},
|
||||
targetCompany: {
|
||||
universalIdentifier: 'c500fbc0-d6f2-4982-a959-5a755431696c',
|
||||
},
|
||||
targetOpportunity: {
|
||||
universalIdentifier: '20202020-4e42-417a-a705-76581c9ade79',
|
||||
},
|
||||
},
|
||||
morphIds: {
|
||||
targetMorphId: { morphId: '20202020-f635-435d-ab8d-e1168b375c70' },
|
||||
},
|
||||
indexes: {
|
||||
noteIdIndex: {
|
||||
universalIdentifier: '9294d9e3-0225-4c7f-9d6e-23b4c25b6b24',
|
||||
@@ -1482,12 +1489,19 @@ export const STANDARD_OBJECTS = {
|
||||
universalIdentifier: '20202020-a03d-4164-9d64-fabcdefabcde',
|
||||
},
|
||||
task: { universalIdentifier: '20202020-e881-457a-8758-74aaef4ae78a' },
|
||||
person: { universalIdentifier: '20202020-c8a0-4e85-a016-87e2349cfbec' },
|
||||
company: { universalIdentifier: '20202020-4703-4a4e-948c-487b0c60a92c' },
|
||||
opportunity: {
|
||||
targetPerson: {
|
||||
universalIdentifier: '20202020-c8a0-4e85-a016-87e2349cfbec',
|
||||
},
|
||||
targetCompany: {
|
||||
universalIdentifier: '20202020-4703-4a4e-948c-487b0c60a92c',
|
||||
},
|
||||
targetOpportunity: {
|
||||
universalIdentifier: '20202020-6cb2-4c01-a9a5-aca3dbc11d41',
|
||||
},
|
||||
},
|
||||
morphIds: {
|
||||
targetMorphId: { morphId: '20202020-f636-435d-ab8d-e1168b375c71' },
|
||||
},
|
||||
indexes: {
|
||||
taskIdIndex: {
|
||||
universalIdentifier: '2527e2f6-3558-4d0a-2e9f-56c7d58c9c57',
|
||||
|
||||
Reference in New Issue
Block a user