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:
Abdullah.
2026-02-04 07:53:06 +05:00
committed by GitHub
parent 9aba2f62e1
commit 7867617385
43 changed files with 1998 additions and 274 deletions
@@ -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,
});
}
@@ -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,
});
}
@@ -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) {