Add viewId to recordIndexId (#9647)

Before the `recordIndexId` was the name plural. This caused problems
because the component states were the same for every view of an object.
When we switched from one view to another, some states weren't reset.
This PR fixes this by:
- Creating an effect at the same level of page change effect to set the
`currentViewId` inside the object `contextStore`
- Adding the `currentViewId` to the `recordIndexId`

Follow ups:
- We need to get rid of
`packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts`
and use the context store instead
This commit is contained in:
Raphaël Bosi
2025-01-16 18:41:19 +01:00
committed by GitHub
parent a248e891ae
commit b81ffcc77c
5 changed files with 130 additions and 89 deletions

View File

@ -6,6 +6,7 @@ import { ChromeExtensionSidecarEffect } from '@/chrome-extension-sidecar/compone
import { ChromeExtensionSidecarProvider } from '@/chrome-extension-sidecar/components/ChromeExtensionSidecarProvider';
import { ClientConfigProvider } from '@/client-config/components/ClientConfigProvider';
import { ClientConfigProviderEffect } from '@/client-config/components/ClientConfigProviderEffect';
import { ContextStoreViewIdEffect } from '@/context-store/components/ContextStoreViewIdEffect';
import { PromiseRejectionEffect } from '@/error-handler/components/PromiseRejectionEffect';
import { ApolloMetadataClientProvider } from '@/object-metadata/components/ApolloMetadataClientProvider';
import { ObjectMetadataItemsGater } from '@/object-metadata/components/ObjectMetadataItemsGater';
@ -21,13 +22,15 @@ import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle';
import { UserProvider } from '@/users/components/UserProvider';
import { UserProviderEffect } from '@/users/components/UserProviderEffect';
import { WorkspaceProviderEffect } from '@/workspace/components/WorkspaceProviderEffect';
import { isNonEmptyString } from '@sniptt/guards';
import { StrictMode } from 'react';
import { Outlet, useLocation } from 'react-router-dom';
import { Outlet, useLocation, useParams } from 'react-router-dom';
import { getPageTitleFromPath } from '~/utils/title-utils';
export const AppRouterProviders = () => {
const { pathname } = useLocation();
const pageTitle = getPageTitleFromPath(pathname);
const objectNamePlural = useParams().objectNamePlural;
return (
<ApolloProvider>
@ -61,6 +64,11 @@ export const AppRouterProviders = () => {
</PrefetchDataProvider>
</ObjectMetadataItemsGater>
<PageChangeEffect />
{isNonEmptyString(objectNamePlural) && (
<ContextStoreViewIdEffect
objectNamePlural={objectNamePlural}
/>
)}
</ObjectMetadataItemsProvider>
</ApolloMetadataClientProvider>
</AuthProvider>

View File

@ -0,0 +1,104 @@
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useLastVisitedObjectMetadataItem } from '@/navigation/hooks/useLastVisitedObjectMetadataItem';
import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
import { View } from '@/views/types/View';
import { isUndefined } from '@sniptt/guards';
import { useEffect } from 'react';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { isDefined } from '~/utils/isDefined';
export const ContextStoreViewIdEffect = ({
objectNamePlural,
}: {
objectNamePlural: string;
}) => {
const { viewIdQueryParam } = useViewFromQueryParams();
const { records: viewsOnCurrentObject } = usePrefetchedData<View>(
PrefetchKey.AllViews,
);
const { findObjectMetadataItemByNamePlural } =
useFilteredObjectMetadataItems();
const objectMetadataItemId =
findObjectMetadataItemByNamePlural(objectNamePlural);
const { getLastVisitedViewIdFromObjectNamePlural, setLastVisitedView } =
useLastVisitedView();
const { lastVisitedObjectMetadataItemId, setLastVisitedObjectMetadataItem } =
useLastVisitedObjectMetadataItem();
const lastVisitedViewId =
getLastVisitedViewIdFromObjectNamePlural(objectNamePlural);
const isLastVisitedObjectMetadataItemDifferent = !isDeeplyEqual(
objectMetadataItemId?.id,
lastVisitedObjectMetadataItemId,
);
const setContextStoreCurrentViewId = useSetRecoilComponentStateV2(
contextStoreCurrentViewIdComponentState,
objectNamePlural,
);
useEffect(() => {
const indexView = viewsOnCurrentObject.find((view) => view.key === 'INDEX');
if (isUndefined(viewIdQueryParam) && isDefined(lastVisitedViewId)) {
if (isLastVisitedObjectMetadataItemDifferent) {
setLastVisitedObjectMetadataItem(objectNamePlural);
setLastVisitedView({
objectNamePlural,
viewId: lastVisitedViewId,
});
}
setContextStoreCurrentViewId(lastVisitedViewId);
return;
}
if (isDefined(viewIdQueryParam)) {
if (isLastVisitedObjectMetadataItemDifferent) {
setLastVisitedObjectMetadataItem(objectNamePlural);
}
if (!isDeeplyEqual(viewIdQueryParam, lastVisitedViewId)) {
setLastVisitedView({
objectNamePlural,
viewId: viewIdQueryParam,
});
}
setContextStoreCurrentViewId(viewIdQueryParam);
return;
}
if (isDefined(indexView)) {
if (isLastVisitedObjectMetadataItemDifferent) {
setLastVisitedObjectMetadataItem(objectNamePlural);
}
if (!isDeeplyEqual(indexView.id, lastVisitedViewId)) {
setLastVisitedView({
objectNamePlural,
viewId: indexView.id,
});
}
setContextStoreCurrentViewId(indexView.id);
return;
}
return () => {
setContextStoreCurrentViewId(null);
};
}, [
isLastVisitedObjectMetadataItemDifferent,
lastVisitedViewId,
objectNamePlural,
setContextStoreCurrentViewId,
setLastVisitedObjectMetadataItem,
setLastVisitedView,
viewIdQueryParam,
viewsOnCurrentObject,
]);
return <></>;
};