Refactor global datasource part 3 (#16447)
## Context Following https://github.com/twentyhq/twenty/pull/16399 Now using the new global orm manager everywhere and returning a GlobalDatasource/WorkspaceDatasource based on a feature flag. This means we now need to wrap all our ORM calls within executeInWorkspaceContext callback (at least for now) so the global datasource can dynamically hydrate its context via the new store (the global datasource does not store anything related to workspaces as it is now a unique singleton). If feature flag is off it still uses local data stored in the workspace datasource.
This commit is contained in:
+74
-59
@@ -4,14 +4,15 @@ import { TIMELINE_THREADS_DEFAULT_PAGE_SIZE } from 'src/engine/core-modules/mess
|
||||
import { type TimelineThreadsWithTotalDTO } from 'src/engine/core-modules/messaging/dtos/timeline-threads-with-total.dto';
|
||||
import { TimelineMessagingService } from 'src/engine/core-modules/messaging/services/timeline-messaging.service';
|
||||
import { formatThreads } from 'src/engine/core-modules/messaging/utils/format-threads.util';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
|
||||
import { type OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
|
||||
import { type PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
|
||||
|
||||
@Injectable()
|
||||
export class GetMessagesService {
|
||||
constructor(
|
||||
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
private readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
|
||||
private readonly timelineMessagingService: TimelineMessagingService,
|
||||
) {}
|
||||
|
||||
@@ -73,38 +74,45 @@ export class GetMessagesService {
|
||||
page = 1,
|
||||
pageSize: number = TIMELINE_THREADS_DEFAULT_PAGE_SIZE,
|
||||
): Promise<TimelineThreadsWithTotalDTO> {
|
||||
const personRepository =
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<PersonWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'person',
|
||||
);
|
||||
const personIds = (
|
||||
await personRepository.find({
|
||||
where: {
|
||||
companyId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
})
|
||||
).map((person) => person.id);
|
||||
const authContext = buildSystemAuthContext(workspaceId);
|
||||
|
||||
if (personIds.length === 0) {
|
||||
return {
|
||||
totalNumberOfThreads: 0,
|
||||
timelineThreads: [],
|
||||
};
|
||||
}
|
||||
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
|
||||
authContext,
|
||||
async () => {
|
||||
const personRepository =
|
||||
await this.globalWorkspaceOrmManager.getRepository<PersonWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'person',
|
||||
);
|
||||
const personIds = (
|
||||
await personRepository.find({
|
||||
where: {
|
||||
companyId,
|
||||
},
|
||||
select: {
|
||||
id: true,
|
||||
},
|
||||
})
|
||||
).map((person) => person.id);
|
||||
|
||||
const messageThreads = await this.getMessagesFromPersonIds(
|
||||
workspaceMemberId,
|
||||
personIds,
|
||||
workspaceId,
|
||||
page,
|
||||
pageSize,
|
||||
if (personIds.length === 0) {
|
||||
return {
|
||||
totalNumberOfThreads: 0,
|
||||
timelineThreads: [],
|
||||
};
|
||||
}
|
||||
|
||||
const messageThreads = await this.getMessagesFromPersonIds(
|
||||
workspaceMemberId,
|
||||
personIds,
|
||||
workspaceId,
|
||||
page,
|
||||
pageSize,
|
||||
);
|
||||
|
||||
return messageThreads;
|
||||
},
|
||||
);
|
||||
|
||||
return messageThreads;
|
||||
}
|
||||
|
||||
async getMessagesFromOpportunityId(
|
||||
@@ -114,36 +122,43 @@ export class GetMessagesService {
|
||||
page = 1,
|
||||
pageSize: number = TIMELINE_THREADS_DEFAULT_PAGE_SIZE,
|
||||
): Promise<TimelineThreadsWithTotalDTO> {
|
||||
const opportunityRepository =
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<OpportunityWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'opportunity',
|
||||
);
|
||||
const authContext = buildSystemAuthContext(workspaceId);
|
||||
|
||||
const opportunity = await opportunityRepository.findOne({
|
||||
where: {
|
||||
id: opportunityId,
|
||||
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
|
||||
authContext,
|
||||
async () => {
|
||||
const opportunityRepository =
|
||||
await this.globalWorkspaceOrmManager.getRepository<OpportunityWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'opportunity',
|
||||
);
|
||||
|
||||
const opportunity = await opportunityRepository.findOne({
|
||||
where: {
|
||||
id: opportunityId,
|
||||
},
|
||||
select: {
|
||||
companyId: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!opportunity?.companyId) {
|
||||
return {
|
||||
totalNumberOfThreads: 0,
|
||||
timelineThreads: [],
|
||||
};
|
||||
}
|
||||
|
||||
const messageThreads = await this.getMessagesFromCompanyId(
|
||||
workspaceMemberId,
|
||||
opportunity.companyId,
|
||||
workspaceId,
|
||||
page,
|
||||
pageSize,
|
||||
);
|
||||
|
||||
return messageThreads;
|
||||
},
|
||||
select: {
|
||||
companyId: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!opportunity?.companyId) {
|
||||
return {
|
||||
totalNumberOfThreads: 0,
|
||||
timelineThreads: [],
|
||||
};
|
||||
}
|
||||
|
||||
const messageThreads = await this.getMessagesFromCompanyId(
|
||||
workspaceMemberId,
|
||||
opportunity.companyId,
|
||||
workspaceId,
|
||||
page,
|
||||
pageSize,
|
||||
);
|
||||
|
||||
return messageThreads;
|
||||
}
|
||||
}
|
||||
|
||||
+203
-177
@@ -1,10 +1,11 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { In } from 'typeorm';
|
||||
import { MessageParticipantRole } from 'twenty-shared/types';
|
||||
import { In } from 'typeorm';
|
||||
|
||||
import { type TimelineThreadDTO } from 'src/engine/core-modules/messaging/dtos/timeline-thread.dto';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { buildSystemAuthContext } from 'src/engine/twenty-orm/utils/build-system-auth-context.util';
|
||||
import { MessageChannelVisibility } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||
import { type MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
|
||||
import { type MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity';
|
||||
@@ -12,7 +13,7 @@ import { type MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/
|
||||
@Injectable()
|
||||
export class TimelineMessagingService {
|
||||
constructor(
|
||||
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
private readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
|
||||
) {}
|
||||
|
||||
public async getAndCountMessageThreads(
|
||||
@@ -31,63 +32,74 @@ export class TimelineMessagingService {
|
||||
>[];
|
||||
totalNumberOfThreads: number;
|
||||
}> {
|
||||
const messageThreadRepository =
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageThreadWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'messageThread',
|
||||
);
|
||||
const authContext = buildSystemAuthContext(workspaceId);
|
||||
|
||||
const totalNumberOfThreads = await messageThreadRepository
|
||||
.createQueryBuilder('messageThread')
|
||||
.innerJoin('messageThread.messages', 'messages')
|
||||
.innerJoin('messages.messageParticipants', 'messageParticipants')
|
||||
.where('messageParticipants.personId IN(:...personIds)', { personIds })
|
||||
.groupBy('messageThread.id')
|
||||
.getCount();
|
||||
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
|
||||
authContext,
|
||||
async () => {
|
||||
const messageThreadRepository =
|
||||
await this.globalWorkspaceOrmManager.getRepository<MessageThreadWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'messageThread',
|
||||
);
|
||||
|
||||
const threadIdsQuery = await messageThreadRepository
|
||||
.createQueryBuilder('messageThread')
|
||||
.select('messageThread.id', 'id')
|
||||
.addSelect('MAX(messages.receivedAt)', 'max_received_at')
|
||||
.innerJoin('messageThread.messages', 'messages')
|
||||
.innerJoin('messages.messageParticipants', 'messageParticipants')
|
||||
.where('messageParticipants.personId IN (:...personIds)', { personIds })
|
||||
.groupBy('messageThread.id')
|
||||
.orderBy('max_received_at', 'DESC')
|
||||
.offset(offset)
|
||||
.limit(pageSize)
|
||||
.getRawMany();
|
||||
const totalNumberOfThreads = await messageThreadRepository
|
||||
.createQueryBuilder('messageThread')
|
||||
.innerJoin('messageThread.messages', 'messages')
|
||||
.innerJoin('messages.messageParticipants', 'messageParticipants')
|
||||
.where('messageParticipants.personId IN(:...personIds)', {
|
||||
personIds,
|
||||
})
|
||||
.groupBy('messageThread.id')
|
||||
.getCount();
|
||||
|
||||
const messageThreadIds = threadIdsQuery.map((thread) => thread.id);
|
||||
const threadIdsQuery = await messageThreadRepository
|
||||
.createQueryBuilder('messageThread')
|
||||
.select('messageThread.id', 'id')
|
||||
.addSelect('MAX(messages.receivedAt)', 'max_received_at')
|
||||
.innerJoin('messageThread.messages', 'messages')
|
||||
.innerJoin('messages.messageParticipants', 'messageParticipants')
|
||||
.where('messageParticipants.personId IN (:...personIds)', {
|
||||
personIds,
|
||||
})
|
||||
.groupBy('messageThread.id')
|
||||
.orderBy('max_received_at', 'DESC')
|
||||
.offset(offset)
|
||||
.limit(pageSize)
|
||||
.getRawMany();
|
||||
|
||||
const messageThreads = await messageThreadRepository.find({
|
||||
where: {
|
||||
id: In(messageThreadIds),
|
||||
},
|
||||
order: {
|
||||
messages: {
|
||||
receivedAt: 'DESC',
|
||||
},
|
||||
},
|
||||
relations: ['messages'],
|
||||
});
|
||||
const messageThreadIds = threadIdsQuery.map((thread) => thread.id);
|
||||
|
||||
return {
|
||||
messageThreads: messageThreads.map((messageThread) => {
|
||||
const lastMessage = messageThread.messages[0];
|
||||
const firstMessage =
|
||||
messageThread.messages[messageThread.messages.length - 1];
|
||||
const messageThreads = await messageThreadRepository.find({
|
||||
where: {
|
||||
id: In(messageThreadIds),
|
||||
},
|
||||
order: {
|
||||
messages: {
|
||||
receivedAt: 'DESC',
|
||||
},
|
||||
},
|
||||
relations: ['messages'],
|
||||
});
|
||||
|
||||
return {
|
||||
id: messageThread.id,
|
||||
subject: firstMessage.subject ?? '',
|
||||
lastMessageBody: lastMessage.text ?? '',
|
||||
lastMessageReceivedAt: lastMessage.receivedAt ?? new Date(),
|
||||
numberOfMessagesInThread: messageThread.messages.length,
|
||||
messageThreads: messageThreads.map((messageThread) => {
|
||||
const lastMessage = messageThread.messages[0];
|
||||
const firstMessage =
|
||||
messageThread.messages[messageThread.messages.length - 1];
|
||||
|
||||
return {
|
||||
id: messageThread.id,
|
||||
subject: firstMessage.subject ?? '',
|
||||
lastMessageBody: lastMessage.text ?? '',
|
||||
lastMessageReceivedAt: lastMessage.receivedAt ?? new Date(),
|
||||
numberOfMessagesInThread: messageThread.messages.length,
|
||||
};
|
||||
}),
|
||||
totalNumberOfThreads,
|
||||
};
|
||||
}),
|
||||
totalNumberOfThreads,
|
||||
};
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
public async getThreadParticipantsByThreadId(
|
||||
@@ -96,89 +108,96 @@ export class TimelineMessagingService {
|
||||
): Promise<{
|
||||
[key: string]: MessageParticipantWorkspaceEntity[];
|
||||
}> {
|
||||
const messageParticipantRepository =
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageParticipantWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'messageParticipant',
|
||||
);
|
||||
const authContext = buildSystemAuthContext(workspaceId);
|
||||
|
||||
const threadParticipants = await messageParticipantRepository
|
||||
.createQueryBuilder()
|
||||
.select('messageParticipant')
|
||||
.addSelect('message.messageThreadId')
|
||||
.addSelect('message.receivedAt')
|
||||
.leftJoinAndSelect('messageParticipant.person', 'person')
|
||||
.leftJoinAndSelect(
|
||||
'messageParticipant.workspaceMember',
|
||||
'workspaceMember',
|
||||
)
|
||||
.leftJoin('messageParticipant.message', 'message')
|
||||
.where('message.messageThreadId = ANY(:messageThreadIds)', {
|
||||
messageThreadIds,
|
||||
})
|
||||
.andWhere('messageParticipant.role = :role', {
|
||||
role: MessageParticipantRole.FROM,
|
||||
})
|
||||
.orderBy('message.messageThreadId')
|
||||
.distinctOn(['message.messageThreadId', 'messageParticipant.handle'])
|
||||
.getMany();
|
||||
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
|
||||
authContext,
|
||||
async () => {
|
||||
const messageParticipantRepository =
|
||||
await this.globalWorkspaceOrmManager.getRepository<MessageParticipantWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'messageParticipant',
|
||||
);
|
||||
|
||||
// This is because subqueries are not handled by twentyORM
|
||||
const orderedThreadParticipants = threadParticipants.sort(
|
||||
(a, b) =>
|
||||
(a.message.receivedAt ?? new Date()).getTime() -
|
||||
(b.message.receivedAt ?? new Date()).getTime(),
|
||||
);
|
||||
const threadParticipants = await messageParticipantRepository
|
||||
.createQueryBuilder()
|
||||
.select('messageParticipant')
|
||||
.addSelect('message.messageThreadId')
|
||||
.addSelect('message.receivedAt')
|
||||
.leftJoinAndSelect('messageParticipant.person', 'person')
|
||||
.leftJoinAndSelect(
|
||||
'messageParticipant.workspaceMember',
|
||||
'workspaceMember',
|
||||
)
|
||||
.leftJoin('messageParticipant.message', 'message')
|
||||
.where('message.messageThreadId = ANY(:messageThreadIds)', {
|
||||
messageThreadIds,
|
||||
})
|
||||
.andWhere('messageParticipant.role = :role', {
|
||||
role: MessageParticipantRole.FROM,
|
||||
})
|
||||
.orderBy('message.messageThreadId')
|
||||
.distinctOn(['message.messageThreadId', 'messageParticipant.handle'])
|
||||
.getMany();
|
||||
|
||||
// This is because composite fields are not handled correctly by the ORM
|
||||
const threadParticipantsWithCompositeFields = orderedThreadParticipants.map(
|
||||
(threadParticipant) => ({
|
||||
...threadParticipant,
|
||||
person: {
|
||||
id: threadParticipant.person?.id,
|
||||
name: {
|
||||
//eslint-disable-next-line
|
||||
//@ts-ignore
|
||||
firstName: threadParticipant.person?.nameFirstName,
|
||||
//eslint-disable-next-line
|
||||
//@ts-ignore
|
||||
lastName: threadParticipant.person?.nameLastName,
|
||||
},
|
||||
avatarUrl: threadParticipant.person?.avatarUrl,
|
||||
},
|
||||
workspaceMember: {
|
||||
id: threadParticipant.workspaceMember?.id,
|
||||
name: {
|
||||
//eslint-disable-next-line
|
||||
//@ts-ignore
|
||||
firstName: threadParticipant.workspaceMember?.nameFirstName,
|
||||
//eslint-disable-next-line
|
||||
//@ts-ignore
|
||||
lastName: threadParticipant.workspaceMember?.nameLastName,
|
||||
},
|
||||
avatarUrl: threadParticipant.workspaceMember?.avatarUrl,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
return threadParticipantsWithCompositeFields.reduce(
|
||||
(threadParticipantsAcc, threadParticipant) => {
|
||||
if (!threadParticipant.message.messageThreadId)
|
||||
return threadParticipantsAcc;
|
||||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
if (!threadParticipantsAcc[threadParticipant.message.messageThreadId])
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
threadParticipantsAcc[threadParticipant.message.messageThreadId] = [];
|
||||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
threadParticipantsAcc[threadParticipant.message.messageThreadId].push(
|
||||
threadParticipant,
|
||||
const orderedThreadParticipants = threadParticipants.sort(
|
||||
(a, b) =>
|
||||
(a.message.receivedAt ?? new Date()).getTime() -
|
||||
(b.message.receivedAt ?? new Date()).getTime(),
|
||||
);
|
||||
|
||||
return threadParticipantsAcc;
|
||||
const threadParticipantsWithCompositeFields =
|
||||
orderedThreadParticipants.map((threadParticipant) => ({
|
||||
...threadParticipant,
|
||||
person: {
|
||||
id: threadParticipant.person?.id,
|
||||
name: {
|
||||
//eslint-disable-next-line
|
||||
//@ts-ignore
|
||||
firstName: threadParticipant.person?.nameFirstName,
|
||||
//eslint-disable-next-line
|
||||
//@ts-ignore
|
||||
lastName: threadParticipant.person?.nameLastName,
|
||||
},
|
||||
avatarUrl: threadParticipant.person?.avatarUrl,
|
||||
},
|
||||
workspaceMember: {
|
||||
id: threadParticipant.workspaceMember?.id,
|
||||
name: {
|
||||
//eslint-disable-next-line
|
||||
//@ts-ignore
|
||||
firstName: threadParticipant.workspaceMember?.nameFirstName,
|
||||
//eslint-disable-next-line
|
||||
//@ts-ignore
|
||||
lastName: threadParticipant.workspaceMember?.nameLastName,
|
||||
},
|
||||
avatarUrl: threadParticipant.workspaceMember?.avatarUrl,
|
||||
},
|
||||
}));
|
||||
|
||||
return threadParticipantsWithCompositeFields.reduce(
|
||||
(threadParticipantsAcc, threadParticipant) => {
|
||||
if (!threadParticipant.message.messageThreadId)
|
||||
return threadParticipantsAcc;
|
||||
|
||||
if (
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
!threadParticipantsAcc[threadParticipant.message.messageThreadId]
|
||||
)
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
threadParticipantsAcc[threadParticipant.message.messageThreadId] =
|
||||
[];
|
||||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
threadParticipantsAcc[
|
||||
threadParticipant.message.messageThreadId
|
||||
].push(threadParticipant);
|
||||
|
||||
return threadParticipantsAcc;
|
||||
},
|
||||
{},
|
||||
);
|
||||
},
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -189,58 +208,65 @@ export class TimelineMessagingService {
|
||||
): Promise<{
|
||||
[key: string]: MessageChannelVisibility;
|
||||
}> {
|
||||
const messageThreadRepository =
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageThreadWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'messageThread',
|
||||
);
|
||||
const authContext = buildSystemAuthContext(workspaceId);
|
||||
|
||||
const threadVisibility = await messageThreadRepository
|
||||
.createQueryBuilder()
|
||||
.select('messageThread.id', 'id')
|
||||
.addSelect('messageChannel.visibility', 'visibility')
|
||||
.addSelect('connectedAccount.accountOwnerId', 'accountOwnerId')
|
||||
.leftJoin('messageThread.messages', 'message')
|
||||
.leftJoin(
|
||||
'message.messageChannelMessageAssociations',
|
||||
'messageChannelMessageAssociation',
|
||||
)
|
||||
.leftJoin(
|
||||
'messageChannelMessageAssociation.messageChannel',
|
||||
'messageChannel',
|
||||
)
|
||||
.leftJoin('messageChannel.connectedAccount', 'connectedAccount')
|
||||
.where('messageThread.id = ANY(:messageThreadIds)', {
|
||||
messageThreadIds: messageThreadIds,
|
||||
})
|
||||
.getRawMany();
|
||||
return this.globalWorkspaceOrmManager.executeInWorkspaceContext(
|
||||
authContext,
|
||||
async () => {
|
||||
const messageThreadRepository =
|
||||
await this.globalWorkspaceOrmManager.getRepository<MessageThreadWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'messageThread',
|
||||
);
|
||||
|
||||
const visibilityValues = Object.values(MessageChannelVisibility);
|
||||
|
||||
const threadVisibilityByThreadId: {
|
||||
[key: string]: MessageChannelVisibility;
|
||||
} = threadVisibility.reduce((threadVisibilityAcc, threadVisibility) => {
|
||||
if (threadVisibility.accountOwnerId === workspaceMemberId) {
|
||||
threadVisibilityAcc[threadVisibility.id] =
|
||||
MessageChannelVisibility.SHARE_EVERYTHING;
|
||||
|
||||
return threadVisibilityAcc;
|
||||
}
|
||||
|
||||
threadVisibilityAcc[threadVisibility.id] =
|
||||
visibilityValues[
|
||||
Math.max(
|
||||
visibilityValues.indexOf(threadVisibility.visibility),
|
||||
visibilityValues.indexOf(
|
||||
threadVisibilityAcc[threadVisibility.id] ??
|
||||
MessageChannelVisibility.METADATA,
|
||||
),
|
||||
const threadVisibility = await messageThreadRepository
|
||||
.createQueryBuilder()
|
||||
.select('messageThread.id', 'id')
|
||||
.addSelect('messageChannel.visibility', 'visibility')
|
||||
.addSelect('connectedAccount.accountOwnerId', 'accountOwnerId')
|
||||
.leftJoin('messageThread.messages', 'message')
|
||||
.leftJoin(
|
||||
'message.messageChannelMessageAssociations',
|
||||
'messageChannelMessageAssociation',
|
||||
)
|
||||
];
|
||||
.leftJoin(
|
||||
'messageChannelMessageAssociation.messageChannel',
|
||||
'messageChannel',
|
||||
)
|
||||
.leftJoin('messageChannel.connectedAccount', 'connectedAccount')
|
||||
.where('messageThread.id = ANY(:messageThreadIds)', {
|
||||
messageThreadIds: messageThreadIds,
|
||||
})
|
||||
.getRawMany();
|
||||
|
||||
return threadVisibilityAcc;
|
||||
}, {});
|
||||
const visibilityValues = Object.values(MessageChannelVisibility);
|
||||
|
||||
return threadVisibilityByThreadId;
|
||||
const threadVisibilityByThreadId: {
|
||||
[key: string]: MessageChannelVisibility;
|
||||
} = threadVisibility.reduce((threadVisibilityAcc, threadVisibility) => {
|
||||
if (threadVisibility.accountOwnerId === workspaceMemberId) {
|
||||
threadVisibilityAcc[threadVisibility.id] =
|
||||
MessageChannelVisibility.SHARE_EVERYTHING;
|
||||
|
||||
return threadVisibilityAcc;
|
||||
}
|
||||
|
||||
threadVisibilityAcc[threadVisibility.id] =
|
||||
visibilityValues[
|
||||
Math.max(
|
||||
visibilityValues.indexOf(threadVisibility.visibility),
|
||||
visibilityValues.indexOf(
|
||||
threadVisibilityAcc[threadVisibility.id] ??
|
||||
MessageChannelVisibility.METADATA,
|
||||
),
|
||||
)
|
||||
];
|
||||
|
||||
return threadVisibilityAcc;
|
||||
}, {});
|
||||
|
||||
return threadVisibilityByThreadId;
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user