7336 create contextstore (#7374)

Closes #7336

Create 3 states:
- `contextStoreCurrentObjectMetadataIdState`: is set when we change
object metadata
- `contextStoreCurrentViewIdState`: is set when we change view
- `contextStoreTargetedRecordIdsState`: is set when we select records
inside a table or a board or when a show page is opened. Is reset when
we change view.
This commit is contained in:
Raphaël Bosi 2024-10-08 18:40:35 +02:00 committed by GitHub
parent 1863636003
commit a8da0e2bc8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 146 additions and 11 deletions

View File

@ -0,0 +1,8 @@
import { createState } from 'twenty-ui';
export const contextStoreCurrentObjectMetadataIdState = createState<
string | null
>({
key: 'contextStoreCurrentObjectMetadataIdState',
defaultValue: null,
});

View File

@ -0,0 +1,6 @@
import { createState } from 'twenty-ui';
export const contextStoreCurrentViewIdState = createState<string | null>({
key: 'contextStoreCurrentViewIdState',
defaultValue: null,
});

View File

@ -0,0 +1,6 @@
import { createState } from 'twenty-ui';
export const contextStoreTargetedRecordIdsState = createState<string[]>({
key: 'contextStoreTargetedRecordIdsState',
defaultValue: [],
});

View File

@ -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 <></>;
};

View File

@ -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 <></>;
};

View File

@ -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,

View File

@ -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);

View File

@ -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 };
};

View File

@ -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 (
<RecordFieldValueSelectorContextProvider>
<RecordValueSetterEffect recordId={objectRecordId} />
<RecordShowPageContextStoreEffect recordId={objectRecordId} />
<PageContainer>
<PageTitle title={pageTitle} />
<RecordShowPageHeader

View File

@ -0,0 +1,43 @@
import { contextStoreCurrentObjectMetadataIdState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdState';
import { contextStoreTargetedRecordIdsState } from '@/context-store/states/contextStoreTargetedRecordIdsState';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { useSetRecoilState } from 'recoil';
export const RecordShowPageContextStoreEffect = ({
recordId,
}: {
recordId: string;
}) => {
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;
};