From 004c23768c9aa1d655b164baa19a244bee0a9c7d Mon Sep 17 00:00:00 2001 From: Thomas Trompette Date: Tue, 23 Jan 2024 10:56:31 +0100 Subject: [PATCH] Build message thread empty right drawer (#3585) * Trigger message thread top bar * Rename message thread to thread * Move all components in a directory --------- Co-authored-by: Thomas Trompette --- .../comment/__stories__/Comment.stories.tsx | 25 +++++++++- .../__stories__/CommentHeader.stories.tsx | 25 +++++++++- .../emails/components/ThreadPreview.tsx | 49 +++++++++++-------- .../components/RightDrawerThread.tsx | 20 ++++++++ .../components/RightDrawerThreadTopBar.tsx | 24 +++++++++ .../RightDrawerThreadTopBar.stories.tsx | 26 ++++++++++ .../hooks/useOpenThreadRightDrawer.ts | 14 ++++++ .../components/ActivityActionBar.tsx | 14 +++--- .../components/RightDrawerActivityTopBar.tsx | 26 ++++++++++ .../RightDrawerActivityTopBar.stories.tsx} | 10 ++-- .../components/RightDrawerRouter.tsx | 14 ++++-- .../components/RightDrawerTopBar.tsx | 44 ----------------- .../components/StyledRightDrawerTopBar.tsx | 17 +++++++ .../right-drawer/types/RightDrawerPages.ts | 1 + 14 files changed, 226 insertions(+), 83 deletions(-) create mode 100644 packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerThread.tsx create mode 100644 packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerThreadTopBar.tsx create mode 100644 packages/twenty-front/src/modules/activities/emails/right-drawer/components/__stories__/RightDrawerThreadTopBar.stories.tsx create mode 100644 packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useOpenThreadRightDrawer.ts create mode 100644 packages/twenty-front/src/modules/activities/right-drawer/components/RightDrawerActivityTopBar.tsx rename packages/twenty-front/src/modules/{ui/layout/right-drawer/components/__stories__/RightDrawerTopBar.stories.tsx => activities/right-drawer/components/__stories__/RightDrawerActivityTopBar.stories.tsx} (59%) delete mode 100644 packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBar.tsx create mode 100644 packages/twenty-front/src/modules/ui/layout/right-drawer/components/StyledRightDrawerTopBar.tsx diff --git a/packages/twenty-front/src/modules/activities/comment/__stories__/Comment.stories.tsx b/packages/twenty-front/src/modules/activities/comment/__stories__/Comment.stories.tsx index fde06a0f0..876d5a251 100644 --- a/packages/twenty-front/src/modules/activities/comment/__stories__/Comment.stories.tsx +++ b/packages/twenty-front/src/modules/activities/comment/__stories__/Comment.stories.tsx @@ -1,5 +1,8 @@ +import { useEffect } from 'react'; import { Meta, StoryObj } from '@storybook/react'; +import { useSetRecoilState } from 'recoil'; +import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState'; import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator'; import { ActivityActionBar } from '../../right-drawer/components/ActivityActionBar'; @@ -7,15 +10,33 @@ import { Comment } from '../Comment'; import { mockComment, mockCommentWithLongValues } from './mock-comment'; +const CommentSetterEffect = () => { + const setViewableActivity = useSetRecoilState(viewableActivityIdState); + + useEffect(() => { + setViewableActivity('test-id'); + }, [setViewableActivity]); + + return null; +}; + const meta: Meta = { title: 'Modules/Activity/Comment/Comment', component: Comment, - decorators: [ComponentDecorator], + decorators: [ + (Story) => ( + <> + + + + ), + ComponentDecorator, + ], argTypes: { actionBar: { type: 'boolean', mapping: { - true: , + true: , false: undefined, }, }, diff --git a/packages/twenty-front/src/modules/activities/comment/__stories__/CommentHeader.stories.tsx b/packages/twenty-front/src/modules/activities/comment/__stories__/CommentHeader.stories.tsx index fee196b1d..e451f57ed 100644 --- a/packages/twenty-front/src/modules/activities/comment/__stories__/CommentHeader.stories.tsx +++ b/packages/twenty-front/src/modules/activities/comment/__stories__/CommentHeader.stories.tsx @@ -1,7 +1,10 @@ +import { useEffect } from 'react'; import { Meta, StoryObj } from '@storybook/react'; import { DateTime } from 'luxon'; +import { useSetRecoilState } from 'recoil'; import { ActivityActionBar } from '@/activities/right-drawer/components/ActivityActionBar'; +import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState'; import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator'; import { avatarUrl } from '~/testing/mock-data/users'; @@ -9,15 +12,33 @@ import { CommentHeader } from '../CommentHeader'; import { mockComment, mockCommentWithLongValues } from './mock-comment'; +const CommentHeaderSetterEffect = () => { + const setViewableActivity = useSetRecoilState(viewableActivityIdState); + + useEffect(() => { + setViewableActivity('test-id'); + }, [setViewableActivity]); + + return null; +}; + const meta: Meta = { title: 'Modules/Activity/Comment/CommentHeader', component: CommentHeader, - decorators: [ComponentDecorator], + decorators: [ + (Story) => ( + <> + + + + ), + ComponentDecorator, + ], argTypes: { actionBar: { type: 'boolean', mapping: { - true: , + true: , false: undefined, }, }, diff --git a/packages/twenty-front/src/modules/activities/emails/components/ThreadPreview.tsx b/packages/twenty-front/src/modules/activities/emails/components/ThreadPreview.tsx index c82396c60..af479fe62 100644 --- a/packages/twenty-front/src/modules/activities/emails/components/ThreadPreview.tsx +++ b/packages/twenty-front/src/modules/activities/emails/components/ThreadPreview.tsx @@ -1,5 +1,6 @@ import styled from '@emotion/styled'; +import { useOpenThreadRightDrawer } from '@/activities/emails/right-drawer/hooks/useOpenThreadRightDrawer'; import { CardContent } from '@/ui/layout/card/components/CardContent'; import { Avatar } from '@/users/components/Avatar'; import { TimelineThread } from '~/generated/graphql'; @@ -11,6 +12,7 @@ const StyledCardContent = styled(CardContent)` gap: ${({ theme }) => theme.spacing(2)}; height: ${({ theme }) => theme.spacing(12)}; padding: ${({ theme }) => theme.spacing(0, 4)}; + cursor: pointer; `; const StyledHeading = styled.div<{ unread: boolean }>` @@ -81,24 +83,31 @@ type ThreadPreviewProps = { thread: TimelineThread; }; -export const ThreadPreview = ({ divider, thread }: ThreadPreviewProps) => ( - - - - {thread.senderName} - {thread.numberOfMessagesInThread} - +export const ThreadPreview = ({ divider, thread }: ThreadPreviewProps) => { + const openMessageThreadRightDrawer = useOpenThreadRightDrawer(); - - {thread.subject} - {thread.body} - - - {formatToHumanReadableDate(thread.receivedAt)} - - -); + return ( + openMessageThreadRightDrawer()} + divider={divider} + > + + + {thread.senderName} + {thread.numberOfMessagesInThread} + + + + {thread.subject} + {thread.body} + + + {formatToHumanReadableDate(thread.receivedAt)} + + + ); +}; diff --git a/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerThread.tsx b/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerThread.tsx new file mode 100644 index 000000000..aa6df0358 --- /dev/null +++ b/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerThread.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import styled from '@emotion/styled'; + +const StyledContainer = styled.div` + box-sizing: border-box; + display: flex; + flex-direction: column; + height: 100%; + justify-content: space-between; + overflow-y: auto; + position: relative; +`; + +export const RightDrawerThread = () => { + return ( + + <> + + ); +}; diff --git a/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerThreadTopBar.tsx b/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerThreadTopBar.tsx new file mode 100644 index 000000000..7bc86eb9c --- /dev/null +++ b/packages/twenty-front/src/modules/activities/emails/right-drawer/components/RightDrawerThreadTopBar.tsx @@ -0,0 +1,24 @@ +import styled from '@emotion/styled'; + +import { StyledRightDrawerTopBar } from '@/ui/layout/right-drawer/components/StyledRightDrawerTopBar'; +import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; + +import { RightDrawerTopBarCloseButton } from '../../../../ui/layout/right-drawer/components/RightDrawerTopBarCloseButton'; +import { RightDrawerTopBarExpandButton } from '../../../../ui/layout/right-drawer/components/RightDrawerTopBarExpandButton'; + +const StyledTopBarWrapper = styled.div` + display: flex; +`; + +export const RightDrawerThreadTopBar = () => { + const isMobile = useIsMobile(); + + return ( + + + + {!isMobile && } + + + ); +}; diff --git a/packages/twenty-front/src/modules/activities/emails/right-drawer/components/__stories__/RightDrawerThreadTopBar.stories.tsx b/packages/twenty-front/src/modules/activities/emails/right-drawer/components/__stories__/RightDrawerThreadTopBar.stories.tsx new file mode 100644 index 000000000..694fc8927 --- /dev/null +++ b/packages/twenty-front/src/modules/activities/emails/right-drawer/components/__stories__/RightDrawerThreadTopBar.stories.tsx @@ -0,0 +1,26 @@ +import { Meta, StoryObj } from '@storybook/react'; + +import { RightDrawerThreadTopBar } from '@/activities/emails/right-drawer/components/RightDrawerThreadTopBar'; +import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator'; +import { graphqlMocks } from '~/testing/graphqlMocks'; + +const meta: Meta = { + title: 'Modules/Activities/Emails/RightDrawer/RightDrawerThreadTopBar', + component: RightDrawerThreadTopBar, + decorators: [ + (Story) => ( +
+ +
+ ), + ComponentDecorator, + ], + parameters: { + msw: graphqlMocks, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; diff --git a/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useOpenThreadRightDrawer.ts b/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useOpenThreadRightDrawer.ts new file mode 100644 index 000000000..f99982f39 --- /dev/null +++ b/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useOpenThreadRightDrawer.ts @@ -0,0 +1,14 @@ +import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; +import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope'; +import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; +import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; + +export const useOpenThreadRightDrawer = () => { + const { openRightDrawer } = useRightDrawer(); + const setHotkeyScope = useSetHotkeyScope(); + + return () => { + setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false }); + openRightDrawer(RightDrawerPages.ViewThread); + }; +}; diff --git a/packages/twenty-front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx b/packages/twenty-front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx index ed1dddd48..dad940eff 100644 --- a/packages/twenty-front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx +++ b/packages/twenty-front/src/modules/activities/right-drawer/components/ActivityActionBar.tsx @@ -1,16 +1,14 @@ -import { useRecoilState } from 'recoil'; +import { useRecoilState, useRecoilValue } from 'recoil'; +import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; import { IconTrash } from '@/ui/display/icon'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState'; -type ActivityActionBarProps = { - activityId: string; -}; - -export const ActivityActionBar = ({ activityId }: ActivityActionBarProps) => { +export const ActivityActionBar = () => { + const viewableActivityId = useRecoilValue(viewableActivityIdState); const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState); const { deleteOneRecord: deleteOneActivity } = useDeleteOneRecord({ objectNameSingular: CoreObjectNameSingular.Activity, @@ -18,7 +16,9 @@ export const ActivityActionBar = ({ activityId }: ActivityActionBarProps) => { }); const deleteActivity = () => { - deleteOneActivity?.(activityId); + if (viewableActivityId) { + deleteOneActivity?.(viewableActivityId); + } setIsRightDrawerOpen(false); }; diff --git a/packages/twenty-front/src/modules/activities/right-drawer/components/RightDrawerActivityTopBar.tsx b/packages/twenty-front/src/modules/activities/right-drawer/components/RightDrawerActivityTopBar.tsx new file mode 100644 index 000000000..628fc3893 --- /dev/null +++ b/packages/twenty-front/src/modules/activities/right-drawer/components/RightDrawerActivityTopBar.tsx @@ -0,0 +1,26 @@ +import styled from '@emotion/styled'; + +import { ActivityActionBar } from '@/activities/right-drawer/components/ActivityActionBar'; +import { StyledRightDrawerTopBar } from '@/ui/layout/right-drawer/components/StyledRightDrawerTopBar'; +import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; + +import { RightDrawerTopBarCloseButton } from '../../../ui/layout/right-drawer/components/RightDrawerTopBarCloseButton'; +import { RightDrawerTopBarExpandButton } from '../../../ui/layout/right-drawer/components/RightDrawerTopBarExpandButton'; + +const StyledTopBarWrapper = styled.div` + display: flex; +`; + +export const RightDrawerActivityTopBar = () => { + const isMobile = useIsMobile(); + + return ( + + + + {!isMobile && } + + + + ); +}; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/__stories__/RightDrawerTopBar.stories.tsx b/packages/twenty-front/src/modules/activities/right-drawer/components/__stories__/RightDrawerActivityTopBar.stories.tsx similarity index 59% rename from packages/twenty-front/src/modules/ui/layout/right-drawer/components/__stories__/RightDrawerTopBar.stories.tsx rename to packages/twenty-front/src/modules/activities/right-drawer/components/__stories__/RightDrawerActivityTopBar.stories.tsx index 2ee20a408..e7afecc95 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/__stories__/RightDrawerTopBar.stories.tsx +++ b/packages/twenty-front/src/modules/activities/right-drawer/components/__stories__/RightDrawerActivityTopBar.stories.tsx @@ -3,11 +3,11 @@ import { Meta, StoryObj } from '@storybook/react'; import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; -import { RightDrawerTopBar } from '../RightDrawerTopBar'; +import { RightDrawerActivityTopBar } from '../RightDrawerActivityTopBar'; -const meta: Meta = { - title: 'UI/Layout/RightDrawer/RightDrawerTopBar', - component: RightDrawerTopBar, +const meta: Meta = { + title: 'Modules/Activities/RightDrawer/RightDrawerActivityTopBar', + component: RightDrawerActivityTopBar, decorators: [ (Story) => (
@@ -22,6 +22,6 @@ const meta: Meta = { }; export default meta; -type Story = StoryObj; +type Story = StoryObj; export const Default: Story = {}; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerRouter.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerRouter.tsx index c95d634e4..610471ade 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerRouter.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerRouter.tsx @@ -1,14 +1,15 @@ import styled from '@emotion/styled'; import { useRecoilState } from 'recoil'; +import { RightDrawerThread } from '@/activities/emails/right-drawer/components/RightDrawerThread'; +import { RightDrawerThreadTopBar } from '@/activities/emails/right-drawer/components/RightDrawerThreadTopBar'; import { RightDrawerCreateActivity } from '@/activities/right-drawer/components/create/RightDrawerCreateActivity'; import { RightDrawerEditActivity } from '@/activities/right-drawer/components/edit/RightDrawerEditActivity'; +import { RightDrawerActivityTopBar } from '../../../../activities/right-drawer/components/RightDrawerActivityTopBar'; import { rightDrawerPageState } from '../states/rightDrawerPageState'; import { RightDrawerPages } from '../types/RightDrawerPages'; -import { RightDrawerTopBar } from './RightDrawerTopBar'; - const StyledRightDrawerPage = styled.div` display: flex; flex-direction: column; @@ -30,13 +31,20 @@ export const RightDrawerRouter = () => { const [rightDrawerPage] = useRecoilState(rightDrawerPageState); let page = <>; + let topBar = <>; switch (rightDrawerPage) { case RightDrawerPages.CreateActivity: page = ; + topBar = ; break; case RightDrawerPages.EditActivity: page = ; + topBar = ; + break; + case RightDrawerPages.ViewThread: + page = ; + topBar = ; break; default: break; @@ -44,7 +52,7 @@ export const RightDrawerRouter = () => { return ( - + {topBar} {page} ); diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBar.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBar.tsx deleted file mode 100644 index cd4c7a7bc..000000000 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBar.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import styled from '@emotion/styled'; -import { useRecoilValue } from 'recoil'; - -import { ActivityActionBar } from '@/activities/right-drawer/components/ActivityActionBar'; -import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState'; -import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; - -import { RightDrawerTopBarCloseButton } from './RightDrawerTopBarCloseButton'; -import { RightDrawerTopBarExpandButton } from './RightDrawerTopBarExpandButton'; - -const StyledRightDrawerTopBar = styled.div` - align-items: center; - background: ${({ theme }) => theme.background.secondary}; - border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; - color: ${({ theme }) => theme.font.color.secondary}; - display: flex; - flex-direction: row; - font-size: ${({ theme }) => theme.font.size.md}; - gap: ${({ theme }) => theme.spacing(1)}; - height: 56px; - justify-content: space-between; - padding-left: ${({ theme }) => theme.spacing(2)}; - - padding-right: ${({ theme }) => theme.spacing(2)}; -`; - -const StyledTopBarWrapper = styled.div` - display: flex; -`; - -export const RightDrawerTopBar = () => { - const isMobile = useIsMobile(); - const viewableActivityId = useRecoilValue(viewableActivityIdState); - - return ( - - - - {!isMobile && } - - - - ); -}; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/StyledRightDrawerTopBar.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/StyledRightDrawerTopBar.tsx new file mode 100644 index 000000000..fe3cae76e --- /dev/null +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/StyledRightDrawerTopBar.tsx @@ -0,0 +1,17 @@ +import styled from '@emotion/styled'; + +export const StyledRightDrawerTopBar = styled.div` + align-items: center; + background: ${({ theme }) => theme.background.secondary}; + border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; + color: ${({ theme }) => theme.font.color.secondary}; + display: flex; + flex-direction: row; + font-size: ${({ theme }) => theme.font.size.md}; + gap: ${({ theme }) => theme.spacing(1)}; + height: 56px; + justify-content: space-between; + padding-left: ${({ theme }) => theme.spacing(2)}; + + padding-right: ${({ theme }) => theme.spacing(2)}; +`; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/types/RightDrawerPages.ts b/packages/twenty-front/src/modules/ui/layout/right-drawer/types/RightDrawerPages.ts index e928bd7fa..4fdb5f921 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/types/RightDrawerPages.ts +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/types/RightDrawerPages.ts @@ -1,4 +1,5 @@ export enum RightDrawerPages { CreateActivity = 'create-activity', EditActivity = 'edit-activity', + ViewThread = 'view-thread', }