POC timeline activity (#5697)
TODO: - remove WorkspaceIsNotAuditLogged decorators on activity/activityTarget to log task/note creations - handle attachments - fix css and remove unnecessary styled components or duplicates
This commit is contained in:
@ -44,9 +44,11 @@ export const EmailThreadHeader = ({
|
||||
<StyledContainer>
|
||||
<StyledHead>
|
||||
<StyledHeading>{subject}</StyledHeading>
|
||||
<StyledContent>
|
||||
Last message {beautifyPastDateRelativeToNow(lastMessageSentAt)}
|
||||
</StyledContent>
|
||||
{lastMessageSentAt && (
|
||||
<StyledContent>
|
||||
Last message {beautifyPastDateRelativeToNow(lastMessageSentAt)}
|
||||
</StyledContent>
|
||||
)}
|
||||
</StyledHead>
|
||||
</StyledContainer>
|
||||
);
|
||||
|
||||
@ -43,11 +43,14 @@ export const RightDrawerEmailThread = () => {
|
||||
|
||||
useRegisterClickOutsideListenerCallback({
|
||||
callbackId:
|
||||
'EmailThreadClickOutsideCallBack-' + (thread.id ?? 'no-thread-id'),
|
||||
'EmailThreadClickOutsideCallBack-' + (thread?.id ?? 'no-thread-id'),
|
||||
callbackFunction: useRecoilCallback(
|
||||
({ set }) =>
|
||||
() => {
|
||||
set(emailThreadIdWhenEmailThreadWasClosedState, thread.id);
|
||||
set(
|
||||
emailThreadIdWhenEmailThreadWasClosedState,
|
||||
thread?.id ?? 'no-thread-id',
|
||||
);
|
||||
},
|
||||
[thread],
|
||||
),
|
||||
@ -71,14 +74,14 @@ export const RightDrawerEmailThread = () => {
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<EmailThreadHeader
|
||||
subject={thread.subject}
|
||||
lastMessageSentAt={thread.lastMessageReceivedAt}
|
||||
/>
|
||||
{loading ? (
|
||||
<EmailLoader loadingText="Loading thread" />
|
||||
) : (
|
||||
<>
|
||||
<EmailThreadHeader
|
||||
subject={thread.subject}
|
||||
lastMessageSentAt={lastMessage.receivedAt}
|
||||
/>
|
||||
{firstMessages.map((message) => (
|
||||
<EmailThreadMessage
|
||||
key={message.id}
|
||||
|
||||
@ -3,9 +3,15 @@ import { renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
||||
|
||||
import { useRightDrawerEmailThread } from '../useRightDrawerEmailThread';
|
||||
|
||||
jest.mock('@/object-record/hooks/useFindOneRecord', () => ({
|
||||
__esModule: true,
|
||||
useFindOneRecord: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock('@/object-record/hooks/useFindManyRecords', () => ({
|
||||
__esModule: true,
|
||||
useFindManyRecords: jest.fn(),
|
||||
@ -13,11 +19,21 @@ jest.mock('@/object-record/hooks/useFindManyRecords', () => ({
|
||||
|
||||
describe('useRightDrawerEmailThread', () => {
|
||||
it('should return correct values', async () => {
|
||||
const mockThread = { id: '1' };
|
||||
|
||||
const mockMessages = [
|
||||
{ id: '1', text: 'Message 1' },
|
||||
{ id: '2', text: 'Message 2' },
|
||||
];
|
||||
|
||||
const mockFetchMoreRecords = jest.fn();
|
||||
|
||||
(useFindOneRecord as jest.Mock).mockReturnValue({
|
||||
record: mockThread,
|
||||
loading: false,
|
||||
fetchMoreRecords: mockFetchMoreRecords,
|
||||
});
|
||||
|
||||
(useFindManyRecords as jest.Mock).mockReturnValue({
|
||||
records: mockMessages,
|
||||
loading: false,
|
||||
|
||||
@ -1,26 +1,26 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import gql from 'graphql-tag';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { fetchAllThreadMessagesOperationSignatureFactory } from '@/activities/emails/graphql/operation-signatures/factories/fetchAllThreadMessagesOperationSignatureFactory';
|
||||
import { EmailThread } from '@/activities/emails/types/EmailThread';
|
||||
import { EmailThreadMessage as EmailThreadMessageType } from '@/activities/emails/types/EmailThreadMessage';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
||||
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
|
||||
import { useSetRecordInStore } from '@/object-record/record-store/hooks/useSetRecordInStore';
|
||||
|
||||
export const useRightDrawerEmailThread = () => {
|
||||
const viewableRecordId = useRecoilValue(viewableRecordIdState);
|
||||
const { setRecords } = useSetRecordInStore();
|
||||
|
||||
const apolloClient = useApolloClient();
|
||||
const thread = apolloClient.readFragment({
|
||||
id: `TimelineThread:${viewableRecordId}`,
|
||||
fragment: gql`
|
||||
fragment timelineThread on TimelineThread {
|
||||
id
|
||||
subject
|
||||
lastMessageReceivedAt
|
||||
}
|
||||
`,
|
||||
const { record: thread } = useFindOneRecord<EmailThread>({
|
||||
objectNameSingular: CoreObjectNameSingular.MessageThread,
|
||||
objectRecordId: viewableRecordId ?? '',
|
||||
recordGqlFields: {
|
||||
id: true,
|
||||
},
|
||||
onCompleted: (record) => setRecords([record]),
|
||||
});
|
||||
|
||||
const FETCH_ALL_MESSAGES_OPERATION_SIGNATURE =
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
import { EmailThreadMessage } from '@/activities/emails/types/EmailThreadMessage';
|
||||
|
||||
export type EmailThread = {
|
||||
id: string;
|
||||
subject: string;
|
||||
messages: EmailThreadMessage[];
|
||||
__typename: 'EmailThread';
|
||||
};
|
||||
@ -4,6 +4,8 @@ export type EmailThreadMessage = {
|
||||
id: string;
|
||||
text: string;
|
||||
receivedAt: string;
|
||||
subject: string;
|
||||
messageThreadId: string;
|
||||
messageParticipants: EmailThreadMessageParticipant[];
|
||||
__typename: 'EmailThreadMessage';
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user