From 12cc126867804cefc8da4c9267723a1c0bb56324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Thu, 23 May 2024 16:38:47 +0200 Subject: [PATCH 01/30] Basic edit in right drawer implem --- .../activities/components/ActivityEditor.tsx | 2 - .../emails/components/EmailThreadHeader.tsx | 2 - .../components/RightDrawerActivityTopBar.tsx | 29 ------ .../components/RightDrawerRecord.tsx | 29 ++++++ .../states/viewableRecordIdState.ts | 6 ++ .../states/viewableRecordNameSingularState.ts | 6 ++ .../components/RecordShowContainer.tsx | 16 ++-- .../components/RecordTableRow.tsx | 1 + .../contexts/RecordTableRowContext.ts | 1 + .../record-table-cell/hooks/__mocks__/cell.ts | 1 + .../hooks/useOpenRecordTableCellFromCell.ts | 5 +- .../hooks/useOpenRecordTableCellV2.ts | 20 +++- .../src/modules/ui/layout/page/PageBody.tsx | 51 +++++++++- .../ui/layout/page/RightDrawerContainer.tsx | 52 ---------- .../ui/layout/page/SubMenuTopBarContainer.tsx | 4 +- .../right-drawer/components/RightDrawer.tsx | 24 ++++- .../components/RightDrawerGenericTopBar.tsx | 95 +++++++++++++++++++ .../components/RightDrawerRouter.tsx | 28 ++++-- .../RightDrawerTopBarCloseButton.tsx | 4 +- .../RightDrawerTopBarExpandButton.tsx | 11 +-- .../RightDrawerTopBarMinimizeButton.tsx | 22 +++++ .../components/StyledRightDrawerTopBar.tsx | 6 +- .../constants/RightDrawerPageIcons.ts | 8 ++ .../constants/RightDrawerPageTitles.ts | 9 ++ .../right-drawer/hooks/useRightDrawer.ts | 51 ++++++++++ .../states/isRightDrawerMinimizedState.ts | 6 ++ .../right-drawer/types/RightDrawerPages.ts | 1 + .../components/ShowPageLeftContainer.tsx | 24 +++-- .../pages/object-record/RecordShowPage.tsx | 1 + 29 files changed, 389 insertions(+), 126 deletions(-) delete mode 100644 packages/twenty-front/src/modules/activities/right-drawer/components/RightDrawerActivityTopBar.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx create mode 100644 packages/twenty-front/src/modules/object-record/record-right-drawer/states/viewableRecordIdState.ts create mode 100644 packages/twenty-front/src/modules/object-record/record-right-drawer/states/viewableRecordNameSingularState.ts delete mode 100644 packages/twenty-front/src/modules/ui/layout/page/RightDrawerContainer.tsx create mode 100644 packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerGenericTopBar.tsx create mode 100644 packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarMinimizeButton.tsx create mode 100644 packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageIcons.ts create mode 100644 packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageTitles.ts create mode 100644 packages/twenty-front/src/modules/ui/layout/right-drawer/states/isRightDrawerMinimizedState.ts diff --git a/packages/twenty-front/src/modules/activities/components/ActivityEditor.tsx b/packages/twenty-front/src/modules/activities/components/ActivityEditor.tsx index b560a76f3d8e..e06b79c9c548 100644 --- a/packages/twenty-front/src/modules/activities/components/ActivityEditor.tsx +++ b/packages/twenty-front/src/modules/activities/components/ActivityEditor.tsx @@ -7,7 +7,6 @@ import { ActivityComments } from '@/activities/components/ActivityComments'; import { ActivityCreationDate } from '@/activities/components/ActivityCreationDate'; import { ActivityEditorFields } from '@/activities/components/ActivityEditorFields'; import { ActivityTitleEffect } from '@/activities/components/ActivityTitleEffect'; -import { ActivityTypeDropdown } from '@/activities/components/ActivityTypeDropdown'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { ActivityTitle } from './ActivityTitle'; @@ -68,7 +67,6 @@ export const ActivityEditor = ({ - diff --git a/packages/twenty-front/src/modules/activities/emails/components/EmailThreadHeader.tsx b/packages/twenty-front/src/modules/activities/emails/components/EmailThreadHeader.tsx index 7063110ac052..29cd280ed0e7 100644 --- a/packages/twenty-front/src/modules/activities/emails/components/EmailThreadHeader.tsx +++ b/packages/twenty-front/src/modules/activities/emails/components/EmailThreadHeader.tsx @@ -1,5 +1,4 @@ import styled from '@emotion/styled'; -import { IconMail, Tag } from 'twenty-ui'; import { beautifyPastDateRelativeToNow } from '~/utils/date-utils'; @@ -43,7 +42,6 @@ export const EmailThreadHeader = ({ }: EmailThreadHeaderProps) => { return ( - {}} /> {subject} 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 deleted file mode 100644 index 2e3c35fe4cf2..000000000000 --- a/packages/twenty-front/src/modules/activities/right-drawer/components/RightDrawerActivityTopBar.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import styled from '@emotion/styled'; - -import { ActivityActionBar } from '@/activities/right-drawer/components/ActivityActionBar'; -import { RightDrawerTopBarCloseButton } from '@/ui/layout/right-drawer/components/RightDrawerTopBarCloseButton'; -import { RightDrawerTopBarExpandButton } from '@/ui/layout/right-drawer/components/RightDrawerTopBarExpandButton'; -import { StyledRightDrawerTopBar } from '@/ui/layout/right-drawer/components/StyledRightDrawerTopBar'; -import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; - -type RightDrawerActivityTopBarProps = { showActionBar?: boolean }; - -const StyledTopBarWrapper = styled.div` - display: flex; -`; - -export const RightDrawerActivityTopBar = ({ - showActionBar = true, -}: RightDrawerActivityTopBarProps) => { - const isMobile = useIsMobile(); - - return ( - - - - {!isMobile && } - - {showActionBar && } - - ); -}; diff --git a/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx b/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx new file mode 100644 index 000000000000..6a5f2badf41f --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx @@ -0,0 +1,29 @@ +import { useRecoilValue } from 'recoil'; + +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; +import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState'; +import { RecordShowContainer } from '@/object-record/record-show/components/RecordShowContainer'; + +export const RightDrawerRecord = () => { + const viewableRecordNameSingular = useRecoilValue( + viewableRecordNameSingularState, + ); + const viewableRecordId = useRecoilValue(viewableRecordIdState); + + if (!viewableRecordNameSingular) { + throw new Error(`Object name is not defined`); + } + + if (!viewableRecordId) { + throw new Error(`Record id is not defined`); + } + + return ( + + ); +}; diff --git a/packages/twenty-front/src/modules/object-record/record-right-drawer/states/viewableRecordIdState.ts b/packages/twenty-front/src/modules/object-record/record-right-drawer/states/viewableRecordIdState.ts new file mode 100644 index 000000000000..c75e6cf8a8a5 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-right-drawer/states/viewableRecordIdState.ts @@ -0,0 +1,6 @@ +import { createState } from 'twenty-ui'; + +export const viewableRecordIdState = createState({ + key: 'activities/viewable-record-id', + defaultValue: null, +}); diff --git a/packages/twenty-front/src/modules/object-record/record-right-drawer/states/viewableRecordNameSingularState.ts b/packages/twenty-front/src/modules/object-record/record-right-drawer/states/viewableRecordNameSingularState.ts new file mode 100644 index 000000000000..3116430e10c3 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-right-drawer/states/viewableRecordNameSingularState.ts @@ -0,0 +1,6 @@ +import { createState } from 'twenty-ui'; + +export const viewableRecordNameSingularState = createState({ + key: 'activities/viewable-record-name-singular', + defaultValue: null, +}); diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx index d3dd52fc3722..78afbbf8273b 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx @@ -37,12 +37,14 @@ type RecordShowContainerProps = { objectNameSingular: string; objectRecordId: string; loading: boolean; + isInRightDrawer?: boolean; }; export const RecordShowContainer = ({ objectNameSingular, objectRecordId, loading, + isInRightDrawer = false, }: RecordShowContainerProps) => { const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular, @@ -131,7 +133,7 @@ export const RecordShowContainer = ({ return ( - + {isDefined(recordFromStore) && ( <> ))} - + {!isInRightDrawer && ( + + )} {relationFieldMetadataItems?.map((fieldMetadataItem, index) => ( )} - {recordFromStore ? ( + {recordFromStore && !isInRightDrawer ? ( { getBasePathToShowPage({ objectNameSingular: objectMetadataItem.nameSingular, }) + recordId, + objectNameSingular: objectMetadataItem.nameSingular, isSelected: currentRowSelected, isReadOnly: objectMetadataItem.isRemote ?? false, }} diff --git a/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableRowContext.ts b/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableRowContext.ts index 4322e26f786f..2cd9f71f333a 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableRowContext.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/contexts/RecordTableRowContext.ts @@ -2,6 +2,7 @@ import { createContext } from 'react'; export type RecordTableRowContextProps = { pathToShowPage: string; + objectNameSingular: string; recordId: string; rowIndex: number; isSelected: boolean; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__mocks__/cell.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__mocks__/cell.ts index e4d84e248a60..792b33adc009 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__mocks__/cell.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/__mocks__/cell.ts @@ -8,6 +8,7 @@ export const recordTableRow: RecordTableRowContextProps = { isSelected: false, recordId: 'recordId', pathToShowPage: '/', + objectNameSingular: 'objectNameSingular', isReadOnly: false, }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell.ts index cf7846adfc2c..f431d142ca9e 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell.ts @@ -31,7 +31,9 @@ export const useOpenRecordTableCellFromCell = () => { const cellPosition = useCurrentTableCellPosition(); const customCellHotkeyScope = useContext(CellHotkeyScopeContext); const { entityId, fieldDefinition } = useContext(FieldContext); - const { isReadOnly, pathToShowPage } = useContext(RecordTableRowContext); + const { isReadOnly, pathToShowPage, objectNameSingular } = useContext( + RecordTableRowContext, + ); const openTableCell = (initialValue?: string) => { onOpenTableCell({ @@ -41,6 +43,7 @@ export const useOpenRecordTableCellFromCell = () => { fieldDefinition, isReadOnly, pathToShowPage, + objectNameSingular, initialValue, }); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts index e9508f5365d2..d3bd90b81dd8 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts @@ -1,15 +1,19 @@ import { useNavigate } from 'react-router-dom'; -import { useRecoilCallback } from 'recoil'; +import { useRecoilCallback, useSetRecoilState } from 'recoil'; import { useInitDraftValueV2 } from '@/object-record/record-field/hooks/useInitDraftValueV2'; import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition'; import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { isFieldValueEmpty } from '@/object-record/record-field/utils/isFieldValueEmpty'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; +import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState'; import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; import { SOFT_FOCUS_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/SoftFocusClickOutsideListenerId'; import { useLeaveTableFocus } from '@/object-record/record-table/hooks/internal/useLeaveTableFocus'; import { useMoveEditModeToTableCellPosition } from '@/object-record/record-table/hooks/internal/useMoveEditModeToCellPosition'; import { TableCellPosition } from '@/object-record/record-table/types/TableCellPosition'; +import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; +import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; import { useDragSelect } from '@/ui/utilities/drag-select/hooks/useDragSelect'; import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; @@ -28,6 +32,7 @@ export type OpenTableCellArgs = { cellPosition: TableCellPosition; isReadOnly: boolean; pathToShowPage: string; + objectNameSingular: string; customCellHotkeyScope: HotkeyScope | null; fieldDefinition: FieldDefinition; entityId: string; @@ -48,6 +53,12 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => { const initDraftValue = useInitDraftValueV2(); + const { openRightDrawer } = useRightDrawer(); + const setViewableRecordId = useSetRecoilState(viewableRecordIdState); + const setViewableRecordNameSingular = useSetRecoilState( + viewableRecordNameSingularState, + ); + const openTableCell = useRecoilCallback( ({ snapshot }) => ({ @@ -55,6 +66,7 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => { cellPosition, isReadOnly, pathToShowPage, + objectNameSingular, customCellHotkeyScope, fieldDefinition, entityId, @@ -80,7 +92,11 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => { if (isFirstColumnCell && !isEmpty) { leaveTableFocus(); - navigate(pathToShowPage); + // navigate(pathToShowPage); + setViewableRecordId(entityId); + setViewableRecordNameSingular(objectNameSingular); + openRightDrawer(RightDrawerPages.ViewRecord); + return; } diff --git a/packages/twenty-front/src/modules/ui/layout/page/PageBody.tsx b/packages/twenty-front/src/modules/ui/layout/page/PageBody.tsx index 4e1269b3e1c2..eee7353684fc 100644 --- a/packages/twenty-front/src/modules/ui/layout/page/PageBody.tsx +++ b/packages/twenty-front/src/modules/ui/layout/page/PageBody.tsx @@ -1 +1,50 @@ -export { RightDrawerContainer as PageBody } from './RightDrawerContainer'; +import { ReactNode } from 'react'; +import styled from '@emotion/styled'; + +import { RightDrawer } from '@/ui/layout/right-drawer/components/RightDrawer'; +import { MOBILE_VIEWPORT } from '@/ui/theme/constants/MobileViewport'; + +import { PagePanel } from './PagePanel'; + +type PageBodyProps = { + children: ReactNode; +}; + +const StyledMainContainer = styled.div` + background: ${({ theme }) => theme.background.noisy}; + box-sizing: border-box; + display: flex; + flex: 1 1 auto; + flex-direction: row; + gap: ${({ theme }) => theme.spacing(2)}; + min-height: 0; + padding-bottom: ${({ theme }) => theme.spacing(3)}; + padding-right: ${({ theme }) => theme.spacing(3)}; + padding-left: 0; + width: 100%; + + @media (max-width: ${MOBILE_VIEWPORT}px) { + padding-left: ${({ theme }) => theme.spacing(3)}; + padding-bottom: 0; + } +`; + +type LeftContainerProps = { + isRightDrawerOpen?: boolean; +}; + +const StyledLeftContainer = styled.div` + display: flex; + flex-direction: column; + position: relative; + width: 100%; +`; + +export const PageBody = ({ children }: PageBodyProps) => ( + + + {children} + + + +); diff --git a/packages/twenty-front/src/modules/ui/layout/page/RightDrawerContainer.tsx b/packages/twenty-front/src/modules/ui/layout/page/RightDrawerContainer.tsx deleted file mode 100644 index 5ee7cae4526e..000000000000 --- a/packages/twenty-front/src/modules/ui/layout/page/RightDrawerContainer.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import { ReactNode } from 'react'; -import styled from '@emotion/styled'; - -import { RightDrawer } from '@/ui/layout/right-drawer/components/RightDrawer'; -import { MOBILE_VIEWPORT } from '@/ui/theme/constants/MobileViewport'; - -import { PagePanel } from './PagePanel'; - -type RightDrawerContainerProps = { - children: ReactNode; -}; - -const StyledMainContainer = styled.div` - background: ${({ theme }) => theme.background.noisy}; - box-sizing: border-box; - display: flex; - flex: 1 1 auto; - flex-direction: row; - gap: ${({ theme }) => theme.spacing(2)}; - min-height: 0; - padding-bottom: ${({ theme }) => theme.spacing(3)}; - padding-right: ${({ theme }) => theme.spacing(3)}; - padding-left: 0; - width: 100%; - - @media (max-width: ${MOBILE_VIEWPORT}px) { - padding-left: ${({ theme }) => theme.spacing(3)}; - padding-bottom: 0; - } -`; - -type LeftContainerProps = { - isRightDrawerOpen?: boolean; -}; - -const StyledLeftContainer = styled.div` - display: flex; - flex-direction: column; - position: relative; - width: 100%; -`; - -export const RightDrawerContainer = ({ - children, -}: RightDrawerContainerProps) => ( - - - {children} - - - -); diff --git a/packages/twenty-front/src/modules/ui/layout/page/SubMenuTopBarContainer.tsx b/packages/twenty-front/src/modules/ui/layout/page/SubMenuTopBarContainer.tsx index 7114005329c1..becc29aae6f9 100644 --- a/packages/twenty-front/src/modules/ui/layout/page/SubMenuTopBarContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/page/SubMenuTopBarContainer.tsx @@ -4,8 +4,8 @@ import { IconComponent } from 'twenty-ui'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; +import { PageBody } from './PageBody'; import { PageHeader } from './PageHeader'; -import { RightDrawerContainer } from './RightDrawerContainer'; type SubMenuTopBarContainerProps = { children: JSX.Element | JSX.Element[]; @@ -32,7 +32,7 @@ export const SubMenuTopBarContainer = ({ return ( {isMobile && } - {children} + {children} ); }; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx index 907d16dda6bd..9165908c49ee 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx @@ -7,6 +7,7 @@ import { Key } from 'ts-key-enum'; import { RIGHT_DRAWER_CLICK_OUTSIDE_LISTENER_ID } from '@/ui/layout/right-drawer/constants/RightDrawerClickOutsideListener'; import { isRightDrawerAnimationCompletedState } from '@/ui/layout/right-drawer/states/isRightDrawerAnimationCompleted'; +import { isRightDrawerMinimizedState } from '@/ui/layout/right-drawer/states/isRightDrawerMinimizedState'; import { rightDrawerCloseEventState } from '@/ui/layout/right-drawer/states/rightDrawerCloseEventsState'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useClickOutsideListener } from '@/ui/utilities/pointer-event/hooks/useClickOutsideListener'; @@ -46,6 +47,8 @@ export const RightDrawer = () => { isRightDrawerOpenState, ); + const isRightDrawerMinimized = useRecoilValue(isRightDrawerMinimizedState); + const isRightDrawerExpanded = useRecoilValue(isRightDrawerExpandedState); const [, setIsRightDrawerAnimationCompleted] = useRecoilState( isRightDrawerAnimationCompletedState, @@ -53,7 +56,7 @@ export const RightDrawer = () => { const rightDrawerPage = useRecoilValue(rightDrawerPageState); - const { closeRightDrawer } = useRightDrawer(); + const { closeRightDrawer, minimizeRightDrawer } = useRightDrawer(); const rightDrawerRef = useRef(null); @@ -72,10 +75,10 @@ export const RightDrawer = () => { if (isRightDrawerOpen) { set(rightDrawerCloseEventState, event); - closeRightDrawer(); + minimizeRightDrawer(); } }, - [closeRightDrawer], + [minimizeRightDrawer], ), mode: ClickOutsideMode.comparePixels, }); @@ -115,6 +118,13 @@ export const RightDrawer = () => { closed: { x: '100%', }, + minimized: { + x: '0%', + width: 'auto', + height: 'auto', + bottom: '0', + top: 'auto', + }, }; const handleAnimationComplete = () => { setIsRightDrawerAnimationCompleted(isRightDrawerOpen); @@ -123,7 +133,13 @@ export const RightDrawer = () => { return ( theme.spacing(1)}; + height: 24px; + width: 168px; +`; + +const StyledMinimizeTopBarTitle = styled.div` + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +`; + +const StyledMinimizeTopBarIcon = styled.div` + align-items: center; + display: flex; +`; + +export const RightDrawerGenericTopBar = ({ + page, +}: { + page: RightDrawerPages; +}) => { + const isMobile = useIsMobile(); + + const [isRightDrawerMinimized, setIsRightDrawerMinimized] = useRecoilState( + isRightDrawerMinimizedState, + ); + + const theme = useTheme(); + + const handleOnclick = () => { + if (isRightDrawerMinimized) { + setIsRightDrawerMinimized(false); + } + }; + + const { getIcon } = useIcons(); + + const PageIcon = getIcon(RIGHT_DRAWER_PAGE_ICONS[page]); + + return ( + + {!isRightDrawerMinimized && ( + } + size={ChipSize.Large} + accent={ChipAccent.TextSecondary} + variant={ChipVariant.Highlighted} + /> + )} + {isRightDrawerMinimized && ( + + + + + + {RIGHT_DRAWER_PAGE_TITLES[page]} + + + )} + + {!isRightDrawerMinimized && } + {!isMobile && !isRightDrawerMinimized && ( + + )} + + + + ); +}; 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 77daadb0eb4c..68e8482bbd87 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,12 +1,14 @@ import styled from '@emotion/styled'; -import { useRecoilState } from 'recoil'; +import { useRecoilState, useRecoilValue } from 'recoil'; import { RightDrawerCalendarEvent } from '@/activities/calendar/right-drawer/components/RightDrawerCalendarEvent'; import { RightDrawerEmailThread } from '@/activities/emails/right-drawer/components/RightDrawerEmailThread'; import { RightDrawerCreateActivity } from '@/activities/right-drawer/components/create/RightDrawerCreateActivity'; import { RightDrawerEditActivity } from '@/activities/right-drawer/components/edit/RightDrawerEditActivity'; +import { RightDrawerRecord } from '@/object-record/record-right-drawer/components/RightDrawerRecord'; +import { RightDrawerGenericTopBar } from '@/ui/layout/right-drawer/components/RightDrawerGenericTopBar'; +import { isRightDrawerMinimizedState } from '@/ui/layout/right-drawer/states/isRightDrawerMinimizedState'; -import { RightDrawerActivityTopBar } from '../../../../activities/right-drawer/components/RightDrawerActivityTopBar'; import { rightDrawerPageState } from '../states/rightDrawerPageState'; import { RightDrawerPages } from '../types/RightDrawerPages'; @@ -30,19 +32,27 @@ const StyledRightDrawerBody = styled.div` const RIGHT_DRAWER_PAGES_CONFIG = { [RightDrawerPages.CreateActivity]: { page: , - topBar: , + topBar: , }, [RightDrawerPages.EditActivity]: { page: , - topBar: , + topBar: , }, [RightDrawerPages.ViewEmailThread]: { page: , - topBar: , + topBar: ( + + ), }, [RightDrawerPages.ViewCalendarEvent]: { page: , - topBar: , + topBar: ( + + ), + }, + [RightDrawerPages.ViewRecord]: { + page: , + topBar: , }, }; @@ -53,10 +63,14 @@ export const RightDrawerRouter = () => { ? RIGHT_DRAWER_PAGES_CONFIG[rightDrawerPage] : {}; + const isRightDrawerMinimized = useRecoilValue(isRightDrawerMinimizedState); + return ( {topBar} - {page} + {!isRightDrawerMinimized && ( + {page} + )} ); }; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarCloseButton.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarCloseButton.tsx index b7e0f0102ee2..9a225f4571d0 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarCloseButton.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarCloseButton.tsx @@ -1,4 +1,4 @@ -import { IconChevronsRight } from 'twenty-ui'; +import { IconX } from 'twenty-ui'; import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; @@ -13,7 +13,7 @@ export const RightDrawerTopBarCloseButton = () => { return ( { - const [isRightDrawerExpanded, setIsRightDrawerExpanded] = useRecoilState( - isRightDrawerExpandedState, - ); + const { isRightDrawerExpanded, downsizeRightDrawer, expandRightDrawer } = + useRightDrawer(); const handleButtonClick = () => { - setIsRightDrawerExpanded(!isRightDrawerExpanded); + isRightDrawerExpanded ? downsizeRightDrawer() : expandRightDrawer(); }; return ( diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarMinimizeButton.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarMinimizeButton.tsx new file mode 100644 index 000000000000..b95be3578766 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarMinimizeButton.tsx @@ -0,0 +1,22 @@ +import { IconMinus } from 'twenty-ui'; + +import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; +import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; + +export const RightDrawerTopBarMinimizeButton = () => { + const { isRightDrawerMinimized, minimizeRightDrawer, maximizeRightDrawer } = + useRightDrawer(); + + const handleButtonClick = () => { + isRightDrawerMinimized ? maximizeRightDrawer() : minimizeRightDrawer(); + }; + + return ( + + ); +}; 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 index fe3cae76e3da..42ea38969b67 100644 --- 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 @@ -1,6 +1,8 @@ import styled from '@emotion/styled'; -export const StyledRightDrawerTopBar = styled.div` +export const StyledRightDrawerTopBar = styled.div<{ + isRightDrawerMinimized: boolean; +}>` align-items: center; background: ${({ theme }) => theme.background.secondary}; border-bottom: 1px solid ${({ theme }) => theme.border.color.light}; @@ -14,4 +16,6 @@ export const StyledRightDrawerTopBar = styled.div` padding-left: ${({ theme }) => theme.spacing(2)}; padding-right: ${({ theme }) => theme.spacing(2)}; + cursor: ${({ isRightDrawerMinimized }) => + isRightDrawerMinimized ? 'pointer' : 'default'}; `; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageIcons.ts b/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageIcons.ts new file mode 100644 index 000000000000..e41bc2fa591e --- /dev/null +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageIcons.ts @@ -0,0 +1,8 @@ +import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; + +export const RIGHT_DRAWER_PAGE_ICONS = { + [RightDrawerPages.CreateActivity]: 'IconNote', + [RightDrawerPages.EditActivity]: 'IconNote', + [RightDrawerPages.ViewEmailThread]: 'IconMail', + [RightDrawerPages.ViewCalendarEvent]: 'IconCalendarEvent', +}; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageTitles.ts b/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageTitles.ts new file mode 100644 index 000000000000..6edb8fec2116 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageTitles.ts @@ -0,0 +1,9 @@ +import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; + +export const RIGHT_DRAWER_PAGE_TITLES = { + [RightDrawerPages.CreateActivity]: 'Create Activity', + [RightDrawerPages.EditActivity]: 'Edit Activity', + [RightDrawerPages.ViewEmailThread]: 'Email Thread', + [RightDrawerPages.ViewCalendarEvent]: 'Calendar Event', + [RightDrawerPages.ViewRecord]: 'Record Editor', +}; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/hooks/useRightDrawer.ts b/packages/twenty-front/src/modules/ui/layout/right-drawer/hooks/useRightDrawer.ts index 5cf5cc621456..09dc989a0cdf 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/hooks/useRightDrawer.ts +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/hooks/useRightDrawer.ts @@ -1,5 +1,6 @@ import { useRecoilCallback, useRecoilState } from 'recoil'; +import { isRightDrawerMinimizedState } from '@/ui/layout/right-drawer/states/isRightDrawerMinimizedState'; import { rightDrawerCloseEventState } from '@/ui/layout/right-drawer/states/rightDrawerCloseEventsState'; import { isRightDrawerExpandedState } from '../states/isRightDrawerExpandedState'; @@ -9,6 +10,8 @@ import { RightDrawerPages } from '../types/RightDrawerPages'; export const useRightDrawer = () => { const [isRightDrawerOpen] = useRecoilState(isRightDrawerOpenState); + const [isRightDrawerExpanded] = useRecoilState(isRightDrawerExpandedState); + const [isRightDrawerMinimized] = useRecoilState(isRightDrawerMinimizedState); const [rightDrawerPage] = useRecoilState(rightDrawerPageState); @@ -18,6 +21,7 @@ export const useRightDrawer = () => { set(rightDrawerPageState, rightDrawerPage); set(isRightDrawerExpandedState, false); set(isRightDrawerOpenState, true); + set(isRightDrawerMinimizedState, false); }, [], ); @@ -27,6 +31,47 @@ export const useRightDrawer = () => { () => { set(isRightDrawerExpandedState, false); set(isRightDrawerOpenState, false); + set(isRightDrawerMinimizedState, false); + }, + [], + ); + + const minimizeRightDrawer = useRecoilCallback( + ({ set }) => + () => { + set(isRightDrawerExpandedState, false); + set(isRightDrawerOpenState, true); + set(isRightDrawerMinimizedState, true); + }, + [], + ); + + const maximizeRightDrawer = useRecoilCallback( + ({ set }) => + () => { + set(isRightDrawerExpandedState, false); + set(isRightDrawerOpenState, true); + set(isRightDrawerMinimizedState, false); + }, + [], + ); + + const expandRightDrawer = useRecoilCallback( + ({ set }) => + () => { + set(isRightDrawerExpandedState, true); + set(isRightDrawerOpenState, true); + set(isRightDrawerMinimizedState, false); + }, + [], + ); + + const downsizeRightDrawer = useRecoilCallback( + ({ set }) => + () => { + set(isRightDrawerExpandedState, false); + set(isRightDrawerOpenState, true); + set(isRightDrawerMinimizedState, false); }, [], ); @@ -50,8 +95,14 @@ export const useRightDrawer = () => { return { rightDrawerPage, isRightDrawerOpen, + isRightDrawerExpanded, + isRightDrawerMinimized, openRightDrawer, closeRightDrawer, + minimizeRightDrawer, + maximizeRightDrawer, + expandRightDrawer, + downsizeRightDrawer, isSameEventThanRightDrawerClose, }; }; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/states/isRightDrawerMinimizedState.ts b/packages/twenty-front/src/modules/ui/layout/right-drawer/states/isRightDrawerMinimizedState.ts new file mode 100644 index 000000000000..9b2124030610 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/states/isRightDrawerMinimizedState.ts @@ -0,0 +1,6 @@ +import { createState } from 'twenty-ui'; + +export const isRightDrawerMinimizedState = createState({ + key: 'ui/layout/is-right-drawer-minimized', + defaultValue: false, +}); 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 df0cd28ca53c..487b1a16f841 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 @@ -3,4 +3,5 @@ export enum RightDrawerPages { EditActivity = 'edit-activity', ViewEmailThread = 'view-email-thread', ViewCalendarEvent = 'view-calendar-event', + ViewRecord = 'view-record', } diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx index fa5d5c1e82c8..accc499cc53c 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx @@ -4,7 +4,7 @@ import styled from '@emotion/styled'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; -const StyledOuterContainer = styled.div` +const StyledOuterContainer = styled.div<{ isInRightDrawer: boolean }>` background: ${({ theme }) => theme.background.secondary}; border-bottom-left-radius: 8px; border-right: ${({ theme }) => @@ -14,12 +14,14 @@ const StyledOuterContainer = styled.div` flex-direction: column; gap: ${({ theme }) => theme.spacing(3)}; z-index: 10; + width: ${({ isInRightDrawer }) => (isInRightDrawer ? `100%` : 'auto')}; `; -const StyledInnerContainer = styled.div` +const StyledInnerContainer = styled.div<{ isInRightDrawer: boolean }>` display: flex; flex-direction: column; - width: ${() => (useIsMobile() ? `100%` : '348px')}; + width: ${({ isInRightDrawer }) => + useIsMobile() || isInRightDrawer ? `100%` : '348px'}; `; const StyledIntermediateContainer = styled.div` @@ -29,22 +31,28 @@ const StyledIntermediateContainer = styled.div` `; export type ShowPageLeftContainerProps = { + isInRightDrawer: boolean; children: ReactNode; }; export const ShowPageLeftContainer = ({ + isInRightDrawer = false, children, }: ShowPageLeftContainerProps) => { const isMobile = useIsMobile(); - return isMobile ? ( - - {children} + return isMobile || isInRightDrawer ? ( + + + {children} + ) : ( - + - {children} + + {children} + diff --git a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx index 64887c0cbcaa..b63f83ac4c66 100644 --- a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx @@ -134,6 +134,7 @@ export const RecordShowPage = () => { objectNameSingular={objectNameSingular} objectRecordId={objectRecordId} loading={loading} + isInRightDrawer={false} /> From bcd26adac6fd2f400bbe56c5aee36f537c87f4b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Thu, 23 May 2024 17:31:48 +0200 Subject: [PATCH 02/30] Remove viewableActivityIdState --- .../comment/__stories__/Comment.stories.tsx | 4 ++-- .../__stories__/CommentHeader.stories.tsx | 4 ++-- .../useOpenActivityRightDrawer.test.tsx | 13 +++++++---- .../useOpenCreateActivityDrawer.test.tsx | 10 ++++---- .../hooks/useOpenActivityRightDrawer.ts | 11 ++++----- .../hooks/useOpenCreateActivityDrawer.ts | 4 ++-- .../components/ActivityActionBar.tsx | 14 +++++------ .../create/RightDrawerCreateActivity.tsx | 8 +++---- .../edit/RightDrawerEditActivity.tsx | 8 +++---- .../states/viewableActivityIdState.ts | 6 ----- .../pages/object-record/RecordIndexPage.tsx | 23 ++++++++++++++++++- 11 files changed, 60 insertions(+), 45 deletions(-) delete mode 100644 packages/twenty-front/src/modules/activities/states/viewableActivityIdState.ts 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 a75afeb82cee..15677354ba6e 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 @@ -3,7 +3,7 @@ import { Meta, StoryObj } from '@storybook/react'; import { useSetRecoilState } from 'recoil'; import { ComponentDecorator } from 'twenty-ui'; -import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { ActivityActionBar } from '../../right-drawer/components/ActivityActionBar'; import { Comment } from '../Comment'; @@ -11,7 +11,7 @@ import { Comment } from '../Comment'; import { mockComment, mockCommentWithLongValues } from './mock-comment'; const CommentSetterEffect = () => { - const setViewableActivity = useSetRecoilState(viewableActivityIdState); + const setViewableActivity = useSetRecoilState(viewableRecordIdState); useEffect(() => { setViewableActivity('test-id'); 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 d61ebc25b23e..a5cbe53275f8 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 @@ -4,7 +4,7 @@ import { DateTime } from 'luxon'; import { useSetRecoilState } from 'recoil'; import { ActivityActionBar } from '@/activities/right-drawer/components/ActivityActionBar'; -import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator'; import { avatarUrl } from '~/testing/mock-data/users'; @@ -13,7 +13,7 @@ import { CommentHeader } from '../CommentHeader'; import { mockComment, mockCommentWithLongValues } from './mock-comment'; const CommentHeaderSetterEffect = () => { - const setViewableActivity = useSetRecoilState(viewableActivityIdState); + const setViewableActivity = useSetRecoilState(viewableRecordIdState); useEffect(() => { setViewableActivity('test-id'); diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenActivityRightDrawer.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenActivityRightDrawer.test.tsx index 19a027551a21..2190c612c848 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenActivityRightDrawer.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenActivityRightDrawer.test.tsx @@ -5,7 +5,10 @@ import { RecoilRoot, useRecoilValue } from 'recoil'; import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer'; import { activityIdInDrawerState } from '@/activities/states/activityIdInDrawerState'; -import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState'; +import { + viewableRecordIdState, + viewableRecordIdState, +} from '@/object-record/record-right-drawer/states/viewableRecordIdState'; const Wrapper = ({ children }: { children: ReactNode }) => ( @@ -18,12 +21,12 @@ describe('useOpenActivityRightDrawer', () => { const { result } = renderHook( () => { const openActivityRightDrawer = useOpenActivityRightDrawer(); - const viewableActivityId = useRecoilValue(viewableActivityIdState); + const viewableRecordId = useRecoilValue(viewableRecordIdState); const activityIdInDrawer = useRecoilValue(activityIdInDrawerState); return { openActivityRightDrawer, activityIdInDrawer, - viewableActivityId, + viewableRecordId, }; }, { @@ -32,11 +35,11 @@ describe('useOpenActivityRightDrawer', () => { ); expect(result.current.activityIdInDrawer).toBeNull(); - expect(result.current.viewableActivityId).toBeNull(); + expect(result.current.viewableRecordId).toBeNull(); act(() => { result.current.openActivityRightDrawer('123'); }); expect(result.current.activityIdInDrawer).toBe('123'); - expect(result.current.viewableActivityId).toBe('123'); + expect(result.current.viewableRecordId).toBe('123'); }); }); diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawer.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawer.test.tsx index eb60717a4125..b545e455c8b0 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawer.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenCreateActivityDrawer.test.tsx @@ -5,9 +5,9 @@ import { RecoilRoot, useRecoilValue, useSetRecoilState } from 'recoil'; import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer'; import { activityIdInDrawerState } from '@/activities/states/activityIdInDrawerState'; -import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { getObjectMetadataItemsMock } from '@/object-metadata/utils/getObjectMetadataItemsMock'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; const mockUUID = '37873e04-2f83-4468-9ab7-3f87da6cafad'; @@ -28,7 +28,7 @@ describe('useOpenCreateActivityDrawer', () => { const { result } = renderHook( () => { const openActivityRightDrawer = useOpenCreateActivityDrawer(); - const viewableActivityId = useRecoilValue(viewableActivityIdState); + const viewableRecordId = useRecoilValue(viewableRecordIdState); const activityIdInDrawer = useRecoilValue(activityIdInDrawerState); const setObjectMetadataItems = useSetRecoilState( objectMetadataItemsState, @@ -36,7 +36,7 @@ describe('useOpenCreateActivityDrawer', () => { return { openActivityRightDrawer, activityIdInDrawer, - viewableActivityId, + viewableRecordId, setObjectMetadataItems, }; }, @@ -50,7 +50,7 @@ describe('useOpenCreateActivityDrawer', () => { }); expect(result.current.activityIdInDrawer).toBeNull(); - expect(result.current.viewableActivityId).toBeNull(); + expect(result.current.viewableRecordId).toBeNull(); await act(async () => { result.current.openActivityRightDrawer({ type: 'Note', @@ -58,6 +58,6 @@ describe('useOpenCreateActivityDrawer', () => { }); }); expect(result.current.activityIdInDrawer).toBe(mockUUID); - expect(result.current.viewableActivityId).toBe(mockUUID); + expect(result.current.viewableRecordId).toBe(mockUUID); }); }); diff --git a/packages/twenty-front/src/modules/activities/hooks/useOpenActivityRightDrawer.ts b/packages/twenty-front/src/modules/activities/hooks/useOpenActivityRightDrawer.ts index b0279e17eece..185661f2a996 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useOpenActivityRightDrawer.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useOpenActivityRightDrawer.ts @@ -1,18 +1,17 @@ import { useRecoilState, useSetRecoilState } from 'recoil'; import { activityIdInDrawerState } from '@/activities/states/activityIdInDrawerState'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; 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'; -import { viewableActivityIdState } from '../states/viewableActivityIdState'; - export const useOpenActivityRightDrawer = () => { const { openRightDrawer, isRightDrawerOpen, rightDrawerPage } = useRightDrawer(); - const [viewableActivityId, setViewableActivityId] = useRecoilState( - viewableActivityIdState, + const [viewableRecordId, setViewableRecordId] = useRecoilState( + viewableRecordIdState, ); const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState); const setHotkeyScope = useSetHotkeyScope(); @@ -21,13 +20,13 @@ export const useOpenActivityRightDrawer = () => { if ( isRightDrawerOpen && rightDrawerPage === RightDrawerPages.EditActivity && - viewableActivityId === activityId + viewableRecordId === activityId ) { return; } setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false }); - setViewableActivityId(activityId); + setViewableRecordId(activityId); setActivityIdInDrawer(activityId); openRightDrawer(RightDrawerPages.EditActivity); }; diff --git a/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts b/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts index 521473627095..88952baede3a 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts @@ -6,8 +6,8 @@ import { activityTargetableEntityArrayState } from '@/activities/states/activity import { isActivityInCreateModeState } from '@/activities/states/isActivityInCreateModeState'; import { isUpsertingActivityInDBState } from '@/activities/states/isCreatingActivityInDBState'; import { temporaryActivityForEditorState } from '@/activities/states/temporaryActivityForEditorState'; -import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState'; import { ActivityType } from '@/activities/types/Activity'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; 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'; @@ -26,7 +26,7 @@ export const useOpenCreateActivityDrawer = () => { const setActivityTargetableEntityArray = useSetRecoilState( activityTargetableEntityArrayState, ); - const setViewableActivityId = useSetRecoilState(viewableActivityIdState); + const setViewableActivityId = useSetRecoilState(viewableRecordIdState); const setIsCreatingActivity = useSetRecoilState(isActivityInCreateModeState); 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 27cfbf2d3c86..8588650e5c3b 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 @@ -10,7 +10,6 @@ import { activityTargetableEntityArrayState } from '@/activities/states/activity import { isActivityInCreateModeState } from '@/activities/states/isActivityInCreateModeState'; import { isUpsertingActivityInDBState } from '@/activities/states/isCreatingActivityInDBState'; import { temporaryActivityForEditorState } from '@/activities/states/temporaryActivityForEditorState'; -import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState'; import { objectShowPageTargetableObjectState } from '@/activities/timeline/states/objectShowPageTargetableObjectIdState'; import { Activity } from '@/activities/types/Activity'; import { ActivityTarget } from '@/activities/types/ActivityTarget'; @@ -18,6 +17,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi import { useDeleteRecordFromCache } from '@/object-record/cache/hooks/useDeleteRecordFromCache'; import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords'; import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { mapToRecordId } from '@/object-record/utils/mapToObjectId'; import { IconButton } from '@/ui/input/button/components/IconButton'; @@ -30,7 +30,7 @@ const StyledButtonContainer = styled.div` `; export const ActivityActionBar = () => { - const viewableActivityId = useRecoilValue(viewableActivityIdState); + const viewableRecordId = useRecoilValue(viewableRecordIdState); const activityIdInDrawer = useRecoilValue(activityIdInDrawerState); const activityTargetableEntityArray = useRecoilValue( @@ -86,7 +86,7 @@ export const ActivityActionBar = () => { setIsRightDrawerOpen(false); - if (!isNonEmptyString(viewableActivityId)) { + if (!isNonEmptyString(viewableRecordId)) { return; } @@ -111,13 +111,13 @@ export const ActivityActionBar = () => { await deleteManyActivityTargets(activityTargetIdsToDelete); } - await deleteOneActivity?.(viewableActivityId); + await deleteOneActivity?.(viewableRecordId); } }, [ activityIdInDrawer, setIsRightDrawerOpen, - viewableActivityId, + viewableRecordId, isActivityInCreateMode, temporaryActivityForEditor, deleteActivityFromCache, @@ -129,9 +129,7 @@ export const ActivityActionBar = () => { ], ); - const record = useRecoilValue( - recordStoreFamilyState(viewableActivityId ?? ''), - ); + const record = useRecoilValue(recordStoreFamilyState(viewableRecordId ?? '')); const addActivity = () => { setIsRightDrawerOpen(false); diff --git a/packages/twenty-front/src/modules/activities/right-drawer/components/create/RightDrawerCreateActivity.tsx b/packages/twenty-front/src/modules/activities/right-drawer/components/create/RightDrawerCreateActivity.tsx index fe6ac8ecaf43..d4b64f7f5239 100644 --- a/packages/twenty-front/src/modules/activities/right-drawer/components/create/RightDrawerCreateActivity.tsx +++ b/packages/twenty-front/src/modules/activities/right-drawer/components/create/RightDrawerCreateActivity.tsx @@ -1,17 +1,17 @@ import { useRecoilValue } from 'recoil'; -import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { RightDrawerActivity } from '../RightDrawerActivity'; export const RightDrawerCreateActivity = () => { - const viewableActivityId = useRecoilValue(viewableActivityIdState); + const viewableRecordId = useRecoilValue(viewableRecordIdState); return ( <> - {viewableActivityId && ( + {viewableRecordId && ( diff --git a/packages/twenty-front/src/modules/activities/right-drawer/components/edit/RightDrawerEditActivity.tsx b/packages/twenty-front/src/modules/activities/right-drawer/components/edit/RightDrawerEditActivity.tsx index 288d7aca88af..84d0168696d1 100644 --- a/packages/twenty-front/src/modules/activities/right-drawer/components/edit/RightDrawerEditActivity.tsx +++ b/packages/twenty-front/src/modules/activities/right-drawer/components/edit/RightDrawerEditActivity.tsx @@ -1,16 +1,16 @@ import { useRecoilValue } from 'recoil'; -import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { RightDrawerActivity } from '../RightDrawerActivity'; export const RightDrawerEditActivity = () => { - const viewableActivityId = useRecoilValue(viewableActivityIdState); + const viewableRecordId = useRecoilValue(viewableRecordIdState); return ( <> - {viewableActivityId && ( - + {viewableRecordId && ( + )} ); diff --git a/packages/twenty-front/src/modules/activities/states/viewableActivityIdState.ts b/packages/twenty-front/src/modules/activities/states/viewableActivityIdState.ts deleted file mode 100644 index 393a2f96aaa5..000000000000 --- a/packages/twenty-front/src/modules/activities/states/viewableActivityIdState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createState } from 'twenty-ui'; - -export const viewableActivityIdState = createState({ - key: 'activities/viewable-activity-id', - defaultValue: null, -}); diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx index 0e3e21018532..21f62cfec8f1 100644 --- a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx @@ -1,14 +1,20 @@ import { useParams } from 'react-router-dom'; import styled from '@emotion/styled'; +import { useSetRecoilState } from 'recoil'; import { v4 } from 'uuid'; +import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; import { RecordIndexContainer } from '@/object-record/record-index/components/RecordIndexContainer'; import { RecordIndexPageHeader } from '@/object-record/record-index/components/RecordIndexPageHeader'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; +import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { DEFAULT_CELL_SCOPE } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCell'; import { useSelectedTableCellEditMode } from '@/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode'; import { PageBody } from '@/ui/layout/page/PageBody'; import { PageContainer } from '@/ui/layout/page/PageContainer'; +import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; +import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; import { PageTitle } from '@/ui/utilities/page-title/PageTitle'; import { capitalize } from '~/utils/string/capitalize'; @@ -25,6 +31,10 @@ export const RecordIndexPage = () => { const recordIndexId = objectNamePlural ?? ''; const setHotkeyScope = useSetHotkeyScope(); + const { objectNameSingular } = useObjectNameSingularFromPlural({ + objectNamePlural, + }); + const { setSelectedTableCellEditMode } = useSelectedTableCellEditMode({ scopeId: recordIndexId, }); @@ -33,8 +43,19 @@ export const RecordIndexPage = () => { recordTableId: recordIndexId, }); + const { openRightDrawer } = useRightDrawer(); + const setViewableRecordId = useSetRecoilState(viewableRecordIdState); + const setViewableRecordNameSingular = useSetRecoilState( + viewableRecordNameSingularState, + ); + const handleAddButtonClick = async () => { - setPendingRecordId(v4()); + const pendingId = v4(); + setPendingRecordId(pendingId); + + setViewableRecordId(pendingId); + setViewableRecordNameSingular(objectNameSingular); + openRightDrawer(RightDrawerPages.ViewRecord); setSelectedTableCellEditMode(-1, 0); setHotkeyScope(DEFAULT_CELL_SCOPE.scope, DEFAULT_CELL_SCOPE.customScopes); From 79d67321c5ca7b9bd78e6d7ba9da24b2cba4502d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Thu, 23 May 2024 17:35:52 +0200 Subject: [PATCH 03/30] Remove viewableEmailThreadIdState --- .../emails/hooks/__tests__/useEmailThread.test.tsx | 11 +++++------ .../modules/activities/emails/hooks/useEmailThread.ts | 8 ++++---- .../right-drawer/hooks/useRightDrawerEmailThread.ts | 10 +++++----- .../emails/states/viewableEmailThreadIdState.ts | 6 ------ 4 files changed, 14 insertions(+), 21 deletions(-) delete mode 100644 packages/twenty-front/src/modules/activities/emails/states/viewableEmailThreadIdState.ts diff --git a/packages/twenty-front/src/modules/activities/emails/hooks/__tests__/useEmailThread.test.tsx b/packages/twenty-front/src/modules/activities/emails/hooks/__tests__/useEmailThread.test.tsx index 4dae422ca2fd..8d8b2c206f0c 100644 --- a/packages/twenty-front/src/modules/activities/emails/hooks/__tests__/useEmailThread.test.tsx +++ b/packages/twenty-front/src/modules/activities/emails/hooks/__tests__/useEmailThread.test.tsx @@ -3,6 +3,7 @@ import { RecoilRoot, useRecoilState, useRecoilValue } from 'recoil'; import { useEmailThread } from '@/activities/emails/hooks/useEmailThread'; import { viewableEmailThreadIdState } from '@/activities/emails/states/viewableEmailThreadIdState'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState'; const viewableEmailThreadId = '1234'; @@ -13,24 +14,22 @@ describe('useEmailThread', () => { () => { const emailThread = useEmailThread(); const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState); - const viewableEmailThreadId = useRecoilValue( - viewableEmailThreadIdState, - ); + const viewableRecordId = useRecoilValue(viewableRecordIdState); - return { ...emailThread, isRightDrawerOpen, viewableEmailThreadId }; + return { ...emailThread, isRightDrawerOpen, viewableRecordId }; }, { wrapper: RecoilRoot }, ); expect(result.current.isRightDrawerOpen).toBe(false); - expect(result.current.viewableEmailThreadId).toBeNull(); + expect(result.current.viewableRecordId).toBeNull(); act(() => { result.current.openEmailThread(viewableEmailThreadId); }); expect(result.current.isRightDrawerOpen).toBe(true); - expect(result.current.viewableEmailThreadId).toBe(viewableEmailThreadId); + expect(result.current.viewableRecordId).toBe(viewableEmailThreadId); }); it('should close email thread if trying to open the same thread id', () => { diff --git a/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts b/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts index a0757a18af57..d27955b30eae 100644 --- a/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts +++ b/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts @@ -1,7 +1,7 @@ import { useRecoilCallback } from 'recoil'; import { useOpenEmailThreadRightDrawer } from '@/activities/emails/right-drawer/hooks/useOpenEmailThreadRightDrawer'; -import { viewableEmailThreadIdState } from '@/activities/emails/states/viewableEmailThreadIdState'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState'; @@ -17,17 +17,17 @@ export const useEmailThread = () => { .getValue(); const viewableEmailThreadId = snapshot - .getLoadable(viewableEmailThreadIdState) + .getLoadable(viewableRecordIdState) .getValue(); if (isRightDrawerOpen && viewableEmailThreadId === threadId) { - set(viewableEmailThreadIdState, null); + set(viewableRecordIdState, null); closeRightDrawer(); return; } openEmailThredRightDrawer(); - set(viewableEmailThreadIdState, threadId); + set(viewableRecordIdState, threadId); }, [closeRightDrawer, openEmailThredRightDrawer], ); diff --git a/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useRightDrawerEmailThread.ts b/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useRightDrawerEmailThread.ts index dce19bb82e84..bc415e406aa7 100644 --- a/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useRightDrawerEmailThread.ts +++ b/packages/twenty-front/src/modules/activities/emails/right-drawer/hooks/useRightDrawerEmailThread.ts @@ -4,16 +4,16 @@ import gql from 'graphql-tag'; import { useRecoilValue } from 'recoil'; import { fetchAllThreadMessagesOperationSignatureFactory } from '@/activities/emails/graphql/operation-signatures/factories/fetchAllThreadMessagesOperationSignatureFactory'; -import { viewableEmailThreadIdState } from '@/activities/emails/states/viewableEmailThreadIdState'; import { EmailThreadMessage as EmailThreadMessageType } from '@/activities/emails/types/EmailThreadMessage'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; export const useRightDrawerEmailThread = () => { - const viewableEmailThreadId = useRecoilValue(viewableEmailThreadIdState); + const viewableRecordId = useRecoilValue(viewableRecordIdState); const apolloClient = useApolloClient(); const thread = apolloClient.readFragment({ - id: `TimelineThread:${viewableEmailThreadId}`, + id: `TimelineThread:${viewableRecordId}`, fragment: gql` fragment timelineThread on TimelineThread { id @@ -25,7 +25,7 @@ export const useRightDrawerEmailThread = () => { const FETCH_ALL_MESSAGES_OPERATION_SIGNATURE = fetchAllThreadMessagesOperationSignatureFactory({ - messageThreadId: viewableEmailThreadId, + messageThreadId: viewableRecordId, }); const { @@ -39,7 +39,7 @@ export const useRightDrawerEmailThread = () => { FETCH_ALL_MESSAGES_OPERATION_SIGNATURE.objectNameSingular, orderBy: FETCH_ALL_MESSAGES_OPERATION_SIGNATURE.variables.orderBy, recordGqlFields: FETCH_ALL_MESSAGES_OPERATION_SIGNATURE.fields, - skip: !viewableEmailThreadId, + skip: !viewableRecordId, }); const fetchMoreMessages = useCallback(() => { diff --git a/packages/twenty-front/src/modules/activities/emails/states/viewableEmailThreadIdState.ts b/packages/twenty-front/src/modules/activities/emails/states/viewableEmailThreadIdState.ts deleted file mode 100644 index 494ec3d9cb63..000000000000 --- a/packages/twenty-front/src/modules/activities/emails/states/viewableEmailThreadIdState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createState } from 'twenty-ui'; - -export const viewableEmailThreadIdState = createState({ - key: 'viewableEmailThreadIdState', - defaultValue: null, -}); From b2cf04b22c2e9db38397c7455a74cc3f04cd5e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Thu, 23 May 2024 20:53:24 +0200 Subject: [PATCH 04/30] Actually better if we close the sidepanel on click outside --- .../src/modules/activities/emails/hooks/useEmailThread.ts | 6 +++--- .../hooks/__tests__/useOpenActivityRightDrawer.test.tsx | 5 +---- .../ui/layout/right-drawer/components/RightDrawer.tsx | 6 +++--- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts b/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts index d27955b30eae..c2fa722ed634 100644 --- a/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts +++ b/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts @@ -7,7 +7,7 @@ import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightD export const useEmailThread = () => { const { closeRightDrawer } = useRightDrawer(); - const openEmailThredRightDrawer = useOpenEmailThreadRightDrawer(); + const openEmailThreadRightDrawer = useOpenEmailThreadRightDrawer(); const openEmailThread = useRecoilCallback( ({ snapshot, set }) => @@ -26,10 +26,10 @@ export const useEmailThread = () => { return; } - openEmailThredRightDrawer(); + openEmailThreadRightDrawer(); set(viewableRecordIdState, threadId); }, - [closeRightDrawer, openEmailThredRightDrawer], + [closeRightDrawer, openEmailThreadRightDrawer], ); return { openEmailThread }; diff --git a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenActivityRightDrawer.test.tsx b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenActivityRightDrawer.test.tsx index 2190c612c848..1294d6ca2998 100644 --- a/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenActivityRightDrawer.test.tsx +++ b/packages/twenty-front/src/modules/activities/hooks/__tests__/useOpenActivityRightDrawer.test.tsx @@ -5,10 +5,7 @@ import { RecoilRoot, useRecoilValue } from 'recoil'; import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer'; import { activityIdInDrawerState } from '@/activities/states/activityIdInDrawerState'; -import { - viewableRecordIdState, - viewableRecordIdState, -} from '@/object-record/record-right-drawer/states/viewableRecordIdState'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; const Wrapper = ({ children }: { children: ReactNode }) => ( diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx index 9165908c49ee..b9f8fc1cc754 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx @@ -56,7 +56,7 @@ export const RightDrawer = () => { const rightDrawerPage = useRecoilValue(rightDrawerPageState); - const { closeRightDrawer, minimizeRightDrawer } = useRightDrawer(); + const { closeRightDrawer } = useRightDrawer(); const rightDrawerRef = useRef(null); @@ -75,10 +75,10 @@ export const RightDrawer = () => { if (isRightDrawerOpen) { set(rightDrawerCloseEventState, event); - minimizeRightDrawer(); + closeRightDrawer(); } }, - [minimizeRightDrawer], + [closeRightDrawer], ), mode: ClickOutsideMode.comparePixels, }); From 98ea5fa7b271240bcac2af43548d6382b7432264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Thu, 23 May 2024 21:16:00 +0200 Subject: [PATCH 05/30] Fix linter --- .../hooks/__tests__/useEmailThread.test.tsx | 14 +++++++------- .../hooks/useOpenRecordTableCellV2.ts | 9 ++++++--- .../components/RightDrawerRouter.tsx | 16 ++++++---------- ...erGenericTopBar.tsx => RightDrawerTopBar.tsx} | 6 +----- .../__stories__/RightDrawerTopBar.stories.tsx} | 8 ++++---- .../constants/RightDrawerPageIcons.ts | 1 + 6 files changed, 25 insertions(+), 29 deletions(-) rename packages/twenty-front/src/modules/ui/layout/right-drawer/components/{RightDrawerGenericTopBar.tsx => RightDrawerTopBar.tsx} (97%) rename packages/twenty-front/src/modules/{activities/right-drawer/components/__stories__/RightDrawerActivityTopBar.stories.tsx => ui/layout/right-drawer/components/__stories__/RightDrawerTopBar.stories.tsx} (70%) diff --git a/packages/twenty-front/src/modules/activities/emails/hooks/__tests__/useEmailThread.test.tsx b/packages/twenty-front/src/modules/activities/emails/hooks/__tests__/useEmailThread.test.tsx index 8d8b2c206f0c..d7d3efe0335e 100644 --- a/packages/twenty-front/src/modules/activities/emails/hooks/__tests__/useEmailThread.test.tsx +++ b/packages/twenty-front/src/modules/activities/emails/hooks/__tests__/useEmailThread.test.tsx @@ -2,7 +2,6 @@ import { act, renderHook } from '@testing-library/react'; import { RecoilRoot, useRecoilState, useRecoilValue } from 'recoil'; import { useEmailThread } from '@/activities/emails/hooks/useEmailThread'; -import { viewableEmailThreadIdState } from '@/activities/emails/states/viewableEmailThreadIdState'; import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState'; @@ -39,15 +38,16 @@ describe('useEmailThread', () => { const [isRightDrawerOpen, setIsRightDrawerOpen] = useRecoilState( isRightDrawerOpenState, ); - const [viewableEmailThreadId, setViewableEmailThreadId] = - useRecoilState(viewableEmailThreadIdState); + const [viewableRecordId, setViewableRecordId] = useRecoilState( + viewableRecordIdState, + ); return { ...emailThread, isRightDrawerOpen, - viewableEmailThreadId, + viewableRecordId, setIsRightDrawerOpen, - setViewableEmailThreadId, + setViewableRecordId, }; }, { wrapper: RecoilRoot }, @@ -55,7 +55,7 @@ describe('useEmailThread', () => { act(() => { result.current.setIsRightDrawerOpen(true); - result.current.setViewableEmailThreadId(viewableEmailThreadId); + result.current.setViewableRecordId(viewableEmailThreadId); }); act(() => { @@ -63,6 +63,6 @@ describe('useEmailThread', () => { }); expect(result.current.isRightDrawerOpen).toBe(false); - expect(result.current.viewableEmailThreadId).toBeNull(); + expect(result.current.viewableRecordId).toBeNull(); }); }); diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts index d3bd90b81dd8..ce0430356080 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts @@ -1,4 +1,3 @@ -import { useNavigate } from 'react-router-dom'; import { useRecoilCallback, useSetRecoilState } from 'recoil'; import { useInitDraftValueV2 } from '@/object-record/record-field/hooks/useInitDraftValueV2'; @@ -45,7 +44,7 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => { const setHotkeyScope = useSetHotkeyScope(); const { setDragSelectionStartEnabled } = useDragSelect(); - const navigate = useNavigate(); + // const navigate = useNavigate(); const leaveTableFocus = useLeaveTableFocus(tableScopeId); const { toggleClickOutsideListener } = useClickOutsideListener( SOFT_FOCUS_CLICK_OUTSIDE_LISTENER_ID, @@ -65,6 +64,8 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => { initialValue, cellPosition, isReadOnly, + // temporary, while refactoring + // eslint-disable-next-line unused-imports/no-unused-vars pathToShowPage, objectNameSingular, customCellHotkeyScope, @@ -128,10 +129,12 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => { setDragSelectionStartEnabled, toggleClickOutsideListener, leaveTableFocus, - navigate, setHotkeyScope, initDraftValue, moveEditModeToTableCellPosition, + openRightDrawer, + setViewableRecordId, + setViewableRecordNameSingular, ], ); 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 68e8482bbd87..c9b4ab44bed7 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 @@ -6,7 +6,7 @@ import { RightDrawerEmailThread } from '@/activities/emails/right-drawer/compone import { RightDrawerCreateActivity } from '@/activities/right-drawer/components/create/RightDrawerCreateActivity'; import { RightDrawerEditActivity } from '@/activities/right-drawer/components/edit/RightDrawerEditActivity'; import { RightDrawerRecord } from '@/object-record/record-right-drawer/components/RightDrawerRecord'; -import { RightDrawerGenericTopBar } from '@/ui/layout/right-drawer/components/RightDrawerGenericTopBar'; +import { RightDrawerTopBar } from '@/ui/layout/right-drawer/components/RightDrawerTopBar'; import { isRightDrawerMinimizedState } from '@/ui/layout/right-drawer/states/isRightDrawerMinimizedState'; import { rightDrawerPageState } from '../states/rightDrawerPageState'; @@ -32,27 +32,23 @@ const StyledRightDrawerBody = styled.div` const RIGHT_DRAWER_PAGES_CONFIG = { [RightDrawerPages.CreateActivity]: { page: , - topBar: , + topBar: , }, [RightDrawerPages.EditActivity]: { page: , - topBar: , + topBar: , }, [RightDrawerPages.ViewEmailThread]: { page: , - topBar: ( - - ), + topBar: , }, [RightDrawerPages.ViewCalendarEvent]: { page: , - topBar: ( - - ), + topBar: , }, [RightDrawerPages.ViewRecord]: { page: , - topBar: , + topBar: , }, }; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerGenericTopBar.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBar.tsx similarity index 97% rename from packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerGenericTopBar.tsx rename to packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBar.tsx index 3b4d3ba3c78e..72aa47c5356e 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerGenericTopBar.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBar.tsx @@ -36,11 +36,7 @@ const StyledMinimizeTopBarIcon = styled.div` display: flex; `; -export const RightDrawerGenericTopBar = ({ - page, -}: { - page: RightDrawerPages; -}) => { +export const RightDrawerTopBar = ({ page }: { page: RightDrawerPages }) => { const isMobile = useIsMobile(); const [isRightDrawerMinimized, setIsRightDrawerMinimized] = useRecoilState( diff --git a/packages/twenty-front/src/modules/activities/right-drawer/components/__stories__/RightDrawerActivityTopBar.stories.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/__stories__/RightDrawerTopBar.stories.tsx similarity index 70% rename from packages/twenty-front/src/modules/activities/right-drawer/components/__stories__/RightDrawerActivityTopBar.stories.tsx rename to packages/twenty-front/src/modules/ui/layout/right-drawer/components/__stories__/RightDrawerTopBar.stories.tsx index fa7616383a80..3f69b0dc387d 100644 --- a/packages/twenty-front/src/modules/activities/right-drawer/components/__stories__/RightDrawerActivityTopBar.stories.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/__stories__/RightDrawerTopBar.stories.tsx @@ -3,11 +3,11 @@ import { Meta, StoryObj } from '@storybook/react'; import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator'; import { graphqlMocks } from '~/testing/graphqlMocks'; -import { RightDrawerActivityTopBar } from '../RightDrawerActivityTopBar'; +import { RightDrawerTopBar } from '../RightDrawerTopBar'; -const meta: Meta = { +const meta: Meta = { title: 'Modules/Activities/RightDrawer/RightDrawerActivityTopBar', - component: RightDrawerActivityTopBar, + component: RightDrawerTopBar, 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/constants/RightDrawerPageIcons.ts b/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageIcons.ts index e41bc2fa591e..f1c46ba194eb 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageIcons.ts +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/constants/RightDrawerPageIcons.ts @@ -5,4 +5,5 @@ export const RIGHT_DRAWER_PAGE_ICONS = { [RightDrawerPages.EditActivity]: 'IconNote', [RightDrawerPages.ViewEmailThread]: 'IconMail', [RightDrawerPages.ViewCalendarEvent]: 'IconCalendarEvent', + [RightDrawerPages.ViewRecord]: 'Icon123', }; From 3f4ca280fecee6695f3dc2f6a01777ef2615cac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Thu, 23 May 2024 22:30:37 +0200 Subject: [PATCH 06/30] Change first cell behavior --- .../components/RecordTableCellContainer.tsx | 8 +++++--- .../hooks/useOpenRecordTableCellFromCell.ts | 6 +++++- .../record-table-cell/hooks/useOpenRecordTableCellV2.ts | 4 +++- .../ui/layout/right-drawer/components/RightDrawer.tsx | 5 ++++- .../layout/right-drawer/components/RightDrawerTopBar.tsx | 4 +++- 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellContainer.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellContainer.tsx index 28f30bf9bc9b..f29e8310567b 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellContainer.tsx @@ -1,7 +1,7 @@ import React, { ReactElement, useContext, useState } from 'react'; import styled from '@emotion/styled'; import { useRecoilValue } from 'recoil'; -import { IconArrowUpRight } from 'twenty-ui'; +import { IconLayoutSidebarRightExpand } from 'twenty-ui'; import { useGetButtonIcon } from '@/object-record/record-field/hooks/useGetButtonIcon'; import { useIsFieldEmpty } from '@/object-record/record-field/hooks/useIsFieldEmpty'; @@ -120,7 +120,7 @@ export const RecordTableCellContainer = ({ const handleButtonClick = () => { onMoveSoftFocusToCell(cellPosition); - openTableCell(); + openTableCell(undefined, true); }; const handleContextMenu = (event: React.MouseEvent) => { @@ -143,7 +143,9 @@ export const RecordTableCellContainer = ({ const isFirstColumn = columnIndex === 0; const customButtonIcon = useGetButtonIcon(); - const buttonIcon = isFirstColumn ? IconArrowUpRight : customButtonIcon; + const buttonIcon = isFirstColumn + ? IconLayoutSidebarRightExpand + : customButtonIcon; const showButton = !!buttonIcon && diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell.ts index f431d142ca9e..af16309867fb 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellFromCell.ts @@ -35,7 +35,10 @@ export const useOpenRecordTableCellFromCell = () => { RecordTableRowContext, ); - const openTableCell = (initialValue?: string) => { + const openTableCell = ( + initialValue?: string, + isActionButtonClick = false, + ) => { onOpenTableCell({ cellPosition, customCellHotkeyScope, @@ -45,6 +48,7 @@ export const useOpenRecordTableCellFromCell = () => { pathToShowPage, objectNameSingular, initialValue, + isActionButtonClick, }); }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts index ce0430356080..50f03257e642 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts @@ -35,6 +35,7 @@ export type OpenTableCellArgs = { customCellHotkeyScope: HotkeyScope | null; fieldDefinition: FieldDefinition; entityId: string; + isActionButtonClick: boolean; }; export const useOpenRecordTableCellV2 = (tableScopeId: string) => { @@ -71,6 +72,7 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => { customCellHotkeyScope, fieldDefinition, entityId, + isActionButtonClick, }: OpenTableCellArgs) => { if (isReadOnly) { return; @@ -91,7 +93,7 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => { fieldValue, }); - if (isFirstColumnCell && !isEmpty) { + if (isFirstColumnCell && !isEmpty && isActionButtonClick) { leaveTableFocus(); // navigate(pathToShowPage); setViewableRecordId(entityId); diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx index b9f8fc1cc754..38e8ca48526d 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx @@ -72,8 +72,11 @@ export const RightDrawer = () => { const isRightDrawerOpen = snapshot .getLoadable(isRightDrawerOpenState) .getValue(); + const isRightDrawerMinimized = snapshot + .getLoadable(isRightDrawerMinimizedState) + .getValue(); - if (isRightDrawerOpen) { + if (isRightDrawerOpen && !isRightDrawerMinimized) { set(rightDrawerCloseEventState, event); closeRightDrawer(); } 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 index 72aa47c5356e..e83a38d4a33b 100644 --- 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 @@ -80,7 +80,9 @@ export const RightDrawerTopBar = ({ page }: { page: RightDrawerPages }) => { )} - {!isRightDrawerMinimized && } + {!isMobile && !isRightDrawerMinimized && ( + + )} {!isMobile && !isRightDrawerMinimized && ( )} From ec11e453d635a76b3729da260a2b7be6f1d950a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Thu, 23 May 2024 23:35:10 +0200 Subject: [PATCH 07/30] Remove panel for creation from index, focus on creation from show instead --- .../object-record/hooks/useCreateOneRecord.ts | 6 +++ .../components/RecordShowContainer.tsx | 48 +++++++++++-------- .../components/RecordShowContainerEffect.tsx | 41 ---------------- .../RecordDetailRelationSection.tsx | 29 ++++++++++- .../pages/object-record/RecordIndexPage.tsx | 24 +--------- 5 files changed, 62 insertions(+), 86 deletions(-) delete mode 100644 packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerEffect.tsx diff --git a/packages/twenty-front/src/modules/object-record/hooks/useCreateOneRecord.ts b/packages/twenty-front/src/modules/object-record/hooks/useCreateOneRecord.ts index 47ab23f5b17e..5cb2d9a436cf 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useCreateOneRecord.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useCreateOneRecord.ts @@ -1,3 +1,4 @@ +import { useState } from 'react'; import { useApolloClient } from '@apollo/client'; import { v4 } from 'uuid'; @@ -28,6 +29,7 @@ export const useCreateOneRecord = < skipPostOptmisticEffect = false, }: useCreateOneRecordProps) => { const apolloClient = useApolloClient(); + const [loading, setLoading] = useState(false); const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular, @@ -50,6 +52,8 @@ export const useCreateOneRecord = < const { objectMetadataItems } = useObjectMetadataItems(); const createOneRecord = async (input: Partial) => { + setLoading(true); + const idForCreation = input.id ?? v4(); const sanitizedInput = { @@ -94,6 +98,7 @@ export const useCreateOneRecord = < recordsToCreate: [record], objectMetadataItems, }); + setLoading(false); }, }); @@ -102,5 +107,6 @@ export const useCreateOneRecord = < return { createOneRecord, + loading, }; }; diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx index 78afbbf8273b..1e6aa5c0b52e 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx @@ -63,6 +63,10 @@ export const RecordShowContainer = ({ recordStoreFamilyState(objectRecordId), ); + console.log('yo'); + console.log(recordFromStore); + console.log(objectRecordId); + const recordIdentifier = useRecoilValue( recordStoreIdentifierFamilySelector({ objectNameSingular, @@ -211,27 +215,29 @@ export const RecordShowContainer = ({ objectNameSingular={objectNameSingular} /> )} - {relationFieldMetadataItems?.map((fieldMetadataItem, index) => ( - - - - ))} + {!isInRightDrawer && + relationFieldMetadataItems?.map((fieldMetadataItem, index) => ( + + + + ))} )} diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerEffect.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerEffect.tsx deleted file mode 100644 index e3b835c9be8c..000000000000 --- a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerEffect.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { useEffect } from 'react'; -import { useRecoilState, useSetRecoilState } from 'recoil'; - -import { Activity } from '@/activities/types/Activity'; -import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord'; -import { recordLoadingFamilyState } from '@/object-record/record-store/states/recordLoadingFamilyState'; -import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; -import { isDefined } from '~/utils/isDefined'; - -export const RecordShowContainer = ({ - objectRecordId, - objectNameSingular, -}: { - objectRecordId: string; - objectNameSingular: string; -}) => { - const { record: activity, loading } = useFindOneRecord({ - objectRecordId, - objectNameSingular, - }); - - const setRecordStore = useSetRecoilState( - recordStoreFamilyState(objectRecordId), - ); - - const [recordLoading, setRecordLoading] = useRecoilState( - recordLoadingFamilyState(objectRecordId), - ); - - useEffect(() => { - if (loading !== recordLoading) { - setRecordLoading(loading); - } - }, [loading, recordLoading, setRecordLoading]); - - useEffect(() => { - if (!loading && isDefined(activity)) { - setRecordStore(activity); - } - }, [loading, setRecordStore, activity]); -}; diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx index 747179db336b..5bbf11df7590 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx @@ -3,14 +3,18 @@ import Skeleton, { SkeletonTheme } from 'react-loading-skeleton'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import qs from 'qs'; -import { useRecoilValue } from 'recoil'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; import { IconForbid, IconPencil, IconPlus } from 'twenty-ui'; +import { v4 } from 'uuid'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; import { usePersistField } from '@/object-record/record-field/hooks/usePersistField'; import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; +import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState'; import { RecordDetailRelationRecordsList } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsList'; import { RecordDetailRelationRecordsListEmptyState } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListEmptyState'; import { RecordDetailSection } from '@/object-record/record-show/record-detail-section/components/RecordDetailSection'; @@ -26,6 +30,8 @@ import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; +import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; +import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; import { FilterQueryParams } from '@/views/hooks/internal/useViewFromQueryParams'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; @@ -154,6 +160,26 @@ export const RecordDetailRelationSection = ({ ); }; + const { openRightDrawer } = useRightDrawer(); + const setViewableRecordId = useSetRecoilState(viewableRecordIdState); + const setViewableRecordNameSingular = useSetRecoilState( + viewableRecordNameSingularState, + ); + + const { createOneRecord } = useCreateOneRecord({ + objectNameSingular: relationObjectMetadataNameSingular, + }); + + const handleOnCreate = async () => { + const newRecordId = v4(); + await createOneRecord({ + id: newRecordId, + }); + setViewableRecordId(newRecordId); + setViewableRecordNameSingular(relationObjectMetadataNameSingular); + openRightDrawer(RightDrawerPages.ViewRecord); + }; + return ( } diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx index 21f62cfec8f1..bcb3508dc359 100644 --- a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx @@ -1,20 +1,14 @@ import { useParams } from 'react-router-dom'; import styled from '@emotion/styled'; -import { useSetRecoilState } from 'recoil'; import { v4 } from 'uuid'; -import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; import { RecordIndexContainer } from '@/object-record/record-index/components/RecordIndexContainer'; import { RecordIndexPageHeader } from '@/object-record/record-index/components/RecordIndexPageHeader'; -import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; -import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { DEFAULT_CELL_SCOPE } from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCell'; import { useSelectedTableCellEditMode } from '@/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode'; import { PageBody } from '@/ui/layout/page/PageBody'; import { PageContainer } from '@/ui/layout/page/PageContainer'; -import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; -import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; import { PageTitle } from '@/ui/utilities/page-title/PageTitle'; import { capitalize } from '~/utils/string/capitalize'; @@ -31,10 +25,6 @@ export const RecordIndexPage = () => { const recordIndexId = objectNamePlural ?? ''; const setHotkeyScope = useSetHotkeyScope(); - const { objectNameSingular } = useObjectNameSingularFromPlural({ - objectNamePlural, - }); - const { setSelectedTableCellEditMode } = useSelectedTableCellEditMode({ scopeId: recordIndexId, }); @@ -43,20 +33,8 @@ export const RecordIndexPage = () => { recordTableId: recordIndexId, }); - const { openRightDrawer } = useRightDrawer(); - const setViewableRecordId = useSetRecoilState(viewableRecordIdState); - const setViewableRecordNameSingular = useSetRecoilState( - viewableRecordNameSingularState, - ); - const handleAddButtonClick = async () => { - const pendingId = v4(); - setPendingRecordId(pendingId); - - setViewableRecordId(pendingId); - setViewableRecordNameSingular(objectNameSingular); - openRightDrawer(RightDrawerPages.ViewRecord); - + setPendingRecordId(v4()); setSelectedTableCellEditMode(-1, 0); setHotkeyScope(DEFAULT_CELL_SCOPE.scope, DEFAULT_CELL_SCOPE.customScopes); }; From dc5df248ccc2c0833544dabb26a3c16ddf25c999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Thu, 23 May 2024 23:37:29 +0200 Subject: [PATCH 08/30] Remove viewableCalendarEventIdState --- .../components/RightDrawerCalendarEvent.tsx | 6 +++--- .../useOpenCalendarEventRightDrawer.test.tsx | 12 +++++------- .../hooks/useOpenCalendarEventRightDrawer.ts | 6 ++---- .../calendar/states/viewableCalendarEventIdState.ts | 6 ------ 4 files changed, 10 insertions(+), 20 deletions(-) delete mode 100644 packages/twenty-front/src/modules/activities/calendar/states/viewableCalendarEventIdState.ts diff --git a/packages/twenty-front/src/modules/activities/calendar/right-drawer/components/RightDrawerCalendarEvent.tsx b/packages/twenty-front/src/modules/activities/calendar/right-drawer/components/RightDrawerCalendarEvent.tsx index 4f760bf95851..06aa66012f55 100644 --- a/packages/twenty-front/src/modules/activities/calendar/right-drawer/components/RightDrawerCalendarEvent.tsx +++ b/packages/twenty-front/src/modules/activities/calendar/right-drawer/components/RightDrawerCalendarEvent.tsx @@ -2,18 +2,18 @@ import { useRecoilValue } from 'recoil'; import { CalendarEventDetails } from '@/activities/calendar/components/CalendarEventDetails'; import { FIND_ONE_CALENDAR_EVENT_OPERATION_SIGNATURE } from '@/activities/calendar/graphql/operation-signatures/FindOneCalendarEventOperationSignature'; -import { viewableCalendarEventIdState } from '@/activities/calendar/states/viewableCalendarEventIdState'; import { CalendarEvent } from '@/activities/calendar/types/CalendarEvent'; 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 RightDrawerCalendarEvent = () => { const { setRecords } = useSetRecordInStore(); - const viewableCalendarEventId = useRecoilValue(viewableCalendarEventIdState); + const viewableRecordId = useRecoilValue(viewableRecordIdState); const { record: calendarEvent } = useFindOneRecord({ objectNameSingular: FIND_ONE_CALENDAR_EVENT_OPERATION_SIGNATURE.objectNameSingular, - objectRecordId: viewableCalendarEventId ?? '', + objectRecordId: viewableRecordId ?? '', recordGqlFields: FIND_ONE_CALENDAR_EVENT_OPERATION_SIGNATURE.fields, onCompleted: (record) => setRecords([record]), }); diff --git a/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/__tests__/useOpenCalendarEventRightDrawer.test.tsx b/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/__tests__/useOpenCalendarEventRightDrawer.test.tsx index 027f7f87557a..9801608508e1 100644 --- a/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/__tests__/useOpenCalendarEventRightDrawer.test.tsx +++ b/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/__tests__/useOpenCalendarEventRightDrawer.test.tsx @@ -2,7 +2,7 @@ import { act, renderHook } from '@testing-library/react'; import { RecoilRoot, useRecoilValue } from 'recoil'; import { useOpenCalendarEventRightDrawer } from '@/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer'; -import { viewableCalendarEventIdState } from '@/activities/calendar/states/viewableCalendarEventIdState'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState'; describe('useOpenCalendarEventRightDrawer', () => { @@ -10,26 +10,24 @@ describe('useOpenCalendarEventRightDrawer', () => { const { result } = renderHook( () => { const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState); - const viewableCalendarEventId = useRecoilValue( - viewableCalendarEventIdState, - ); + const viewableRecordId = useRecoilValue(viewableRecordIdState); return { ...useOpenCalendarEventRightDrawer(), isRightDrawerOpen, - viewableCalendarEventId, + viewableRecordId, }; }, { wrapper: RecoilRoot }, ); expect(result.current.isRightDrawerOpen).toBe(false); - expect(result.current.viewableCalendarEventId).toBeNull(); + expect(result.current.viewableRecordId).toBeNull(); act(() => { result.current.openCalendarEventRightDrawer('1234'); }); expect(result.current.isRightDrawerOpen).toBe(true); - expect(result.current.viewableCalendarEventId).toBe('1234'); + expect(result.current.viewableRecordId).toBe('1234'); }); }); diff --git a/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer.ts b/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer.ts index 9cd27d017e52..b8e275f85196 100644 --- a/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer.ts +++ b/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer.ts @@ -1,6 +1,6 @@ import { useSetRecoilState } from 'recoil'; -import { viewableCalendarEventIdState } from '@/activities/calendar/states/viewableCalendarEventIdState'; +import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; 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'; @@ -9,9 +9,7 @@ import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope export const useOpenCalendarEventRightDrawer = () => { const { openRightDrawer } = useRightDrawer(); const setHotkeyScope = useSetHotkeyScope(); - const setViewableCalendarEventId = useSetRecoilState( - viewableCalendarEventIdState, - ); + const setViewableCalendarEventId = useSetRecoilState(viewableRecordIdState); const openCalendarEventRightDrawer = (calendarEventId: string) => { setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false }); diff --git a/packages/twenty-front/src/modules/activities/calendar/states/viewableCalendarEventIdState.ts b/packages/twenty-front/src/modules/activities/calendar/states/viewableCalendarEventIdState.ts deleted file mode 100644 index 32d1951bcf5b..000000000000 --- a/packages/twenty-front/src/modules/activities/calendar/states/viewableCalendarEventIdState.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { createState } from 'twenty-ui'; - -export const viewableCalendarEventIdState = createState({ - key: 'viewableCalendarEventIdState', - defaultValue: null, -}); From c1447471bdcdb202a8930c753679593af049087c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Fri, 24 May 2024 12:09:05 +0200 Subject: [PATCH 09/30] Summary tab --- .../components/RecordShowContainer.tsx | 214 +++++++++--------- .../hooks/useOpenRecordTableCellV2.ts | 11 +- .../components/ShowPageRightContainer.tsx | 12 + .../ui/layout/tab/components/TabList.tsx | 2 +- 4 files changed, 133 insertions(+), 106 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx index 1e6aa5c0b52e..a41cce84ab7d 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx @@ -25,6 +25,7 @@ import { ShowPageRightContainer } from '@/ui/layout/show-page/components/ShowPag import { ShowPageSummaryCard } from '@/ui/layout/show-page/components/ShowPageSummaryCard'; import { ShowPageRecoilScopeContext } from '@/ui/layout/states/ShowPageRecoilScopeContext'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; +import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { FieldMetadataType, FileFolder, @@ -63,10 +64,6 @@ export const RecordShowContainer = ({ recordStoreFamilyState(objectRecordId), ); - console.log('yo'); - console.log(recordFromStore); - console.log(objectRecordId); - const recordIdentifier = useRecoilValue( recordStoreIdentifierFamilySelector({ objectNameSingular, @@ -133,113 +130,121 @@ export const RecordShowContainer = ({ ); const isReadOnly = objectMetadataItem.isRemote; + const isMobile = useIsMobile(); + + const summary = (hideOnMobile: boolean) => + isDefined(recordFromStore) ? ( + <> + {(!isMobile || !hideOnMobile) && ( + + {inlineFieldMetadataItems.map((fieldMetadataItem, index) => ( + + + + ))} + + )} + {!isInRightDrawer && (!isMobile || !hideOnMobile) && ( + + )} + {!isInRightDrawer && + (!isMobile || !hideOnMobile) && + relationFieldMetadataItems?.map((fieldMetadataItem, index) => ( + + + + ))} + + ) : ( + <> + ); return ( - {isDefined(recordFromStore) && ( - <> - - - - } - avatarType={recordIdentifier?.avatarType ?? 'rounded'} - onUploadPicture={ - objectNameSingular === 'person' ? onUploadPicture : undefined - } - /> - - {inlineFieldMetadataItems.map((fieldMetadataItem, index) => ( - - - - ))} - - {!isInRightDrawer && ( - - )} - {!isInRightDrawer && - relationFieldMetadataItems?.map((fieldMetadataItem, index) => ( - - - - ))} - + defaultValue: + labelIdentifierFieldMetadataItem?.defaultValue, + }, + useUpdateRecord: useUpdateOneObjectRecordMutation, + hotkeyScope: InlineCellHotkeyScope.InlineCell, + }} + > + + + } + avatarType={recordIdentifier?.avatarType ?? 'rounded'} + onUploadPicture={ + objectNameSingular === 'person' ? onUploadPicture : undefined + } + /> + ) : ( + <> )} + {summary(true)} {recordFromStore && !isInRightDrawer ? ( ) : ( diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts index 50f03257e642..fc0ecc984790 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts @@ -1,3 +1,4 @@ +import { useNavigate } from 'react-router-dom'; import { useRecoilCallback, useSetRecoilState } from 'recoil'; import { useInitDraftValueV2 } from '@/object-record/record-field/hooks/useInitDraftValueV2'; @@ -45,7 +46,7 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => { const setHotkeyScope = useSetHotkeyScope(); const { setDragSelectionStartEnabled } = useDragSelect(); - // const navigate = useNavigate(); + const navigate = useNavigate(); const leaveTableFocus = useLeaveTableFocus(tableScopeId); const { toggleClickOutsideListener } = useClickOutsideListener( SOFT_FOCUS_CLICK_OUTSIDE_LISTENER_ID, @@ -93,6 +94,13 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => { fieldValue, }); + if (isFirstColumnCell && !isEmpty && !isActionButtonClick) { + leaveTableFocus(); + navigate(pathToShowPage); + + return; + } + if (isFirstColumnCell && !isEmpty && isActionButtonClick) { leaveTableFocus(); // navigate(pathToShowPage); @@ -137,6 +145,7 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => { openRightDrawer, setViewableRecordId, setViewableRecordNameSingular, + navigate, ], ); diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx index fa81d538710d..eb71160ef898 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx @@ -54,6 +54,7 @@ type ShowPageRightContainerProps = { notes?: boolean; emails?: boolean; loading?: boolean; + summary?: JSX.Element; }; export const ShowPageRightContainer = ({ @@ -63,6 +64,7 @@ export const ShowPageRightContainer = ({ notes, emails, loading, + summary, }: ShowPageRightContainerProps) => { const { activeTabIdState } = useTabList(TAB_LIST_COMPONENT_ID); const activeTabId = useRecoilValue(activeTabIdState); @@ -80,7 +82,15 @@ export const ShowPageRightContainer = ({ CoreObjectNameSingular.Company) || targetableObject.targetObjectNameSingular === CoreObjectNameSingular.Person; + const isMobile = useIsMobile(); + const TASK_TABS = [ + { + id: 'summary', + title: 'Summary', + Icon: IconCheckbox, + hide: !isMobile, + }, { id: 'timeline', title: 'Timeline', @@ -135,6 +145,7 @@ export const ShowPageRightContainer = ({ tabs={TASK_TABS} /> + {activeTabId === 'summary' && summary} {activeTabId === 'timeline' && ( <> @@ -157,6 +168,7 @@ export const ShowPageRightContainer = ({ {activeTabId === 'logs' && ( )} + {} ); }; diff --git a/packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx b/packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx index 1d9f4baa5d0c..ba93d808f9d9 100644 --- a/packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx +++ b/packages/twenty-front/src/modules/ui/layout/tab/components/TabList.tsx @@ -35,7 +35,7 @@ const StyledContainer = styled.div` `; export const TabList = ({ tabs, tabListId, loading }: TabListProps) => { - const initialActiveTabId = tabs[0].id; + const initialActiveTabId = tabs.find((tab) => !tab.hide)?.id || ''; const { activeTabIdState, setActiveTabId } = useTabList(tabListId); From a8dac2b8616dd5e88c4d6199d0b604420395b3be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Sun, 26 May 2024 20:21:11 +0200 Subject: [PATCH 10/30] Improve mobile display --- .../components/RecordShowContainer.tsx | 216 +++++++++--------- .../components/ShowPageLeftContainer.tsx | 29 ++- .../components/ShowPageRightContainer.tsx | 4 +- 3 files changed, 120 insertions(+), 129 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx index a41cce84ab7d..178b64d768c2 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx @@ -31,7 +31,6 @@ import { FileFolder, useUploadImageMutation, } from '~/generated/graphql'; -import { isDefined } from '~/utils/isDefined'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; type RecordShowContainerProps = { @@ -130,123 +129,113 @@ export const RecordShowContainer = ({ ); const isReadOnly = objectMetadataItem.isRemote; - const isMobile = useIsMobile(); + const isMobile = useIsMobile() || isInRightDrawer; - const summary = (hideOnMobile: boolean) => - isDefined(recordFromStore) ? ( - <> - {(!isMobile || !hideOnMobile) && ( - - {inlineFieldMetadataItems.map((fieldMetadataItem, index) => ( - - - - ))} - - )} - {!isInRightDrawer && (!isMobile || !hideOnMobile) && ( - - )} - {!isInRightDrawer && - (!isMobile || !hideOnMobile) && - relationFieldMetadataItems?.map((fieldMetadataItem, index) => ( - - - - ))} - - ) : ( - <> - ); + const summary = recordFromStore ? ( + <> + + + + } + avatarType={recordIdentifier?.avatarType ?? 'rounded'} + onUploadPicture={ + objectNameSingular === 'person' ? onUploadPicture : undefined + } + /> + + {inlineFieldMetadataItems.map((fieldMetadataItem, index) => ( + + + + ))} + + {true && ( + + )} + {true && + relationFieldMetadataItems?.map((fieldMetadataItem, index) => ( + + + + ))} + + ) : ( + <> + ); return ( - - {isDefined(recordFromStore) ? ( - - - - } - avatarType={recordIdentifier?.avatarType ?? 'rounded'} - onUploadPicture={ - objectNameSingular === 'person' ? onUploadPicture : undefined - } - /> - ) : ( - <> - )} - {summary(true)} + + {!isMobile && summary} - {recordFromStore && !isInRightDrawer ? ( + {recordFromStore ? ( ) : ( diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx index accc499cc53c..721ba74c5ac9 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx @@ -4,24 +4,23 @@ import styled from '@emotion/styled'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; -const StyledOuterContainer = styled.div<{ isInRightDrawer: boolean }>` +const StyledOuterContainer = styled.div<{ isMobile: boolean }>` background: ${({ theme }) => theme.background.secondary}; border-bottom-left-radius: 8px; - border-right: ${({ theme }) => - useIsMobile() ? 'none' : `1px solid ${theme.border.color.medium}`}; + border-right: ${({ theme, isMobile }) => + isMobile ? 'none' : `1px solid ${theme.border.color.medium}`}; border-top-left-radius: 8px; display: flex; flex-direction: column; gap: ${({ theme }) => theme.spacing(3)}; z-index: 10; - width: ${({ isInRightDrawer }) => (isInRightDrawer ? `100%` : 'auto')}; + width: 'auto'; `; -const StyledInnerContainer = styled.div<{ isInRightDrawer: boolean }>` +const StyledInnerContainer = styled.div<{ isMobile: boolean }>` display: flex; flex-direction: column; - width: ${({ isInRightDrawer }) => - useIsMobile() || isInRightDrawer ? `100%` : '348px'}; + width: ${({ isMobile }) => (isMobile ? `100%` : '348px')}; `; const StyledIntermediateContainer = styled.div` @@ -31,26 +30,26 @@ const StyledIntermediateContainer = styled.div` `; export type ShowPageLeftContainerProps = { - isInRightDrawer: boolean; + forceMobile: boolean; children: ReactNode; }; export const ShowPageLeftContainer = ({ - isInRightDrawer = false, + forceMobile = false, children, }: ShowPageLeftContainerProps) => { - const isMobile = useIsMobile(); - return isMobile || isInRightDrawer ? ( - - + const isMobile = useIsMobile() || forceMobile; + return isMobile || forceMobile ? ( + + {children} ) : ( - + - + {children} diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx index eb71160ef898..892a56318fc2 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx @@ -55,6 +55,7 @@ type ShowPageRightContainerProps = { emails?: boolean; loading?: boolean; summary?: JSX.Element; + forceMobile?: boolean; }; export const ShowPageRightContainer = ({ @@ -65,6 +66,7 @@ export const ShowPageRightContainer = ({ emails, loading, summary, + forceMobile = false, }: ShowPageRightContainerProps) => { const { activeTabIdState } = useTabList(TAB_LIST_COMPONENT_ID); const activeTabId = useRecoilValue(activeTabIdState); @@ -82,7 +84,7 @@ export const ShowPageRightContainer = ({ CoreObjectNameSingular.Company) || targetableObject.targetObjectNameSingular === CoreObjectNameSingular.Person; - const isMobile = useIsMobile(); + const isMobile = useIsMobile() || forceMobile; const TASK_TABS = [ { From ae5cf01487cc66f0d3ed51bedaf09980b2392f8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Wed, 29 May 2024 21:46:32 +0200 Subject: [PATCH 11/30] Bring back button --- .../components/RecordTableCellSoftFocusMode.tsx | 14 +++++++++++--- .../hooks/useOpenRecordTableCellV2.ts | 1 - 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx index 7862d47d2cf8..fe504a109e75 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx @@ -1,7 +1,7 @@ import { ReactElement, useContext, useEffect, useRef } from 'react'; +import { IconLayoutSidebarRightExpand } from '@tabler/icons-react'; import { useRecoilValue } from 'recoil'; import { Key } from 'ts-key-enum'; -import { IconArrowUpRight } from 'twenty-ui'; import { useClearField } from '@/object-record/record-field/hooks/useClearField'; import { useGetButtonIcon } from '@/object-record/record-field/hooks/useGetButtonIcon'; @@ -117,9 +117,17 @@ export const RecordTableCellSoftFocusMode = ({ } }; + const handleButtonClick = () => { + if (!isFieldInputOnly) { + openTableCell(undefined, true); + } + }; + const isFirstColumn = columnIndex === 0; const customButtonIcon = useGetButtonIcon(); - const buttonIcon = isFirstColumn ? IconArrowUpRight : customButtonIcon; + const buttonIcon = isFirstColumn + ? IconLayoutSidebarRightExpand + : customButtonIcon; const showButton = isDefined(buttonIcon) && @@ -136,7 +144,7 @@ export const RecordTableCellSoftFocusMode = ({ {editModeContentOnly ? editModeContent : nonEditModeContent} {showButton && ( - + )} ); diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts index fc0ecc984790..a96668841adc 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts @@ -103,7 +103,6 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => { if (isFirstColumnCell && !isEmpty && isActionButtonClick) { leaveTableFocus(); - // navigate(pathToShowPage); setViewableRecordId(entityId); setViewableRecordNameSingular(objectNameSingular); openRightDrawer(RightDrawerPages.ViewRecord); From 3ea22e98f9554b99ccf47add028c23d4c9df5e60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Thu, 30 May 2024 11:25:07 +0200 Subject: [PATCH 12/30] WIP --- .../components/RightDrawerRecord.tsx | 10 +- .../record-show/hooks/useRecordShowPage.ts | 98 +++++++++++++++++ .../pages/object-record/RecordShowPage.tsx | 100 +++--------------- 3 files changed, 120 insertions(+), 88 deletions(-) create mode 100644 packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts diff --git a/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx b/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx index 6a5f2badf41f..e84ed4b75087 100644 --- a/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx +++ b/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx @@ -3,6 +3,7 @@ import { useRecoilValue } from 'recoil'; import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState'; import { RecordShowContainer } from '@/object-record/record-show/components/RecordShowContainer'; +import { useRecordShowPage } from '@/object-record/record-show/hooks/useRecordShowPage'; export const RightDrawerRecord = () => { const viewableRecordNameSingular = useRecoilValue( @@ -18,10 +19,15 @@ export const RightDrawerRecord = () => { throw new Error(`Record id is not defined`); } + const { objectNameSingular, objectRecordId } = useRecordShowPage( + viewableRecordNameSingular ?? '', + viewableRecordId ?? '', + ); + return ( diff --git a/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts new file mode 100644 index 000000000000..161832d1ddc1 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts @@ -0,0 +1,98 @@ +import { useEffect } from 'react'; +import { useParams } from 'react-router-dom'; +import { useSetRecoilState } from 'recoil'; +import { useIcons } from 'twenty-ui'; + +import { useFavorites } from '@/favorites/hooks/useFavorites'; +import { useLabelIdentifierFieldMetadataItem } from '@/object-metadata/hooks/useLabelIdentifierFieldMetadataItem'; +import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord'; +import { findOneRecordForShowPageOperationSignatureFactory } from '@/object-record/record-show/graphql/operations/factories/findOneRecordForShowPageOperationSignatureFactory'; +import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; +import { isDefined } from '~/utils/isDefined'; +import { capitalize } from '~/utils/string/capitalize'; + +export const useRecordShowPage = ( + propsObjectNameSingular: string, + propsObjectRecordId: string, +) => { + const { + objectNameSingular: paramObjectNameSingular, + objectRecordId: paramObjectRecordId, + } = useParams(); + + const objectNameSingular = propsObjectNameSingular || paramObjectNameSingular; + const objectRecordId = propsObjectRecordId || paramObjectRecordId; + + if (!objectNameSingular || !objectRecordId) { + throw new Error('Object name or Record id is not defined'); + } + + const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular }); + const { labelIdentifierFieldMetadataItem } = + useLabelIdentifierFieldMetadataItem({ objectNameSingular }); + const { favorites, createFavorite, deleteFavorite } = useFavorites(); + const setEntityFields = useSetRecoilState( + recordStoreFamilyState(objectRecordId), + ); + const { getIcon } = useIcons(); + const headerIcon = getIcon(objectMetadataItem?.icon); + const FIND_ONE_RECORD_FOR_SHOW_PAGE_OPERATION_SIGNATURE = + findOneRecordForShowPageOperationSignatureFactory({ objectMetadataItem }); + const { record, loading } = useFindOneRecord({ + objectRecordId, + objectNameSingular, + recordGqlFields: FIND_ONE_RECORD_FOR_SHOW_PAGE_OPERATION_SIGNATURE.fields, + }); + + useEffect(() => { + if (record) { + setEntityFields(record); + } + }, [record, setEntityFields]); + + const correspondingFavorite = favorites.find( + (favorite) => favorite.recordId === objectRecordId, + ); + const isFavorite = isDefined(correspondingFavorite); + + const handleFavoriteButtonClick = async () => { + if (!objectNameSingular || !record) return; + + if (isFavorite) { + deleteFavorite(correspondingFavorite.id); + } else { + createFavorite(record, objectNameSingular); + } + }; + + const labelIdentifierFieldValue = + record?.[labelIdentifierFieldMetadataItem?.name ?? '']; + const pageName = + labelIdentifierFieldMetadataItem?.type === FieldMetadataType.FullName + ? [ + labelIdentifierFieldValue?.firstName, + labelIdentifierFieldValue?.lastName, + ].join(' ') + : isDefined(labelIdentifierFieldValue) + ? `${labelIdentifierFieldValue}` + : ''; + + const pageTitle = pageName.trim() + ? `${pageName} - ${capitalize(objectNameSingular)}` + : capitalize(objectNameSingular); + + return { + objectNameSingular, + objectRecordId, + headerIcon, + loading, + pageTitle, + pageName, + isFavorite, + handleFavoriteButtonClick, + record, + objectMetadataItem, + }; +}; diff --git a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx index 736f1621060b..215d5197310c 100644 --- a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx @@ -1,17 +1,9 @@ -import { useEffect } from 'react'; import { useParams } from 'react-router-dom'; -import { useSetRecoilState } from 'recoil'; -import { useIcons } from 'twenty-ui'; -import { useFavorites } from '@/favorites/hooks/useFavorites'; -import { useLabelIdentifierFieldMetadataItem } from '@/object-metadata/hooks/useLabelIdentifierFieldMetadataItem'; -import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; -import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord'; import { RecordShowContainer } from '@/object-record/record-show/components/RecordShowContainer'; -import { findOneRecordForShowPageOperationSignatureFactory } from '@/object-record/record-show/graphql/operations/factories/findOneRecordForShowPageOperationSignatureFactory'; +import { useRecordShowPage } from '@/object-record/record-show/hooks/useRecordShowPage'; import { RecordValueSetterEffect } from '@/object-record/record-store/components/RecordValueSetterEffect'; import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; -import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { PageBody } from '@/ui/layout/page/PageBody'; import { PageContainer } from '@/ui/layout/page/PageContainer'; import { PageFavoriteButton } from '@/ui/layout/page/PageFavoriteButton'; @@ -19,93 +11,29 @@ import { PageHeader } from '@/ui/layout/page/PageHeader'; import { ShowPageAddButton } from '@/ui/layout/show-page/components/ShowPageAddButton'; import { ShowPageMoreButton } from '@/ui/layout/show-page/components/ShowPageMoreButton'; import { PageTitle } from '@/ui/utilities/page-title/PageTitle'; -import { FieldMetadataType } from '~/generated-metadata/graphql'; -import { isDefined } from '~/utils/isDefined'; -import { capitalize } from '~/utils/string/capitalize'; export const RecordShowPage = () => { - const { objectNameSingular, objectRecordId } = useParams<{ + const parameters = useParams<{ objectNameSingular: string; objectRecordId: string; }>(); - if (!objectNameSingular) { - throw new Error(`Object name is not defined`); - } - - if (!objectRecordId) { - throw new Error(`Record id is not defined`); - } - - const { objectMetadataItem } = useObjectMetadataItem({ + const { objectNameSingular, - }); - - const { labelIdentifierFieldMetadataItem } = - useLabelIdentifierFieldMetadataItem({ - objectNameSingular, - }); - - const { favorites, createFavorite, deleteFavorite } = useFavorites(); - - const setEntityFields = useSetRecoilState( - recordStoreFamilyState(objectRecordId), - ); - - const { getIcon } = useIcons(); - - const headerIcon = getIcon(objectMetadataItem?.icon); - - const FIND_ONE_RECORD_FOR_SHOW_PAGE_OPERATION_SIGNATURE = - findOneRecordForShowPageOperationSignatureFactory({ objectMetadataItem }); - - const { record, loading } = useFindOneRecord({ objectRecordId, - objectNameSingular, - recordGqlFields: FIND_ONE_RECORD_FOR_SHOW_PAGE_OPERATION_SIGNATURE.fields, - }); - - useEffect(() => { - if (!record) { - return; - } - - setEntityFields(record); - }, [record, setEntityFields]); - - const correspondingFavorite = favorites.find( - (favorite) => favorite.recordId === objectRecordId, + headerIcon, + loading, + pageTitle, + pageName, + isFavorite, + handleFavoriteButtonClick, + record, + objectMetadataItem, + } = useRecordShowPage( + parameters.objectNameSingular ?? '', + parameters.objectRecordId ?? '', ); - const isFavorite = isDefined(correspondingFavorite); - - const handleFavoriteButtonClick = async () => { - if (!objectNameSingular || !record) return; - - if (isFavorite && isDefined(record)) { - deleteFavorite(correspondingFavorite.id); - } else { - createFavorite(record, objectNameSingular); - } - }; - - const labelIdentifierFieldValue = - record?.[labelIdentifierFieldMetadataItem?.name ?? '']; - - const pageName = - labelIdentifierFieldMetadataItem?.type === FieldMetadataType.FullName - ? [ - labelIdentifierFieldValue?.firstName, - labelIdentifierFieldValue?.lastName, - ].join(' ') - : isDefined(labelIdentifierFieldValue) - ? `${labelIdentifierFieldValue}` - : ''; - - const pageTitle = pageName.trim() - ? `${pageName} - ${capitalize(objectNameSingular)}` - : capitalize(objectNameSingular); - return ( From 33465fec6173ea8ab58986a19e27ee701711ee03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Thu, 30 May 2024 12:59:17 +0200 Subject: [PATCH 13/30] Add context --- .../components/RightDrawerRecord.tsx | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx b/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx index e84ed4b75087..49b27cdfe3eb 100644 --- a/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx +++ b/packages/twenty-front/src/modules/object-record/record-right-drawer/components/RightDrawerRecord.tsx @@ -4,6 +4,8 @@ import { viewableRecordIdState } from '@/object-record/record-right-drawer/state import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState'; import { RecordShowContainer } from '@/object-record/record-show/components/RecordShowContainer'; import { useRecordShowPage } from '@/object-record/record-show/hooks/useRecordShowPage'; +import { RecordValueSetterEffect } from '@/object-record/record-store/components/RecordValueSetterEffect'; +import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; export const RightDrawerRecord = () => { const viewableRecordNameSingular = useRecoilValue( @@ -25,11 +27,14 @@ export const RightDrawerRecord = () => { ); return ( - + + + + ); }; From a5016c94fd75f909d414897bfd2a52657df2a70f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Thu, 30 May 2024 15:25:54 +0200 Subject: [PATCH 14/30] Create relationship --- .../record-show/hooks/useRecordShowPage.ts | 2 +- .../RecordDetailRelationSection.tsx | 39 ++++++++++++++----- .../SingleEntitySelectMenuItemsWithSearch.tsx | 16 +++++++- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts index 161832d1ddc1..f584c4cabcc9 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts +++ b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts @@ -47,7 +47,7 @@ export const useRecordShowPage = ( }); useEffect(() => { - if (record) { + if (isDefined(record)) { setEntityFields(record); } }, [record, setEntityFields]); diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx index 010b9ae28317..824d490d7b6d 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx @@ -6,6 +6,7 @@ import { IconForbid, IconPencil, IconPlus } from 'twenty-ui'; import { v4 } from 'uuid'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem'; import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; @@ -33,6 +34,7 @@ import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; import { FilterQueryParams } from '@/views/hooks/internal/useViewFromQueryParams'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; +import { FieldMetadataType } from '~/generated-metadata/graphql'; type RecordDetailRelationSectionProps = { loading: boolean; @@ -78,7 +80,7 @@ export const RecordDetailRelationSection = ({ const relationRecordIds = relationRecords.map(({ id }) => id); - const dropdownId = `record-field-card-relation-picker-${fieldDefinition.label}`; + const dropdownId = `record-field-card-relation-picker-${fieldDefinition.label}-${entityId}`; const { closeDropdown, isDropdownOpen } = useDropdown(dropdownId); @@ -154,15 +156,32 @@ export const RecordDetailRelationSection = ({ objectNameSingular: relationObjectMetadataNameSingular, }); - const handleOnCreate = async () => { - const newRecordId = v4(); - await createOneRecord({ - id: newRecordId, - }); - setViewableRecordId(newRecordId); - setViewableRecordNameSingular(relationObjectMetadataNameSingular); - openRightDrawer(RightDrawerPages.ViewRecord); - }; + const handleOnCreate = + relationObjectMetadataNameSingular !== 'workspaceMember' + ? async (searchInput?: string) => { + const newRecordId = v4(); + const labelIdentifierType = getLabelIdentifierFieldMetadataItem( + relationObjectMetadataItem, + )?.type; + const createRecordPayload: { + id: string; + name: string | { firstName: string | undefined }; + [key: string]: any; + } = + labelIdentifierType === FieldMetadataType.FullName + ? { id: newRecordId, name: { firstName: searchInput } } + : { id: newRecordId, name: searchInput ?? '' }; + + createRecordPayload[ + `${relationFieldMetadataItem?.relationDefinition?.sourceFieldMetadata.name}Id` + ] = entityId; + console.log(createRecordPayload); + await createOneRecord(createRecordPayload); + setViewableRecordId(newRecordId); + setViewableRecordNameSingular(relationObjectMetadataNameSingular); + openRightDrawer(RightDrawerPages.ViewRecord); + } + : undefined; return ( diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch.tsx index 256b5bc9b07b..1fd9118244f4 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch.tsx @@ -15,7 +15,7 @@ import { useEntitySelectSearch } from '../hooks/useEntitySelectSearch'; export type SingleEntitySelectMenuItemsWithSearchProps = { excludedRelationRecordIds?: string[]; - onCreate?: () => void; + onCreate?: ((searchInput?: string) => void) | (() => void); relationObjectNameSingular: string; relationPickerScopeId?: string; selectedRelationRecordIds: string[]; @@ -71,6 +71,18 @@ export const SingleEntitySelectMenuItemsWithSearch = ({ objectNameSingular: relationObjectNameSingular, }); + const onCreateWithInput = isDefined(onCreate) + ? () => { + if (onCreate.length > 0) { + (onCreate as (searchInput?: string) => void)( + relationPickerSearchFilter, + ); + } else { + (onCreate as () => void)(); + } + } + : undefined; + return ( <> Date: Fri, 31 May 2024 08:18:58 +0200 Subject: [PATCH 15/30] Fix tabs issue --- .../record-show/components/RecordShowContainer.tsx | 2 +- .../components/RecordDetailRelationSection.tsx | 1 - .../components/ShowPageRightContainer.tsx | 14 ++++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx index 644a9dc630cb..828fa028a1cc 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainer.tsx @@ -255,7 +255,7 @@ export const RecordShowContainer = ({ tasks notes emails - forceMobile={isInRightDrawer} + isRightDrawer={isInRightDrawer} summary={summary} loading={isPrefetchLoading || loading || recordLoading} /> diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx index 824d490d7b6d..ae87a29c48bd 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx @@ -175,7 +175,6 @@ export const RecordDetailRelationSection = ({ createRecordPayload[ `${relationFieldMetadataItem?.relationDefinition?.sourceFieldMetadata.name}Id` ] = entityId; - console.log(createRecordPayload); await createOneRecord(createRecordPayload); setViewableRecordId(newRecordId); setViewableRecordNameSingular(relationObjectMetadataNameSingular); diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx index c6a4d6feb08f..3b3c2deb2958 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx @@ -54,7 +54,7 @@ type ShowPageRightContainerProps = { notes?: boolean; emails?: boolean; summary?: JSX.Element; - forceMobile?: boolean; + isRightDrawer?: boolean; loading: boolean; }; @@ -66,9 +66,11 @@ export const ShowPageRightContainer = ({ emails, loading, summary, - forceMobile = false, + isRightDrawer = false, }: ShowPageRightContainerProps) => { - const { activeTabIdState } = useTabList(TAB_LIST_COMPONENT_ID); + const { activeTabIdState } = useTabList( + TAB_LIST_COMPONENT_ID + isRightDrawer, + ); const activeTabId = useRecoilValue(activeTabIdState); const shouldDisplayCalendarTab = @@ -84,7 +86,7 @@ export const ShowPageRightContainer = ({ CoreObjectNameSingular.Company) || targetableObject.targetObjectNameSingular === CoreObjectNameSingular.Person; - const isMobile = useIsMobile() || forceMobile; + const isMobile = useIsMobile() || isRightDrawer; const TASK_TABS = [ { @@ -97,7 +99,7 @@ export const ShowPageRightContainer = ({ id: 'timeline', title: 'Timeline', Icon: IconTimelineEvent, - hide: !timeline, + hide: !timeline || isRightDrawer, }, { id: 'tasks', @@ -143,7 +145,7 @@ export const ShowPageRightContainer = ({ From 02899688366e47981fba25fa70074e6f4c3d230d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Fri, 31 May 2024 08:25:45 +0200 Subject: [PATCH 16/30] Smarter firstname/lastname split --- .../components/RecordDetailRelationSection.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx index ae87a29c48bd..dc487c1d3df5 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx @@ -165,11 +165,22 @@ export const RecordDetailRelationSection = ({ )?.type; const createRecordPayload: { id: string; - name: string | { firstName: string | undefined }; + name: + | string + | { firstName: string | undefined; lastName: string | undefined }; [key: string]: any; } = labelIdentifierType === FieldMetadataType.FullName - ? { id: newRecordId, name: { firstName: searchInput } } + ? { + id: newRecordId, + name: + searchInput && searchInput.split(' ').length > 1 + ? { + firstName: searchInput.split(' ')[0], + lastName: searchInput.split(' ').slice(1).join(' '), + } + : { firstName: searchInput, lastName: '' }, + } : { id: newRecordId, name: searchInput ?? '' }; createRecordPayload[ From ccf60c05d31aa10073f84eeb4a3ab0bbae6307cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Fri, 31 May 2024 14:50:30 +0200 Subject: [PATCH 17/30] Add ability to add relation from list view --- .../RecordDetailRelationSection.tsx | 61 ++------------- .../components/RelationPicker.tsx | 21 +++++ .../hooks/useAddNewRecordAnOpenPanel.ts | 78 +++++++++++++++++++ 3 files changed, 106 insertions(+), 54 deletions(-) create mode 100644 packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAnOpenPanel.ts diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx index dc487c1d3df5..d1f6d704b8fc 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx @@ -1,19 +1,14 @@ import { useCallback, useContext } from 'react'; import styled from '@emotion/styled'; import qs from 'qs'; -import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { useRecoilValue } from 'recoil'; import { IconForbid, IconPencil, IconPlus } from 'twenty-ui'; -import { v4 } from 'uuid'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; -import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem'; -import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; import { usePersistField } from '@/object-record/record-field/hooks/usePersistField'; import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata'; -import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; -import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState'; import { RecordDetailRelationRecordsList } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsList'; import { RecordDetailRelationRecordsListEmptyState } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationRecordsListEmptyState'; import { RecordDetailRelationSectionSkeletonLoader } from '@/object-record/record-show/record-detail-section/components/RecordDetailRelationSectionSkeletonLoader'; @@ -22,6 +17,7 @@ import { RecordDetailSectionHeader } from '@/object-record/record-show/record-de import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; import { SingleEntitySelectMenuItemsWithSearch } from '@/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch'; +import { useAddNewRecordAnOpenPanel } from '@/object-record/relation-picker/hooks/useAddNewRecordAnOpenPanel'; import { useRelationPicker } from '@/object-record/relation-picker/hooks/useRelationPicker'; import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope'; import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; @@ -30,11 +26,8 @@ import { LightIconButton } from '@/ui/input/button/components/LightIconButton'; import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown'; import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown'; import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope'; -import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; -import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; import { FilterQueryParams } from '@/views/hooks/internal/useViewFromQueryParams'; import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; -import { FieldMetadataType } from '~/generated-metadata/graphql'; type RecordDetailRelationSectionProps = { loading: boolean; @@ -146,53 +139,13 @@ export const RecordDetailRelationSection = ({ ); }; - const { openRightDrawer } = useRightDrawer(); - const setViewableRecordId = useSetRecoilState(viewableRecordIdState); - const setViewableRecordNameSingular = useSetRecoilState( - viewableRecordNameSingularState, - ); - - const { createOneRecord } = useCreateOneRecord({ - objectNameSingular: relationObjectMetadataNameSingular, + const { handleOnCreate } = useAddNewRecordAnOpenPanel({ + relationObjectMetadataNameSingular, + relationObjectMetadataItem, + relationFieldMetadataItem, + entityId, }); - const handleOnCreate = - relationObjectMetadataNameSingular !== 'workspaceMember' - ? async (searchInput?: string) => { - const newRecordId = v4(); - const labelIdentifierType = getLabelIdentifierFieldMetadataItem( - relationObjectMetadataItem, - )?.type; - const createRecordPayload: { - id: string; - name: - | string - | { firstName: string | undefined; lastName: string | undefined }; - [key: string]: any; - } = - labelIdentifierType === FieldMetadataType.FullName - ? { - id: newRecordId, - name: - searchInput && searchInput.split(' ').length > 1 - ? { - firstName: searchInput.split(' ')[0], - lastName: searchInput.split(' ').slice(1).join(' '), - } - : { firstName: searchInput, lastName: '' }, - } - : { id: newRecordId, name: searchInput ?? '' }; - - createRecordPayload[ - `${relationFieldMetadataItem?.relationDefinition?.sourceFieldMetadata.name}Id` - ] = entityId; - await createOneRecord(createRecordPayload); - setViewableRecordId(newRecordId); - setViewableRecordNameSingular(relationObjectMetadataNameSingular); - openRightDrawer(RightDrawerPages.ViewRecord); - } - : undefined; - return ( onSubmit(selectedEntity ?? null); + const { objectMetadataItem: relationObjectMetadataItem } = + useObjectMetadataItem({ + objectNameSingular: + fieldDefinition.metadata.relationObjectMetadataNameSingular, + }); + + const relationFieldMetadataItem = relationObjectMetadataItem.fields.find( + ({ id }) => id === fieldDefinition.metadata.relationFieldMetadataId, + ); + + const { handleOnCreate } = useAddNewRecordAnOpenPanel({ + relationObjectMetadataNameSingular: + fieldDefinition.metadata.relationObjectMetadataNameSingular, + relationObjectMetadataItem, + relationFieldMetadataItem, + entityId: recordId, + }); + return ( { + const setViewableRecordId = useSetRecoilState(viewableRecordIdState); + const setViewableRecordNameSingular = useSetRecoilState( + viewableRecordNameSingularState, + ); + + const { createOneRecord } = useCreateOneRecord({ + objectNameSingular: relationObjectMetadataNameSingular, + }); + + const { openRightDrawer } = useRightDrawer(); + + const handleOnCreate = + relationObjectMetadataNameSingular !== 'workspaceMember' + ? async (searchInput?: string) => { + const newRecordId = v4(); + const labelIdentifierType = getLabelIdentifierFieldMetadataItem( + relationObjectMetadataItem, + )?.type; + const createRecordPayload: { + id: string; + name: + | string + | { firstName: string | undefined; lastName: string | undefined }; + [key: string]: any; + } = + labelIdentifierType === FieldMetadataType.FullName + ? { + id: newRecordId, + name: + searchInput && searchInput.split(' ').length > 1 + ? { + firstName: searchInput.split(' ')[0], + lastName: searchInput.split(' ').slice(1).join(' '), + } + : { firstName: searchInput, lastName: '' }, + } + : { id: newRecordId, name: searchInput ?? '' }; + + if (isDefined(entityId)) { + createRecordPayload[ + `${relationFieldMetadataItem?.relationDefinition?.sourceFieldMetadata.name}Id` + ] = entityId; + } + await createOneRecord(createRecordPayload); + setViewableRecordId(newRecordId); + setViewableRecordNameSingular(relationObjectMetadataNameSingular); + openRightDrawer(RightDrawerPages.ViewRecord); + } + : undefined; + + return { handleOnCreate }; +}; From 0efd78efe66cd0025ecc746a5d71eacd91081e71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Fri, 31 May 2024 15:16:59 +0200 Subject: [PATCH 18/30] Fix scroll --- .../components/ShowPageLeftContainer.tsx | 28 +++++++++---------- .../components/ShowPageRightContainer.tsx | 6 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx index 721ba74c5ac9..402bc97dcd2c 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageLeftContainer.tsx @@ -39,21 +39,21 @@ export const ShowPageLeftContainer = ({ children, }: ShowPageLeftContainerProps) => { const isMobile = useIsMobile() || forceMobile; - return isMobile || forceMobile ? ( + return ( - - {children} - - - ) : ( - - - - - {children} - - - + {isMobile ? ( + + {children} + + ) : ( + + + + {children} + + + + )} ); }; diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx index 3b3c2deb2958..1a4c51e441d4 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx @@ -24,12 +24,12 @@ import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; -const StyledShowPageRightContainer = styled.div` +const StyledShowPageRightContainer = styled.div<{ isMobile: boolean }>` display: flex; flex: 1 0 0; flex-direction: column; justify-content: start; - overflow: ${() => (useIsMobile() ? 'none' : 'hidden')}; + overflow: ${(isMobile) => (isMobile ? 'none' : 'hidden')}; width: calc(100% + 4px); `; @@ -141,7 +141,7 @@ export const ShowPageRightContainer = ({ ]; return ( - + Date: Fri, 31 May 2024 15:50:58 +0200 Subject: [PATCH 19/30] Fix strange relation on picker (although fix isn't that great either) --- .../components/SingleEntitySelectMenuItemsWithSearch.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch.tsx index 1fd9118244f4..6cc7b726aec9 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch.tsx @@ -93,7 +93,12 @@ export const SingleEntitySelectMenuItemsWithSearch = ({ Date: Fri, 31 May 2024 15:55:20 +0200 Subject: [PATCH 20/30] Disable right drawer access from list --- .../components/RecordTableCellSoftFocusMode.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx index fe504a109e75..f653eb51d352 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx @@ -1,5 +1,5 @@ import { ReactElement, useContext, useEffect, useRef } from 'react'; -import { IconLayoutSidebarRightExpand } from '@tabler/icons-react'; +import { IconArrowUpRight } from '@tabler/icons-react'; import { useRecoilValue } from 'recoil'; import { Key } from 'ts-key-enum'; @@ -118,15 +118,19 @@ export const RecordTableCellSoftFocusMode = ({ }; const handleButtonClick = () => { + handleClick(); + /* + Disabling sidepanel access for now, TODO: launch if (!isFieldInputOnly) { openTableCell(undefined, true); } + */ }; const isFirstColumn = columnIndex === 0; const customButtonIcon = useGetButtonIcon(); const buttonIcon = isFirstColumn - ? IconLayoutSidebarRightExpand + ? IconArrowUpRight // IconLayoutSidebarRightExpand - Disabling sidepanel access for now : customButtonIcon; const showButton = From 6b67ade614198fe163c31e51e2724c9a94d02337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Fri, 31 May 2024 17:19:05 +0200 Subject: [PATCH 21/30] Improve relation creation --- .../RecordTableCellSoftFocusMode.tsx | 2 +- .../hooks/useOpenRecordTableCellV2.ts | 2 -- .../components/RelationPicker.tsx | 7 ++-- .../hooks/useAddNewRecordAnOpenPanel.ts | 36 ++++++++++++++++--- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx index f653eb51d352..567c70853716 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellSoftFocusMode.tsx @@ -1,7 +1,7 @@ import { ReactElement, useContext, useEffect, useRef } from 'react'; -import { IconArrowUpRight } from '@tabler/icons-react'; import { useRecoilValue } from 'recoil'; import { Key } from 'ts-key-enum'; +import { IconArrowUpRight } from 'twenty-ui'; import { useClearField } from '@/object-record/record-field/hooks/useClearField'; import { useGetButtonIcon } from '@/object-record/record-field/hooks/useGetButtonIcon'; diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts index a96668841adc..b9e279b0b77a 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCellV2.ts @@ -66,8 +66,6 @@ export const useOpenRecordTableCellV2 = (tableScopeId: string) => { initialValue, cellPosition, isReadOnly, - // temporary, while refactoring - // eslint-disable-next-line unused-imports/no-unused-vars pathToShowPage, objectNameSingular, customCellHotkeyScope, diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx index 5e7199bb462a..85bffc0c7392 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx @@ -1,7 +1,8 @@ -import { useEffect } from 'react'; +import { useContext, useEffect } from 'react'; import { IconForbid } from 'twenty-ui'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { FieldContext } from '@/object-record/record-field/contexts/FieldContext'; import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition'; import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { SingleEntitySelect } from '@/object-record/relation-picker/components/SingleEntitySelect'; @@ -51,12 +52,14 @@ export const RelationPicker = ({ ({ id }) => id === fieldDefinition.metadata.relationFieldMetadataId, ); + const { entityId } = useContext(FieldContext); + const { handleOnCreate } = useAddNewRecordAnOpenPanel({ relationObjectMetadataNameSingular: fieldDefinition.metadata.relationObjectMetadataNameSingular, relationObjectMetadataItem, relationFieldMetadataItem, - entityId: recordId, + entityId, }); return ( diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAnOpenPanel.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAnOpenPanel.ts index 88f5753e04f3..a99e1598dcf4 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAnOpenPanel.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAnOpenPanel.ts @@ -5,18 +5,21 @@ import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem'; import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; +import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState'; import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; -import { FieldMetadataType } from '~/generated-metadata/graphql'; -import { isDefined } from '~/utils/isDefined'; +import { + FieldMetadataType, + RelationDefinitionType, +} from '~/generated-metadata/graphql'; type RecordDetailRelationSectionProps = { relationObjectMetadataNameSingular: string; relationObjectMetadataItem: ObjectMetadataItem; relationFieldMetadataItem?: FieldMetadataItem; - entityId?: string; + entityId: string; }; export const useAddNewRecordAnOpenPanel = ({ relationObjectMetadataNameSingular, @@ -32,6 +35,11 @@ export const useAddNewRecordAnOpenPanel = ({ const { createOneRecord } = useCreateOneRecord({ objectNameSingular: relationObjectMetadataNameSingular, }); + const { updateOneRecord } = useUpdateOneRecord({ + objectNameSingular: + relationFieldMetadataItem?.relationDefinition?.targetObjectMetadata + .nameSingular ?? '', + }); const { openRightDrawer } = useRightDrawer(); @@ -62,12 +70,30 @@ export const useAddNewRecordAnOpenPanel = ({ } : { id: newRecordId, name: searchInput ?? '' }; - if (isDefined(entityId)) { + if ( + relationFieldMetadataItem?.relationDefinition?.direction === + RelationDefinitionType.ManyToOne + ) { createRecordPayload[ - `${relationFieldMetadataItem?.relationDefinition?.sourceFieldMetadata.name}Id` + `${relationFieldMetadataItem?.relationDefinition?.targetFieldMetadata.name}Id` ] = entityId; } + await createOneRecord(createRecordPayload); + + if ( + relationFieldMetadataItem?.relationDefinition?.direction === + RelationDefinitionType.OneToMany + ) { + updateOneRecord({ + idToUpdate: entityId, + updateOneRecordInput: { + [`${relationFieldMetadataItem?.relationDefinition?.targetFieldMetadata.name}Id`]: + newRecordId, + }, + }); + } + setViewableRecordId(newRecordId); setViewableRecordNameSingular(relationObjectMetadataNameSingular); openRightDrawer(RightDrawerPages.ViewRecord); From 8674e614f79bc9848cbe69dbc24262f5e0e9b51f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Fri, 31 May 2024 17:29:05 +0200 Subject: [PATCH 22/30] Rename panel to right drawer --- .../components/RecordDetailRelationSection.tsx | 4 ++-- .../relation-picker/components/RelationPicker.tsx | 4 ++-- ...ordAnOpenPanel.ts => useAddNewRecordAndOpenRightDrawer.ts} | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) rename packages/twenty-front/src/modules/object-record/relation-picker/hooks/{useAddNewRecordAnOpenPanel.ts => useAddNewRecordAndOpenRightDrawer.ts} (97%) diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx index d1f6d704b8fc..6e6b02d1ac5b 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx @@ -17,7 +17,7 @@ import { RecordDetailSectionHeader } from '@/object-record/record-show/record-de import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector'; import { SingleEntitySelectMenuItemsWithSearch } from '@/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch'; -import { useAddNewRecordAnOpenPanel } from '@/object-record/relation-picker/hooks/useAddNewRecordAnOpenPanel'; +import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer'; import { useRelationPicker } from '@/object-record/relation-picker/hooks/useRelationPicker'; import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope'; import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; @@ -139,7 +139,7 @@ export const RecordDetailRelationSection = ({ ); }; - const { handleOnCreate } = useAddNewRecordAnOpenPanel({ + const { handleOnCreate } = useAddNewRecordAndOpenRightDrawer({ relationObjectMetadataNameSingular, relationObjectMetadataItem, relationFieldMetadataItem, diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx index 85bffc0c7392..98ebc115e987 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx @@ -6,7 +6,7 @@ import { FieldContext } from '@/object-record/record-field/contexts/FieldContext import { FieldDefinition } from '@/object-record/record-field/types/FieldDefinition'; import { FieldRelationMetadata } from '@/object-record/record-field/types/FieldMetadata'; import { SingleEntitySelect } from '@/object-record/relation-picker/components/SingleEntitySelect'; -import { useAddNewRecordAnOpenPanel } from '@/object-record/relation-picker/hooks/useAddNewRecordAnOpenPanel'; +import { useAddNewRecordAndOpenRightDrawer } from '@/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer'; import { useRelationPicker } from '@/object-record/relation-picker/hooks/useRelationPicker'; import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect'; @@ -54,7 +54,7 @@ export const RelationPicker = ({ const { entityId } = useContext(FieldContext); - const { handleOnCreate } = useAddNewRecordAnOpenPanel({ + const { handleOnCreate } = useAddNewRecordAndOpenRightDrawer({ relationObjectMetadataNameSingular: fieldDefinition.metadata.relationObjectMetadataNameSingular, relationObjectMetadataItem, diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAnOpenPanel.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts similarity index 97% rename from packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAnOpenPanel.ts rename to packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts index a99e1598dcf4..2afb9fad5622 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAnOpenPanel.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts @@ -21,7 +21,7 @@ type RecordDetailRelationSectionProps = { relationFieldMetadataItem?: FieldMetadataItem; entityId: string; }; -export const useAddNewRecordAnOpenPanel = ({ +export const useAddNewRecordAndOpenRightDrawer = ({ relationObjectMetadataNameSingular, relationObjectMetadataItem, relationFieldMetadataItem, @@ -85,7 +85,7 @@ export const useAddNewRecordAnOpenPanel = ({ relationFieldMetadataItem?.relationDefinition?.direction === RelationDefinitionType.OneToMany ) { - updateOneRecord({ + await updateOneRecord({ idToUpdate: entityId, updateOneRecordInput: { [`${relationFieldMetadataItem?.relationDefinition?.targetFieldMetadata.name}Id`]: From 505923920ec622ac38cc547ddf2c1c04cd642a0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Mon, 3 Jun 2024 11:37:33 +0200 Subject: [PATCH 23/30] Always show add new --- .../relation-picker/components/SingleEntitySelectMenuItems.tsx | 2 +- .../components/SingleEntitySelectMenuItemsWithSearch.tsx | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItems.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItems.tsx index 3ede46b1dfe6..f6bc76d9282e 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItems.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/SingleEntitySelectMenuItems.tsx @@ -122,7 +122,7 @@ export const SingleEntitySelectMenuItems = ({ selectedEntity={selectedEntity} /> ))} - {showCreateButton && !loading && ( + {showCreateButton && ( <> {entitiesToSelect.length > 0 && } Date: Mon, 3 Jun 2024 12:20:35 +0200 Subject: [PATCH 24/30] Code style updates --- .../hooks/useOpenCalendarEventRightDrawer.ts | 4 +- .../comment/__stories__/Comment.stories.tsx | 6 +- .../__stories__/CommentHeader.stories.tsx | 6 +- .../hooks/useOpenCreateActivityDrawer.ts | 4 +- .../components/RelationPicker.tsx | 15 +-- .../SingleEntitySelectMenuItemsWithSearch.tsx | 22 ++-- .../useAddNewRecordAndOpenRightDrawer.ts | 109 +++++++++--------- .../RightDrawerTopBarExpandButton.tsx | 6 +- 8 files changed, 91 insertions(+), 81 deletions(-) diff --git a/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer.ts b/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer.ts index b8e275f85196..b10743f3533c 100644 --- a/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer.ts +++ b/packages/twenty-front/src/modules/activities/calendar/right-drawer/hooks/useOpenCalendarEventRightDrawer.ts @@ -9,12 +9,12 @@ import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope export const useOpenCalendarEventRightDrawer = () => { const { openRightDrawer } = useRightDrawer(); const setHotkeyScope = useSetHotkeyScope(); - const setViewableCalendarEventId = useSetRecoilState(viewableRecordIdState); + const setViewableRecordId = useSetRecoilState(viewableRecordIdState); const openCalendarEventRightDrawer = (calendarEventId: string) => { setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false }); openRightDrawer(RightDrawerPages.ViewCalendarEvent); - setViewableCalendarEventId(calendarEventId); + setViewableRecordId(calendarEventId); }; return { openCalendarEventRightDrawer }; 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 15677354ba6e..8df2da80928a 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 @@ -11,11 +11,11 @@ import { Comment } from '../Comment'; import { mockComment, mockCommentWithLongValues } from './mock-comment'; const CommentSetterEffect = () => { - const setViewableActivity = useSetRecoilState(viewableRecordIdState); + const setViewableRecord = useSetRecoilState(viewableRecordIdState); useEffect(() => { - setViewableActivity('test-id'); - }, [setViewableActivity]); + setViewableRecord('test-id'); + }, [setViewableRecord]); return null; }; 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 a5cbe53275f8..25c01d745c0b 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 @@ -13,11 +13,11 @@ import { CommentHeader } from '../CommentHeader'; import { mockComment, mockCommentWithLongValues } from './mock-comment'; const CommentHeaderSetterEffect = () => { - const setViewableActivity = useSetRecoilState(viewableRecordIdState); + const setViewableRecord = useSetRecoilState(viewableRecordIdState); useEffect(() => { - setViewableActivity('test-id'); - }, [setViewableActivity]); + setViewableRecord('test-id'); + }, [setViewableRecord]); return null; }; diff --git a/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts b/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts index 88952baede3a..d85646096a94 100644 --- a/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts +++ b/packages/twenty-front/src/modules/activities/hooks/useOpenCreateActivityDrawer.ts @@ -26,7 +26,7 @@ export const useOpenCreateActivityDrawer = () => { const setActivityTargetableEntityArray = useSetRecoilState( activityTargetableEntityArrayState, ); - const setViewableActivityId = useSetRecoilState(viewableRecordIdState); + const setViewableRecordId = useSetRecoilState(viewableRecordIdState); const setIsCreatingActivity = useSetRecoilState(isActivityInCreateModeState); @@ -59,7 +59,7 @@ export const useOpenCreateActivityDrawer = () => { setTemporaryActivityForEditor(createdActivityInCache); setIsCreatingActivity(true); setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false }); - setViewableActivityId(createdActivityInCache.id); + setViewableRecordId(createdActivityInCache.id); setActivityTargetableEntityArray(targetableObjects ?? []); openRightDrawer(RightDrawerPages.CreateActivity); setIsUpsertingActivityInDB(false); diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx index 98ebc115e987..08ce2d760e0b 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx @@ -54,13 +54,14 @@ export const RelationPicker = ({ const { entityId } = useContext(FieldContext); - const { handleOnCreate } = useAddNewRecordAndOpenRightDrawer({ - relationObjectMetadataNameSingular: - fieldDefinition.metadata.relationObjectMetadataNameSingular, - relationObjectMetadataItem, - relationFieldMetadataItem, - entityId, - }); + const { createNewRecordAndOpenRightDrawer: handleOnCreate } = + useAddNewRecordAndOpenRightDrawer({ + relationObjectMetadataNameSingular: + fieldDefinition.metadata.relationObjectMetadataNameSingular, + relationObjectMetadataItem, + relationFieldMetadataItem, + entityId, + }); return ( { - if (onCreate.length > 0) { - (onCreate as (searchInput?: string) => void)( - relationPickerSearchFilter, - ); - } else { - (onCreate as () => void)(); - } + let onCreateWithInput = undefined; + + if (isDefined(onCreate)) { + onCreateWithInput = () => { + if (onCreate.length > 0) { + (onCreate as (searchInput?: string) => void)( + relationPickerSearchFilter, + ); + } else { + (onCreate as () => void)(); } - : undefined; + }; + } return ( <> diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts index 2afb9fad5622..e413dbc72ea4 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts @@ -43,62 +43,65 @@ export const useAddNewRecordAndOpenRightDrawer = ({ const { openRightDrawer } = useRightDrawer(); - const handleOnCreate = - relationObjectMetadataNameSingular !== 'workspaceMember' - ? async (searchInput?: string) => { - const newRecordId = v4(); - const labelIdentifierType = getLabelIdentifierFieldMetadataItem( - relationObjectMetadataItem, - )?.type; - const createRecordPayload: { - id: string; - name: - | string - | { firstName: string | undefined; lastName: string | undefined }; - [key: string]: any; - } = - labelIdentifierType === FieldMetadataType.FullName - ? { - id: newRecordId, - name: - searchInput && searchInput.split(' ').length > 1 - ? { - firstName: searchInput.split(' ')[0], - lastName: searchInput.split(' ').slice(1).join(' '), - } - : { firstName: searchInput, lastName: '' }, - } - : { id: newRecordId, name: searchInput ?? '' }; + if (relationObjectMetadataNameSingular === 'workspaceMember') { + return { + createNewRecordAndOpenRightDrawer: undefined, + }; + } - if ( - relationFieldMetadataItem?.relationDefinition?.direction === - RelationDefinitionType.ManyToOne - ) { - createRecordPayload[ - `${relationFieldMetadataItem?.relationDefinition?.targetFieldMetadata.name}Id` - ] = entityId; - } + return { + createNewRecordAndOpenRightDrawer: async (searchInput?: string) => { + const newRecordId = v4(); + const labelIdentifierType = getLabelIdentifierFieldMetadataItem( + relationObjectMetadataItem, + )?.type; + const createRecordPayload: { + id: string; + name: + | string + | { firstName: string | undefined; lastName: string | undefined }; + [key: string]: any; + } = + labelIdentifierType === FieldMetadataType.FullName + ? { + id: newRecordId, + name: + searchInput && searchInput.split(' ').length > 1 + ? { + firstName: searchInput.split(' ')[0], + lastName: searchInput.split(' ').slice(1).join(' '), + } + : { firstName: searchInput, lastName: '' }, + } + : { id: newRecordId, name: searchInput ?? '' }; - await createOneRecord(createRecordPayload); + if ( + relationFieldMetadataItem?.relationDefinition?.direction === + RelationDefinitionType.ManyToOne + ) { + createRecordPayload[ + `${relationFieldMetadataItem?.relationDefinition?.targetFieldMetadata.name}Id` + ] = entityId; + } - if ( - relationFieldMetadataItem?.relationDefinition?.direction === - RelationDefinitionType.OneToMany - ) { - await updateOneRecord({ - idToUpdate: entityId, - updateOneRecordInput: { - [`${relationFieldMetadataItem?.relationDefinition?.targetFieldMetadata.name}Id`]: - newRecordId, - }, - }); - } + await createOneRecord(createRecordPayload); - setViewableRecordId(newRecordId); - setViewableRecordNameSingular(relationObjectMetadataNameSingular); - openRightDrawer(RightDrawerPages.ViewRecord); - } - : undefined; + if ( + relationFieldMetadataItem?.relationDefinition?.direction === + RelationDefinitionType.OneToMany + ) { + await updateOneRecord({ + idToUpdate: entityId, + updateOneRecordInput: { + [`${relationFieldMetadataItem?.relationDefinition?.targetFieldMetadata.name}Id`]: + newRecordId, + }, + }); + } - return { handleOnCreate }; + setViewableRecordId(newRecordId); + setViewableRecordNameSingular(relationObjectMetadataNameSingular); + openRightDrawer(RightDrawerPages.ViewRecord); + }, + }; }; diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarExpandButton.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarExpandButton.tsx index c2c07ee47d17..8e4942b99e17 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarExpandButton.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawerTopBarExpandButton.tsx @@ -11,7 +11,11 @@ export const RightDrawerTopBarExpandButton = () => { useRightDrawer(); const handleButtonClick = () => { - isRightDrawerExpanded ? downsizeRightDrawer() : expandRightDrawer(); + if (isRightDrawerExpanded === true) { + downsizeRightDrawer(); + return; + } + expandRightDrawer(); }; return ( From 51b5c92117e0340d7c8c10b3e466ae145d193d53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Mon, 3 Jun 2024 14:33:25 +0200 Subject: [PATCH 25/30] Typo --- .../components/RecordDetailRelationSection.tsx | 15 ++++++++------- .../relation-picker/components/RelationPicker.tsx | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx index 6e6b02d1ac5b..0ce3ef74b026 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx +++ b/packages/twenty-front/src/modules/object-record/record-show/record-detail-section/components/RecordDetailRelationSection.tsx @@ -139,12 +139,13 @@ export const RecordDetailRelationSection = ({ ); }; - const { handleOnCreate } = useAddNewRecordAndOpenRightDrawer({ - relationObjectMetadataNameSingular, - relationObjectMetadataItem, - relationFieldMetadataItem, - entityId, - }); + const { createNewRecordAndOpenRightDrawer } = + useAddNewRecordAndOpenRightDrawer({ + relationObjectMetadataNameSingular, + relationObjectMetadataItem, + relationFieldMetadataItem, + entityId, + }); return ( @@ -182,7 +183,7 @@ export const RecordDetailRelationSection = ({ relationObjectMetadataNameSingular } relationPickerScopeId={dropdownId} - onCreate={handleOnCreate} + onCreate={createNewRecordAndOpenRightDrawer} /> } diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx b/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx index 08ce2d760e0b..18da2c62b7ec 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx +++ b/packages/twenty-front/src/modules/object-record/relation-picker/components/RelationPicker.tsx @@ -54,7 +54,7 @@ export const RelationPicker = ({ const { entityId } = useContext(FieldContext); - const { createNewRecordAndOpenRightDrawer: handleOnCreate } = + const { createNewRecordAndOpenRightDrawer } = useAddNewRecordAndOpenRightDrawer({ relationObjectMetadataNameSingular: fieldDefinition.metadata.relationObjectMetadataNameSingular, @@ -68,7 +68,7 @@ export const RelationPicker = ({ EmptyIcon={IconForbid} emptyLabel={'No ' + fieldDefinition.label} onCancel={onCancel} - onCreate={handleOnCreate} + onCreate={createNewRecordAndOpenRightDrawer} onEntitySelected={handleEntitySelected} width={width} relationObjectNameSingular={ From 1b210a26a4ed49a686c4f6237e3a6c7573f213e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Mon, 3 Jun 2024 14:43:06 +0200 Subject: [PATCH 26/30] Fix drawer transition glitch --- .../ui/layout/right-drawer/components/RightDrawer.tsx | 8 +++++++- .../ui/layout/right-drawer/hooks/useRightDrawer.ts | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx index 38e8ca48526d..0fc54fbdaf37 100644 --- a/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/right-drawer/components/RightDrawer.tsx @@ -135,7 +135,13 @@ export const RightDrawer = () => { return ( { const maximizeRightDrawer = useRecoilCallback( ({ set }) => () => { + set(isRightDrawerMinimizedState, false); set(isRightDrawerExpandedState, false); set(isRightDrawerOpenState, true); - set(isRightDrawerMinimizedState, false); }, [], ); From 0b7bd6c619f236a81e72fa26e00eece2d6bd5af0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Mon, 3 Jun 2024 15:14:34 +0200 Subject: [PATCH 27/30] Improve drawer top bar --- .../components/ActivityActionBar.tsx | 36 +------------ .../components/RightDrawerTopBar.tsx | 53 +++++++++++++------ 2 files changed, 39 insertions(+), 50 deletions(-) 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 8588650e5c3b..60cce744e2ee 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,13 @@ import styled from '@emotion/styled'; import { isNonEmptyArray, isNonEmptyString } from '@sniptt/guards'; import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil'; -import { IconPlus, IconTrash } from 'twenty-ui'; +import { IconTrash } from 'twenty-ui'; -import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer'; import { useRefreshShowPageFindManyActivitiesQueries } from '@/activities/hooks/useRefreshShowPageFindManyActivitiesQueries'; import { activityIdInDrawerState } from '@/activities/states/activityIdInDrawerState'; -import { activityTargetableEntityArrayState } from '@/activities/states/activityTargetableEntityArrayState'; import { isActivityInCreateModeState } from '@/activities/states/isActivityInCreateModeState'; import { isUpsertingActivityInDBState } from '@/activities/states/isCreatingActivityInDBState'; import { temporaryActivityForEditorState } from '@/activities/states/temporaryActivityForEditorState'; -import { objectShowPageTargetableObjectState } from '@/activities/timeline/states/objectShowPageTargetableObjectIdState'; import { Activity } from '@/activities/types/Activity'; import { ActivityTarget } from '@/activities/types/ActivityTarget'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; @@ -33,9 +30,6 @@ export const ActivityActionBar = () => { const viewableRecordId = useRecoilValue(viewableRecordIdState); const activityIdInDrawer = useRecoilValue(activityIdInDrawerState); - const activityTargetableEntityArray = useRecoilValue( - activityTargetableEntityArrayState, - ); const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState); const { deleteOneRecord: deleteOneActivity } = useDeleteOneRecord({ objectNameSingular: CoreObjectNameSingular.Activity, @@ -62,15 +56,9 @@ export const ActivityActionBar = () => { isUpsertingActivityInDBState, ); - const objectShowPageTargetableObject = useRecoilValue( - objectShowPageTargetableObjectState, - ); - const { refreshShowPageFindManyActivitiesQueries } = useRefreshShowPageFindManyActivitiesQueries(); - const openCreateActivity = useOpenCreateActivityDrawer(); - const deleteActivity = useRecoilCallback( ({ snapshot }) => async () => { @@ -129,32 +117,10 @@ export const ActivityActionBar = () => { ], ); - const record = useRecoilValue(recordStoreFamilyState(viewableRecordId ?? '')); - - const addActivity = () => { - setIsRightDrawerOpen(false); - if (isDefined(record) && isDefined(objectShowPageTargetableObject)) { - openCreateActivity({ - type: record?.type, - customAssignee: record?.assignee, - targetableObjects: activityTargetableEntityArray, - }); - } - }; - const actionsAreDisabled = isUpsertingActivityInDB; - const isCreateActionDisabled = isActivityInCreateMode; - return ( - { const PageIcon = getIcon(RIGHT_DRAWER_PAGE_ICONS[page]); + const viewableRecordNameSingular = useRecoilValue( + viewableRecordNameSingularState, + ); + + const { objectMetadataItem } = useObjectMetadataItem({ + objectNameSingular: viewableRecordNameSingular ?? 'company', + }); + + const ObjectIcon = getIcon(objectMetadataItem.icon); + + const label = + page === RightDrawerPages.ViewRecord + ? objectMetadataItem.labelSingular + : RIGHT_DRAWER_PAGE_TITLES[page]; + + const Icon = page === RightDrawerPages.ViewRecord ? ObjectIcon : PageIcon; + return ( - {!isRightDrawerMinimized && ( - } - size={ChipSize.Large} - accent={ChipAccent.TextSecondary} - variant={ChipVariant.Highlighted} - /> - )} + {!isRightDrawerMinimized && + (page === RightDrawerPages.EditActivity || + page === RightDrawerPages.CreateActivity) && } + {!isRightDrawerMinimized && + page !== RightDrawerPages.EditActivity && + page !== RightDrawerPages.CreateActivity && ( + } + size={ChipSize.Large} + accent={ChipAccent.TextSecondary} + clickable={false} + /> + )} {isRightDrawerMinimized && ( - + - - {RIGHT_DRAWER_PAGE_TITLES[page]} - + {label} )} From 2aa279569baeb39ff2f81b0e2947dfdf542c0bd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Mon, 3 Jun 2024 16:51:23 +0200 Subject: [PATCH 28/30] Design fix --- .../__stories__/RelationFieldInput.stories.tsx | 1 + .../hooks/useAddNewRecordAndOpenRightDrawer.ts | 10 +++++++++- .../components/StyledRightDrawerTopBar.tsx | 3 ++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationFieldInput.stories.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationFieldInput.stories.tsx index a6fca0e4d1fc..9874373e81fd 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationFieldInput.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/input/components/__stories__/RelationFieldInput.stories.tsx @@ -74,6 +74,7 @@ const RelationFieldInputWithContext = ({ relationObjectMetadataNameSingular: CoreObjectNameSingular.WorkspaceMember, objectMetadataNameSingular: 'person', + relationFieldMetadataId: '20202020-8c37-4163-ba06-1dada334ce3e', }, }} entityId={entityId} diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts index e413dbc72ea4..cfb1b5c2b065 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts @@ -14,6 +14,7 @@ import { FieldMetadataType, RelationDefinitionType, } from '~/generated-metadata/graphql'; +import { isDefined } from '~/utils/isDefined'; type RecordDetailRelationSectionProps = { relationObjectMetadataNameSingular: string; @@ -35,6 +36,7 @@ export const useAddNewRecordAndOpenRightDrawer = ({ const { createOneRecord } = useCreateOneRecord({ objectNameSingular: relationObjectMetadataNameSingular, }); + const { updateOneRecord } = useUpdateOneRecord({ objectNameSingular: relationFieldMetadataItem?.relationDefinition?.targetObjectMetadata @@ -43,7 +45,13 @@ export const useAddNewRecordAndOpenRightDrawer = ({ const { openRightDrawer } = useRightDrawer(); - if (relationObjectMetadataNameSingular === 'workspaceMember') { + if ( + relationObjectMetadataNameSingular === 'workspaceMember' || + !isDefined( + relationFieldMetadataItem?.relationDefinition?.targetObjectMetadata + .nameSingular, + ) + ) { return { createNewRecordAndOpenRightDrawer: undefined, }; 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 index 42ea38969b67..3378e36ddca2 100644 --- 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 @@ -11,7 +11,8 @@ export const StyledRightDrawerTopBar = styled.div<{ flex-direction: row; font-size: ${({ theme }) => theme.font.size.md}; gap: ${({ theme }) => theme.spacing(1)}; - height: 56px; + height: ${({ isRightDrawerMinimized }) => + isRightDrawerMinimized ? '40px' : '56px'}; justify-content: space-between; padding-left: ${({ theme }) => theme.spacing(2)}; From 337a1fc0d1df3ea2c5ee4df6493a15baec4a5f57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Mon, 3 Jun 2024 16:58:22 +0200 Subject: [PATCH 29/30] Quick fix --- .../relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts index cfb1b5c2b065..ab2b9f7b90b8 100644 --- a/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts +++ b/packages/twenty-front/src/modules/object-record/relation-picker/hooks/useAddNewRecordAndOpenRightDrawer.ts @@ -40,7 +40,7 @@ export const useAddNewRecordAndOpenRightDrawer = ({ const { updateOneRecord } = useUpdateOneRecord({ objectNameSingular: relationFieldMetadataItem?.relationDefinition?.targetObjectMetadata - .nameSingular ?? '', + .nameSingular ?? 'workspaceMember', }); const { openRightDrawer } = useRightDrawer(); From 09cd6eda282cbf5cc3a898e9928325b1ada283f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Mon, 3 Jun 2024 17:06:52 +0200 Subject: [PATCH 30/30] Fix a broken typescript validation (unrelated to this PR) --- .../__stories__/perf/RecordTableCell.perf.stories.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx index 73518d41906d..9c0bf8b7ba08 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx @@ -79,6 +79,8 @@ const meta: Meta = { >