From 3831ddc0025b1752a0968df83c9e30448f751906 Mon Sep 17 00:00:00 2001 From: bosiraphael <71827178+bosiraphael@users.noreply.github.com> Date: Wed, 7 Feb 2024 16:35:19 +0100 Subject: [PATCH] 3803 use email visibility to display only the shared information backend (#3871) * update dto * wip * compute thread visibility * fix bugs * fix bug * improve typing * working * update according to comments * use string --- .../twenty-front/src/generated/graphql.tsx | 19 ++++++-- .../fragments/timelineThreadFragment.ts | 1 + .../messaging/dtos/timeline-thread.dto.ts | 3 ++ .../messaging/timeline-messaging.service.ts | 48 +++++++++++++++++++ 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/packages/twenty-front/src/generated/graphql.tsx b/packages/twenty-front/src/generated/graphql.tsx index 785e6d88c..616194ac8 100644 --- a/packages/twenty-front/src/generated/graphql.tsx +++ b/packages/twenty-front/src/generated/graphql.tsx @@ -495,6 +495,7 @@ export type TimelineThread = { participantCount: Scalars['Float']; read: Scalars['Boolean']; subject: Scalars['String']; + visibility: Scalars['String']; }; export type TimelineThreadParticipant = { @@ -710,9 +711,9 @@ export type RelationEdge = { export type ParticipantFragmentFragment = { __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }; -export type TimelineThreadFragmentFragment = { __typename?: 'TimelineThread', id: string, read: boolean, lastMessageReceivedAt: string, lastMessageBody: string, subject: string, numberOfMessagesInThread: number, participantCount: number, firstParticipant: { __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }, lastTwoParticipants: Array<{ __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }; +export type TimelineThreadFragmentFragment = { __typename?: 'TimelineThread', id: string, read: boolean, visibility: string, lastMessageReceivedAt: string, lastMessageBody: string, subject: string, numberOfMessagesInThread: number, participantCount: number, firstParticipant: { __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }, lastTwoParticipants: Array<{ __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }; -export type TimelineThreadsWithTotalFragmentFragment = { __typename?: 'TimelineThreadsWithTotal', totalNumberOfThreads: number, timelineThreads: Array<{ __typename?: 'TimelineThread', id: string, read: boolean, lastMessageReceivedAt: string, lastMessageBody: string, subject: string, numberOfMessagesInThread: number, participantCount: number, firstParticipant: { __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }, lastTwoParticipants: Array<{ __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }> }; +export type TimelineThreadsWithTotalFragmentFragment = { __typename?: 'TimelineThreadsWithTotal', totalNumberOfThreads: number, timelineThreads: Array<{ __typename?: 'TimelineThread', id: string, read: boolean, visibility: string, lastMessageReceivedAt: string, lastMessageBody: string, subject: string, numberOfMessagesInThread: number, participantCount: number, firstParticipant: { __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }, lastTwoParticipants: Array<{ __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }> }; export type GetTimelineThreadsFromCompanyIdQueryVariables = Exact<{ companyId: Scalars['ID']; @@ -721,7 +722,7 @@ export type GetTimelineThreadsFromCompanyIdQueryVariables = Exact<{ }>; -export type GetTimelineThreadsFromCompanyIdQuery = { __typename?: 'Query', getTimelineThreadsFromCompanyId: { __typename?: 'TimelineThreadsWithTotal', totalNumberOfThreads: number, timelineThreads: Array<{ __typename?: 'TimelineThread', id: string, read: boolean, lastMessageReceivedAt: string, lastMessageBody: string, subject: string, numberOfMessagesInThread: number, participantCount: number, firstParticipant: { __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }, lastTwoParticipants: Array<{ __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }> } }; +export type GetTimelineThreadsFromCompanyIdQuery = { __typename?: 'Query', getTimelineThreadsFromCompanyId: { __typename?: 'TimelineThreadsWithTotal', totalNumberOfThreads: number, timelineThreads: Array<{ __typename?: 'TimelineThread', id: string, read: boolean, visibility: string, lastMessageReceivedAt: string, lastMessageBody: string, subject: string, numberOfMessagesInThread: number, participantCount: number, firstParticipant: { __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }, lastTwoParticipants: Array<{ __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }> } }; export type GetTimelineThreadsFromPersonIdQueryVariables = Exact<{ personId: Scalars['ID']; @@ -730,7 +731,9 @@ export type GetTimelineThreadsFromPersonIdQueryVariables = Exact<{ }>; -export type GetTimelineThreadsFromPersonIdQuery = { __typename?: 'Query', getTimelineThreadsFromPersonId: { __typename?: 'TimelineThreadsWithTotal', totalNumberOfThreads: number, timelineThreads: Array<{ __typename?: 'TimelineThread', id: string, read: boolean, lastMessageReceivedAt: string, lastMessageBody: string, subject: string, numberOfMessagesInThread: number, participantCount: number, firstParticipant: { __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }, lastTwoParticipants: Array<{ __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }> } }; +export type GetTimelineThreadsFromPersonIdQuery = { __typename?: 'Query', getTimelineThreadsFromPersonId: { __typename?: 'TimelineThreadsWithTotal', totalNumberOfThreads: number, timelineThreads: Array<{ __typename?: 'TimelineThread', id: string, read: boolean, visibility: string, lastMessageReceivedAt: string, lastMessageBody: string, subject: string, numberOfMessagesInThread: number, participantCount: number, firstParticipant: { __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }, lastTwoParticipants: Array<{ __typename?: 'TimelineThreadParticipant', personId?: string | null, workspaceMemberId?: string | null, firstName: string, lastName: string, displayName: string, avatarUrl: string, handle: string }> }> } }; + +export type TimelineThreadFragment = { __typename?: 'TimelineThread', id: string, subject: string, lastMessageReceivedAt: string }; export type CreateEventMutationVariables = Exact<{ type: Scalars['String']; @@ -898,6 +901,7 @@ export const TimelineThreadFragmentFragmentDoc = gql` fragment TimelineThreadFragment on TimelineThread { id read + visibility firstParticipant { ...ParticipantFragment } @@ -919,6 +923,13 @@ export const TimelineThreadsWithTotalFragmentFragmentDoc = gql` } } ${TimelineThreadFragmentFragmentDoc}`; +export const TimelineThreadFragmentDoc = gql` + fragment timelineThread on TimelineThread { + id + subject + lastMessageReceivedAt +} + `; export const AuthTokenFragmentFragmentDoc = gql` fragment AuthTokenFragment on AuthToken { token diff --git a/packages/twenty-front/src/modules/activities/emails/queries/fragments/timelineThreadFragment.ts b/packages/twenty-front/src/modules/activities/emails/queries/fragments/timelineThreadFragment.ts index c58458658..d5728f23e 100644 --- a/packages/twenty-front/src/modules/activities/emails/queries/fragments/timelineThreadFragment.ts +++ b/packages/twenty-front/src/modules/activities/emails/queries/fragments/timelineThreadFragment.ts @@ -6,6 +6,7 @@ export const timelineThreadFragment = gql` fragment TimelineThreadFragment on TimelineThread { id read + visibility firstParticipant { ...ParticipantFragment } diff --git a/packages/twenty-server/src/core/messaging/dtos/timeline-thread.dto.ts b/packages/twenty-server/src/core/messaging/dtos/timeline-thread.dto.ts index 6590e85ac..32402d314 100644 --- a/packages/twenty-server/src/core/messaging/dtos/timeline-thread.dto.ts +++ b/packages/twenty-server/src/core/messaging/dtos/timeline-thread.dto.ts @@ -12,6 +12,9 @@ export class TimelineThread { @Field() read: boolean; + @Field() + visibility: string; + @Field() firstParticipant: TimelineThreadParticipant; diff --git a/packages/twenty-server/src/core/messaging/timeline-messaging.service.ts b/packages/twenty-server/src/core/messaging/timeline-messaging.service.ts index 2ea042be9..cf61c7e1d 100644 --- a/packages/twenty-server/src/core/messaging/timeline-messaging.service.ts +++ b/packages/twenty-server/src/core/messaging/timeline-messaging.service.ts @@ -317,6 +317,53 @@ export class TimelineMessagingService { return messageThreadIdAcc; }, {}); + const threadVisibility: + | { + id: string; + visibility: 'metadata' | 'subject' | 'share_everything'; + }[] + | undefined = await workspaceDataSource?.query( + ` + SELECT + "messageThread".id, + "messageChannel".visibility + FROM + ${dataSourceMetadata.schema}."messageThread" "messageThread" + LEFT JOIN + ${dataSourceMetadata.schema}."message" message ON "message"."messageThreadId" = "messageThread".id + LEFT JOIN + ${dataSourceMetadata.schema}."messageChannelMessageAssociation" "messageChannelMessageAssociation" ON "messageChannelMessageAssociation"."messageId" = message.id + LEFT JOIN + ${dataSourceMetadata.schema}."messageChannel" "messageChannel" ON "messageChannel".id = "messageChannelMessageAssociation"."messageChannelId" + WHERE + "messageThread".id = ANY($1) + `, + [messageThreadIds], + ); + + const visibilityValues = ['metadata', 'subject', 'share_everything']; + + const threadVisibilityByThreadId: + | { + [key: string]: 'metadata' | 'subject' | 'share_everything'; + } + | undefined = threadVisibility?.reduce( + (threadVisibilityAcc, threadVisibility) => { + threadVisibilityAcc[threadVisibility.id] = + visibilityValues[ + Math.max( + visibilityValues.indexOf(threadVisibility.visibility), + visibilityValues.indexOf( + threadVisibilityAcc[threadVisibility.id] ?? 'metadata', + ), + ) + ]; + + return threadVisibilityAcc; + }, + {}, + ); + const timelineThreads = messageThreadIds.map((messageThreadId) => { const threadParticipants = threadParticipantsByThreadId[messageThreadId]; @@ -364,6 +411,7 @@ export class TimelineMessagingService { lastTwoParticipants, lastMessageReceivedAt: thread.lastMessageReceivedAt, lastMessageBody: thread.lastMessageBody, + visibility: threadVisibilityByThreadId?.[messageThreadId] ?? 'metadata', subject: threadSubject, numberOfMessagesInThread: numberOfMessages, participantCount: threadParticipants.length,