feat: real-time email & calendar tabs on record pages (#21953)

emails and calendar tabs only refreshed on reload, unlike timeline. this
subscribes to the participant object (messageParticipant /
calendarEventParticipant) for the record's related people over the
existing sse stream and refetches on change.

relatedPersonIds is resolved server-side so any object with the tab
inherits it, no per-object code. resolver stays the source of truth so
visibility masking is untouched.
This commit is contained in:
neo773
2026-06-22 19:57:09 +05:30
committed by GitHub
parent 068a8d4efe
commit c608792aea
11 changed files with 102 additions and 11 deletions
@@ -1,5 +1,6 @@
import { Field, Int, ObjectType } from '@nestjs/graphql';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { TimelineCalendarEventDTO } from 'src/engine/core-modules/calendar/dtos/timeline-calendar-event.dto';
@ObjectType('TimelineCalendarEventsWithTotal')
@@ -9,4 +10,7 @@ export class TimelineCalendarEventsWithTotalDTO {
@Field(() => [TimelineCalendarEventDTO])
timelineCalendarEvents: TimelineCalendarEventDTO[];
@Field(() => [UUIDScalarType])
relatedPersonIds: string[];
}
@@ -88,6 +88,7 @@ export class TimelineCalendarEventService {
return {
totalNumberOfCalendarEvents,
timelineCalendarEvents: [],
relatedPersonIds: personIds,
};
}
@@ -253,6 +254,7 @@ export class TimelineCalendarEventService {
return {
totalNumberOfCalendarEvents,
timelineCalendarEvents,
relatedPersonIds: personIds,
};
},
authContext,
@@ -284,6 +286,7 @@ export class TimelineCalendarEventService {
return {
totalNumberOfCalendarEvents: 0,
timelineCalendarEvents: [],
relatedPersonIds: [],
};
}
@@ -1,5 +1,6 @@
import { Field, Int, ObjectType } from '@nestjs/graphql';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { TimelineThreadDTO } from 'src/engine/core-modules/messaging/dtos/timeline-thread.dto';
@ObjectType('TimelineThreadsWithTotal')
@@ -9,4 +10,7 @@ export class TimelineThreadsWithTotalDTO {
@Field(() => [TimelineThreadDTO])
timelineThreads: TimelineThreadDTO[];
@Field(() => [UUIDScalarType])
relatedPersonIds: string[];
}
@@ -34,6 +34,7 @@ export class GetMessagesService {
return {
totalNumberOfThreads: 0,
timelineThreads: [],
relatedPersonIds: personIds,
};
}
@@ -61,6 +62,7 @@ export class GetMessagesService {
threadParticipantsByThreadId,
threadVisibilityByThreadId,
),
relatedPersonIds: personIds,
};
}
@@ -82,6 +84,7 @@ export class GetMessagesService {
return {
totalNumberOfThreads: 0,
timelineThreads: [],
relatedPersonIds: [],
};
}