diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdState.ts new file mode 100644 index 000000000000..3227e53807df --- /dev/null +++ b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdState.ts @@ -0,0 +1,8 @@ +import { createState } from 'twenty-ui'; + +export const contextStoreCurrentObjectMetadataIdState = createState< + string | null +>({ + key: 'contextStoreCurrentObjectMetadataIdState', + defaultValue: null, +}); diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdState.ts new file mode 100644 index 000000000000..41af1cc1357b --- /dev/null +++ b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdState.ts @@ -0,0 +1,6 @@ +import { createState } from 'twenty-ui'; + +export const contextStoreCurrentViewIdState = createState({ + key: 'contextStoreCurrentViewIdState', + defaultValue: null, +}); diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreTargetedRecordIdsState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreTargetedRecordIdsState.ts new file mode 100644 index 000000000000..df0c3451172c --- /dev/null +++ b/packages/twenty-front/src/modules/context-store/states/contextStoreTargetedRecordIdsState.ts @@ -0,0 +1,6 @@ +import { createState } from 'twenty-ui'; + +export const contextStoreTargetedRecordIdsState = createState({ + key: 'contextStoreTargetedRecordIdsState', + defaultValue: [], +}); diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardDataLoaderEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardDataLoaderEffect.tsx index ba3abec91e75..c4ad79ed412f 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardDataLoaderEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardDataLoaderEffect.tsx @@ -2,6 +2,8 @@ import { useCallback, useEffect } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { contextStoreCurrentObjectMetadataIdState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdState'; +import { contextStoreTargetedRecordIdsState } from '@/context-store/states/contextStoreTargetedRecordIdsState'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug'; import { useRecordActionBar } from '@/object-record/record-action-bar/hooks/useRecordActionBar'; @@ -129,10 +131,33 @@ export const RecordIndexBoardDataLoaderEffect = ({ callback: resetRecordSelection, }); + const setContextStoreTargetedRecordIds = useSetRecoilState( + contextStoreTargetedRecordIdsState, + ); + + const setContextStoreCurrentObjectMetadataItem = useSetRecoilState( + contextStoreCurrentObjectMetadataIdState, + ); + useEffect(() => { setActionBarEntries?.(); setContextMenuEntries?.(); }, [setActionBarEntries, setContextMenuEntries]); + useEffect(() => { + setContextStoreTargetedRecordIds(selectedRecordIds); + setContextStoreCurrentObjectMetadataItem(objectMetadataItem?.id); + + return () => { + setContextStoreTargetedRecordIds([]); + setContextStoreCurrentObjectMetadataItem(null); + }; + }, [ + objectMetadataItem?.id, + selectedRecordIds, + setContextStoreCurrentObjectMetadataItem, + setContextStoreTargetedRecordIds, + ]); + return <>; }; diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx index 428537f69467..ce8bb6572d8c 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx @@ -1,6 +1,8 @@ import { useEffect } from 'react'; -import { useRecoilValue } from 'recoil'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { contextStoreCurrentObjectMetadataIdState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdState'; +import { contextStoreTargetedRecordIdsState } from '@/context-store/states/contextStoreTargetedRecordIdsState'; import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useRecordActionBar } from '@/object-record/record-action-bar/hooks/useRecordActionBar'; @@ -34,6 +36,14 @@ export const RecordIndexTableContainerEffect = ({ recordTableId, }); + const setContextStoreTargetedRecordIds = useSetRecoilState( + contextStoreTargetedRecordIdsState, + ); + + const setContextStoreCurrentObjectMetadataItem = useSetRecoilState( + contextStoreCurrentObjectMetadataIdState, + ); + const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular, }); @@ -111,5 +121,20 @@ export const RecordIndexTableContainerEffect = ({ ); }, [setRecordCountInCurrentView, setOnEntityCountChange]); + useEffect(() => { + setContextStoreTargetedRecordIds(selectedRowIds); + setContextStoreCurrentObjectMetadataItem(objectMetadataItem?.id); + + return () => { + setContextStoreTargetedRecordIds([]); + setContextStoreCurrentObjectMetadataItem(null); + }; + }, [ + objectMetadataItem?.id, + selectedRowIds, + setContextStoreCurrentObjectMetadataItem, + setContextStoreTargetedRecordIds, + ]); + return <>; }; diff --git a/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx b/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx index 2ee24d43fdc3..f306f29bd7d5 100644 --- a/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx +++ b/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx @@ -1,3 +1,4 @@ +import { contextStoreCurrentViewIdState } from '@/context-store/states/contextStoreCurrentViewIdState'; import { useLastVisitedObjectMetadataItem } from '@/navigation/hooks/useLastVisitedObjectMetadataItem'; import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; @@ -7,6 +8,7 @@ import { useGetCurrentView } from '@/views/hooks/useGetCurrentView'; import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; import { isUndefined } from '@sniptt/guards'; import { useEffect } from 'react'; +import { useSetRecoilState } from 'recoil'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { isDefined } from '~/utils/isDefined'; @@ -37,6 +39,9 @@ export const QueryParamsViewIdEffect = () => { objectMetadataItemId?.id, lastVisitedObjectMetadataItemId, ); + const setContextStoreCurrentViewId = useSetRecoilState( + contextStoreCurrentViewIdState, + ); // // TODO: scope view bar per view id if possible // const { resetCurrentView } = useResetCurrentView(); @@ -59,6 +64,7 @@ export const QueryParamsViewIdEffect = () => { }); } setCurrentViewId(lastVisitedViewId); + setContextStoreCurrentViewId(lastVisitedViewId); return; } @@ -73,6 +79,7 @@ export const QueryParamsViewIdEffect = () => { }); } setCurrentViewId(viewIdQueryParam); + setContextStoreCurrentViewId(viewIdQueryParam); return; } @@ -87,8 +94,13 @@ export const QueryParamsViewIdEffect = () => { }); } setCurrentViewId(indexView.id); + setContextStoreCurrentViewId(indexView.id); return; } + + return () => { + setContextStoreCurrentViewId(null); + }; }, [ currentViewId, getFiltersFromQueryParams, @@ -96,6 +108,7 @@ export const QueryParamsViewIdEffect = () => { lastVisitedViewId, objectMetadataItemId?.id, objectNamePlural, + setContextStoreCurrentViewId, setCurrentViewId, setLastVisitedObjectMetadataItem, setLastVisitedView, diff --git a/packages/twenty-front/src/modules/views/hooks/useChangeView.ts b/packages/twenty-front/src/modules/views/hooks/useChangeView.ts index 669de5157b1b..9ed9aeeff420 100644 --- a/packages/twenty-front/src/modules/views/hooks/useChangeView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useChangeView.ts @@ -1,19 +1,11 @@ import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates'; -import { useSearchParams } from 'react-router-dom'; +import { useSetViewInUrl } from '@/views/hooks/useSetViewInUrl'; export const useChangeView = (viewBarComponentId?: string) => { const { resetUnsavedViewStates } = useResetUnsavedViewStates(viewBarComponentId); - const [, setSearchParams] = useSearchParams(); - - const setViewInUrl = (viewId: string) => { - setSearchParams(() => { - const searchParams = new URLSearchParams(); - searchParams.set('view', viewId); - return searchParams; - }); - }; + const { setViewInUrl } = useSetViewInUrl(); const changeView = async (viewId: string) => { setViewInUrl(viewId); diff --git a/packages/twenty-front/src/modules/views/hooks/useSetViewInUrl.ts b/packages/twenty-front/src/modules/views/hooks/useSetViewInUrl.ts new file mode 100644 index 000000000000..01e0397ffd6d --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useSetViewInUrl.ts @@ -0,0 +1,15 @@ +import { useSearchParams } from 'react-router-dom'; + +export const useSetViewInUrl = () => { + const [, setSearchParams] = useSearchParams(); + + const setViewInUrl = (viewId: string) => { + setSearchParams(() => { + const searchParams = new URLSearchParams(); + searchParams.set('view', viewId); + return searchParams; + }); + }; + + return { setViewInUrl }; +}; diff --git a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx index 09a3d14b91c2..0ecb2cb569de 100644 --- a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx +++ b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx @@ -12,6 +12,7 @@ import { PageTitle } from '@/ui/utilities/page-title/PageTitle'; import { RecordShowPageWorkflowHeader } from '@/workflow/components/RecordShowPageWorkflowHeader'; import { RecordShowPageWorkflowVersionHeader } from '@/workflow/components/RecordShowPageWorkflowVersionHeader'; import { RecordShowPageBaseHeader } from '~/pages/object-record/RecordShowPageBaseHeader'; +import { RecordShowPageContextStoreEffect } from '~/pages/object-record/RecordShowPageContextStoreEffect'; import { RecordShowPageHeader } from '~/pages/object-record/RecordShowPageHeader'; export const RecordShowPage = () => { @@ -39,6 +40,7 @@ export const RecordShowPage = () => { return ( + { + const setContextStoreTargetedRecordIds = useSetRecoilState( + contextStoreTargetedRecordIdsState, + ); + + const setContextStoreCurrentObjectMetadataId = useSetRecoilState( + contextStoreCurrentObjectMetadataIdState, + ); + + const { objectNameSingular } = useParams(); + + const { objectMetadataItem } = useObjectMetadataItem({ + objectNameSingular: objectNameSingular ?? '', + }); + + useEffect(() => { + setContextStoreTargetedRecordIds([recordId]); + setContextStoreCurrentObjectMetadataId(objectMetadataItem?.id); + + return () => { + setContextStoreTargetedRecordIds([]); + setContextStoreCurrentObjectMetadataId(null); + }; + }, [ + recordId, + setContextStoreTargetedRecordIds, + setContextStoreCurrentObjectMetadataId, + objectMetadataItem?.id, + ]); + + return null; +};