diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx
index 4bbd1aa15103..06217adc7410 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx
+++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter.tsx
@@ -2,25 +2,17 @@ import { RegisterRecordActionEffect } from '@/action-menu/actions/record-actions
import { WorkflowRunRecordActionMenuEntrySetterEffect } from '@/action-menu/actions/record-actions/workflow-run-record-actions/components/WorkflowRunRecordActionMenuEntrySetter';
import { getActionConfig } from '@/action-menu/actions/utils/getActionConfig';
import { getActionViewType } from '@/action-menu/actions/utils/getActionViewType';
-import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
-import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
-import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
import { FeatureFlagKey } from '~/generated/graphql';
export const RecordActionMenuEntriesSetter = () => {
- const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
- contextStoreCurrentObjectMetadataIdComponentState,
- );
-
- const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
-
- const objectMetadataItem = objectMetadataItems.find(
- (item) => item.id === contextStoreCurrentObjectMetadataId,
+ const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
);
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
@@ -39,10 +31,7 @@ export const RecordActionMenuEntriesSetter = () => {
FeatureFlagKey.IsCommandMenuV2Enabled,
);
- if (
- !isDefined(contextStoreCurrentObjectMetadataId) ||
- !isDefined(objectMetadataItem)
- ) {
+ if (!isDefined(contextStoreCurrentObjectMetadataItem)) {
return null;
}
@@ -52,7 +41,7 @@ export const RecordActionMenuEntriesSetter = () => {
);
const actionConfig = getActionConfig(
- objectMetadataItem,
+ contextStoreCurrentObjectMetadataItem,
isCommandMenuV2Enabled,
);
@@ -68,7 +57,7 @@ export const RecordActionMenuEntriesSetter = () => {
))}
@@ -76,7 +65,7 @@ export const RecordActionMenuEntriesSetter = () => {
contextStoreTargetedRecordsRule?.mode === 'selection' &&
contextStoreTargetedRecordsRule?.selectedRecordIds.length === 1 && (
)}
>
diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx
index 5fa370179879..6bad7e63a2cc 100644
--- a/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx
+++ b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx
@@ -8,8 +8,7 @@ import { RecordIndexActionMenuButtons } from '@/action-menu/components/RecordInd
import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown';
import { RecordIndexActionMenuEffect } from '@/action-menu/components/RecordIndexActionMenuEffect';
import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
-
-import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { isRecordIndexLoadMoreLockedComponentState } from '@/object-record/record-index/states/isRecordIndexLoadMoreLockedComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
@@ -18,8 +17,8 @@ import { useIsMobile } from 'twenty-ui';
import { FeatureFlagKey } from '~/generated/graphql';
export const RecordIndexActionMenu = ({ indexId }: { indexId: string }) => {
- const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
- contextStoreCurrentObjectMetadataIdComponentState,
+ const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
);
const isCommandMenuV2Enabled = useIsFeatureEnabled(
@@ -39,7 +38,7 @@ export const RecordIndexActionMenu = ({ indexId }: { indexId: string }) => {
return (
<>
- {contextStoreCurrentObjectMetadataId && (
+ {contextStoreCurrentObjectMetadataItem && (
void;
}) => {
- const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
- contextStoreCurrentObjectMetadataIdComponentState,
+ const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
);
const isCommandMenuV2Enabled = useIsFeatureEnabled(
@@ -42,7 +41,7 @@ export const RecordShowActionMenu = ({
return (
<>
- {contextStoreCurrentObjectMetadataId && (
+ {contextStoreCurrentObjectMetadataItem && (
{
- const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
- contextStoreCurrentObjectMetadataIdComponentState,
+ const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
);
const isWorkflowEnabled = useIsFeatureEnabled(
@@ -21,7 +20,7 @@ export const RecordShowRightDrawerActionMenu = () => {
return (
<>
- {contextStoreCurrentObjectMetadataId && (
+ {contextStoreCurrentObjectMetadataItem && (
diff --git a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect.ts b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect.ts
index 9acca6114a5f..88f1220f31d5 100644
--- a/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect.ts
+++ b/packages/twenty-front/src/modules/apollo/optimistic-effect/utils/triggerCreateRecordsOptimisticEffect.ts
@@ -66,6 +66,7 @@ export const triggerCreateRecordsOptimisticEffect = ({
});
cache.modify({
+ broadcast: false,
fields: {
[objectMetadataItem.namePlural]: (
rootQueryCachedResponse,
diff --git a/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx b/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx
index 37abf41e6347..f5c45a946c6e 100644
--- a/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx
+++ b/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx
@@ -59,10 +59,10 @@ export const AppRouterProviders = () => {
+
-
diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx
index 4381df6bc052..a5ac88220c04 100644
--- a/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx
+++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenu.tsx
@@ -5,12 +5,10 @@ import { RESET_CONTEXT_TO_SELECTION } from '@/command-menu/constants/ResetContex
import { useMatchingCommandMenuCommands } from '@/command-menu/hooks/useMatchingCommandMenuCommands';
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
import { Command } from '@/command-menu/types/Command';
-import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
-import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { SelectableItem } from '@/ui/layout/selectable-list/components/SelectableItem';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useLingui } from '@lingui/react/macro';
-import { isNonEmptyString } from '@sniptt/guards';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
@@ -50,23 +48,19 @@ export const CommandMenu = () => {
)
.filter(isDefined);
- const previousContextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
- contextStoreCurrentObjectMetadataIdComponentState,
- 'command-menu-previous',
- );
-
- const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
- const currentObjectMetadataId = useRecoilComponentValueV2(
- contextStoreCurrentObjectMetadataIdComponentState,
- );
+ const previousContextStoreCurrentObjectMetadataItem =
+ useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
+ 'command-menu-previous',
+ );
- const currentObjectMetadataItem = objectMetadataItems.find(
- (objectMetadataItem) => objectMetadataItem.id === currentObjectMetadataId,
+ const currentObjectMetadataItem = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
);
const selectableItemIds = selectableItems.map((item) => item.id);
- if (isNonEmptyString(previousContextStoreCurrentObjectMetadataId)) {
+ if (isDefined(previousContextStoreCurrentObjectMetadataItem)) {
selectableItemIds.unshift(RESET_CONTEXT_TO_SELECTION);
}
@@ -103,7 +97,7 @@ export const CommandMenu = () => {
selectableItemIds={selectableItemIds}
noResults={noResults}
>
- {isNonEmptyString(previousContextStoreCurrentObjectMetadataId) && (
+ {isDefined(previousContextStoreCurrentObjectMetadataItem) && (
diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenuTopBar.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenuTopBar.tsx
index c3fd69d38f60..68033af5b55a 100644
--- a/packages/twenty-front/src/modules/command-menu/components/CommandMenuTopBar.tsx
+++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenuTopBar.tsx
@@ -9,7 +9,7 @@ import { commandMenuNavigationStackState } from '@/command-menu/states/commandMe
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
-import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useTheme } from '@emotion/react';
@@ -96,8 +96,8 @@ export const CommandMenuTopBar = () => {
const { closeCommandMenu, goBackFromCommandMenu } = useCommandMenu();
- const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
- contextStoreCurrentObjectMetadataIdComponentState,
+ const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
);
const commandMenuPage = useRecoilValue(commandMenuPageState);
@@ -137,11 +137,11 @@ export const CommandMenuTopBar = () => {
testId="command-menu-go-back-button"
/>
)}
- {isDefined(contextStoreCurrentObjectMetadataId) &&
+ {isDefined(contextStoreCurrentObjectMetadataItem) &&
commandMenuPage !== CommandMenuPages.SearchRecords ? (
) : (
diff --git a/packages/twenty-front/src/modules/command-menu/components/ResetContextToSelectionCommandButton.tsx b/packages/twenty-front/src/modules/command-menu/components/ResetContextToSelectionCommandButton.tsx
index a8c85c3b6bcf..5992786b32c5 100644
--- a/packages/twenty-front/src/modules/command-menu/components/ResetContextToSelectionCommandButton.tsx
+++ b/packages/twenty-front/src/modules/command-menu/components/ResetContextToSelectionCommandButton.tsx
@@ -2,7 +2,7 @@ import { CommandMenuContextRecordChip } from '@/command-menu/components/CommandM
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
import { RESET_CONTEXT_TO_SELECTION } from '@/command-menu/constants/ResetContextToSelection';
import { useResetPreviousCommandMenuContext } from '@/command-menu/hooks/useResetPreviousCommandMenuContext';
-import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
@@ -17,8 +17,8 @@ export const ResetContextToSelectionCommandButton = () => {
'command-menu-previous',
);
- const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
- contextStoreCurrentObjectMetadataIdComponentState,
+ const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
'command-menu-previous',
);
@@ -26,7 +26,7 @@ export const ResetContextToSelectionCommandButton = () => {
const objectMetadataItem = objectMetadataItems.find(
(objectMetadataItem) =>
- objectMetadataItem.id === contextStoreCurrentObjectMetadataId,
+ objectMetadataItem.id === contextStoreCurrentObjectMetadataItem?.id,
);
const { resetPreviousCommandMenuContext } =
diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts b/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts
index 61e76709272b..607ed17f9e04 100644
--- a/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts
+++ b/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts
@@ -1,5 +1,5 @@
import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
-import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
@@ -17,19 +17,19 @@ export const useCopyContextStoreStates = () => {
instanceIdToCopyFrom: string;
instanceIdToCopyTo: string;
}) => {
- const contextStoreCurrentObjectMetadataId = snapshot
+ const contextStoreCurrentObjectMetadataItem = snapshot
.getLoadable(
- contextStoreCurrentObjectMetadataIdComponentState.atomFamily({
+ contextStoreCurrentObjectMetadataItemComponentState.atomFamily({
instanceId: instanceIdToCopyFrom,
}),
)
.getValue();
set(
- contextStoreCurrentObjectMetadataIdComponentState.atomFamily({
+ contextStoreCurrentObjectMetadataItemComponentState.atomFamily({
instanceId: instanceIdToCopyTo,
}),
- contextStoreCurrentObjectMetadataId,
+ contextStoreCurrentObjectMetadataItem,
);
const contextStoreTargetedRecordsRule = snapshot
diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts b/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts
index 795bb12531c8..f90a0f3e914e 100644
--- a/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts
+++ b/packages/twenty-front/src/modules/command-menu/hooks/useResetContextStoreStates.ts
@@ -1,5 +1,5 @@
import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
-import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
@@ -11,10 +11,10 @@ export const useResetContextStoreStates = () => {
const resetContextStoreStates = useRecoilCallback(({ set }) => {
return (instanceId: string) => {
set(
- contextStoreCurrentObjectMetadataIdComponentState.atomFamily({
+ contextStoreCurrentObjectMetadataItemComponentState.atomFamily({
instanceId,
}),
- null,
+ undefined,
);
set(
@@ -45,7 +45,7 @@ export const useResetContextStoreStates = () => {
contextStoreCurrentViewIdComponentState.atomFamily({
instanceId,
}),
- null,
+ undefined,
);
set(
diff --git a/packages/twenty-front/src/modules/context-store/components/ContextStoreCurrentViewTypeEffect.tsx b/packages/twenty-front/src/modules/context-store/components/ContextStoreCurrentViewTypeEffect.tsx
deleted file mode 100644
index fc8b9b9c7443..000000000000
--- a/packages/twenty-front/src/modules/context-store/components/ContextStoreCurrentViewTypeEffect.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
-import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType';
-import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
-import { useEffect } from 'react';
-
-export const ContextStoreCurrentViewTypeEffect = ({
- viewType,
-}: {
- viewType: ContextStoreViewType | null;
-}) => {
- const setContextStoreCurrentViewType = useSetRecoilComponentStateV2(
- contextStoreCurrentViewTypeComponentState,
- );
-
- useEffect(() => {
- setContextStoreCurrentViewType(viewType);
-
- return () => {
- setContextStoreCurrentViewType(null);
- };
- }, [setContextStoreCurrentViewType, viewType]);
-
- return null;
-};
diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx
index 5ca07b30b022..73bc03463756 100644
--- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx
+++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProvider.tsx
@@ -1,20 +1,16 @@
import { MainContextStoreProviderEffect } from '@/context-store/components/MainContextStoreProviderEffect';
import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchIndexViewIdFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector';
import { AppPath } from '@/types/AppPath';
-import { View } from '@/views/types/View';
-import { isNonEmptyString } from '@sniptt/guards';
import { useParams, useSearchParams } from 'react-router-dom';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
-import { undefined } from 'zod';
import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation';
const getViewId = (
viewIdFromQueryParams: string | null,
- indexView?: View,
+ indexViewId?: string,
lastVisitedViewId?: string,
) => {
if (isDefined(viewIdFromQueryParams)) {
@@ -25,8 +21,8 @@ const getViewId = (
return lastVisitedViewId;
}
- if (isDefined(indexView)) {
- return indexView.id;
+ if (isDefined(indexViewId)) {
+ return indexViewId;
}
return undefined;
@@ -44,17 +40,17 @@ export const MainContextStoreProvider = () => {
: undefined;
const objectNamePlural = useParams().objectNamePlural ?? '';
+ const objectNameSingular = useParams().objectNameSingular ?? '';
const [searchParams] = useSearchParams();
const viewIdQueryParam = searchParams.get('viewId');
- // Todo: this is triggering a lot of re-renders as we update the viewFields, we should introduce a state here
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
-
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const objectMetadataItem = objectMetadataItems.find(
- (objectMetadataItem) => objectMetadataItem.namePlural === objectNamePlural,
+ (objectMetadataItem) =>
+ objectMetadataItem.namePlural === objectNamePlural ||
+ objectMetadataItem.nameSingular === objectNameSingular,
);
const { getLastVisitedViewIdFromObjectNamePlural } = useLastVisitedView();
@@ -63,30 +59,24 @@ export const MainContextStoreProvider = () => {
objectMetadataItem?.namePlural ?? '',
);
- const viewsOnCurrentObject = views.filter(
- (view) => view.objectMetadataId === objectMetadataItem?.id,
+ const indexViewId = useRecoilValue(
+ prefetchIndexViewIdFromObjectMetadataItemFamilySelector({
+ objectMetadataItemId: objectMetadataItem?.id,
+ }),
);
- const indexView = viewsOnCurrentObject.find((view) => view.key === 'INDEX');
-
- const viewId = getViewId(viewIdQueryParam, indexView, lastVisitedViewId);
- const mainContextStoreComponentInstanceId = `${pageName}-${objectMetadataItem?.namePlural}-${viewId}`;
+ const viewId = getViewId(viewIdQueryParam, indexViewId, lastVisitedViewId);
- if (
- !isDefined(pageName) ||
- !isDefined(objectMetadataItem) ||
- !isNonEmptyString(viewId)
- ) {
+ if (!isDefined(pageName) || !isDefined(objectMetadataItem)) {
return null;
}
return (
);
};
diff --git a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx
index 28a634a72137..d0db2ea4e97f 100644
--- a/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx
+++ b/packages/twenty-front/src/modules/context-store/components/MainContextStoreProviderEffect.tsx
@@ -1,21 +1,27 @@
-import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
+import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId';
+import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType';
import { useSetLastVisitedObjectMetadataId } from '@/navigation/hooks/useSetLastVisitedObjectMetadataId';
import { useSetLastVisitedViewForObjectMetadataNamePlural } from '@/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
+import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
+import { ViewType } from '@/views/types/ViewType';
import { useEffect } from 'react';
-import { useRecoilState } from 'recoil';
+import { useRecoilState, useRecoilValue } from 'recoil';
export const MainContextStoreProviderEffect = ({
mainContextStoreComponentInstanceIdToSet,
viewId,
objectMetadataItem,
+ pageName,
}: {
mainContextStoreComponentInstanceIdToSet: string;
- viewId: string;
+ viewId?: string;
objectMetadataItem: ObjectMetadataItem;
+ pageName: string;
}) => {
const [
mainContextStoreComponentInstanceId,
@@ -34,17 +40,29 @@ export const MainContextStoreProviderEffect = ({
mainContextStoreComponentInstanceId,
);
+ const [contextStoreCurrentViewType, setContextStoreCurrentViewType] =
+ useRecoilComponentStateV2(
+ contextStoreCurrentViewTypeComponentState,
+ mainContextStoreComponentInstanceId,
+ );
+
const [
- contextStoreCurrentObjectMetadataId,
- setContextStoreCurrentObjectMetadataId,
+ contextStoreCurrentObjectMetadataItem,
+ setContextStoreCurrentObjectMetadataItem,
] = useRecoilComponentStateV2(
- contextStoreCurrentObjectMetadataIdComponentState,
+ contextStoreCurrentObjectMetadataItemComponentState,
mainContextStoreComponentInstanceId,
);
+ const view = useRecoilValue(
+ prefetchViewFromViewIdFamilySelector({
+ viewId: viewId ?? '',
+ }),
+ );
+
useEffect(() => {
- if (contextStoreCurrentObjectMetadataId !== objectMetadataItem.id) {
- setContextStoreCurrentObjectMetadataId(objectMetadataItem.id);
+ if (contextStoreCurrentObjectMetadataItem?.id !== objectMetadataItem.id) {
+ setContextStoreCurrentObjectMetadataItem(objectMetadataItem);
}
if (
@@ -58,7 +76,7 @@ export const MainContextStoreProviderEffect = ({
setLastVisitedViewForObjectMetadataNamePlural({
objectNamePlural: objectMetadataItem.namePlural,
- viewId: viewId,
+ viewId: viewId ?? '',
});
setLastVisitedObjectMetadataId({
@@ -69,13 +87,13 @@ export const MainContextStoreProviderEffect = ({
setContextStoreCurrentViewId(viewId);
}
}, [
- contextStoreCurrentObjectMetadataId,
+ contextStoreCurrentObjectMetadataItem,
contextStoreCurrentViewId,
mainContextStoreComponentInstanceId,
mainContextStoreComponentInstanceIdToSet,
objectMetadataItem,
objectMetadataItem.namePlural,
- setContextStoreCurrentObjectMetadataId,
+ setContextStoreCurrentObjectMetadataItem,
setContextStoreCurrentViewId,
setLastVisitedObjectMetadataId,
setLastVisitedViewForObjectMetadataNamePlural,
@@ -83,5 +101,23 @@ export const MainContextStoreProviderEffect = ({
viewId,
]);
+ useEffect(() => {
+ const viewType =
+ pageName === 'record-show'
+ ? ContextStoreViewType.ShowPage
+ : view && view.type === ViewType.Kanban
+ ? ContextStoreViewType.Kanban
+ : ContextStoreViewType.Table;
+
+ if (contextStoreCurrentViewType !== viewType) {
+ setContextStoreCurrentViewType(viewType);
+ }
+ }, [
+ contextStoreCurrentViewType,
+ pageName,
+ setContextStoreCurrentViewType,
+ view,
+ ]);
+
return null;
};
diff --git a/packages/twenty-front/src/modules/context-store/hooks/useContextStoreCurrentObjectMetadataIdOrThrow.ts b/packages/twenty-front/src/modules/context-store/hooks/useContextStoreCurrentObjectMetadataIdOrThrow.ts
deleted file mode 100644
index 2b265fe47346..000000000000
--- a/packages/twenty-front/src/modules/context-store/hooks/useContextStoreCurrentObjectMetadataIdOrThrow.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
-import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
-
-export const useContextStoreCurrentObjectMetadataIdOrThrow = (
- instanceId?: string,
-) => {
- const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
- contextStoreCurrentObjectMetadataIdComponentState,
- instanceId,
- );
-
- if (!contextStoreCurrentObjectMetadataId) {
- throw new Error('contextStoreCurrentObjectMetadataIdComponent is not set');
- }
-
- return contextStoreCurrentObjectMetadataId;
-};
diff --git a/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts b/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts
new file mode 100644
index 000000000000..5e09defb6937
--- /dev/null
+++ b/packages/twenty-front/src/modules/context-store/hooks/useContextStoreObjectMetadataItemOrThrow.ts
@@ -0,0 +1,17 @@
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
+
+export const useContextStoreObjectMetadataItemOrThrow = (
+ contextStoreInstanceId?: string,
+) => {
+ const objectMetadataItem = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
+ contextStoreInstanceId,
+ );
+
+ if (!objectMetadataItem) {
+ throw new Error('Object metadata item is not set in context store');
+ }
+
+ return { objectMetadataItem };
+};
diff --git a/packages/twenty-front/src/modules/context-store/hooks/useFindManyRecordsSelectedInContextStore.ts b/packages/twenty-front/src/modules/context-store/hooks/useFindManyRecordsSelectedInContextStore.ts
index 5743292a5633..eb89af04db7a 100644
--- a/packages/twenty-front/src/modules/context-store/hooks/useFindManyRecordsSelectedInContextStore.ts
+++ b/packages/twenty-front/src/modules/context-store/hooks/useFindManyRecordsSelectedInContextStore.ts
@@ -1,8 +1,7 @@
-import { useContextStoreCurrentObjectMetadataIdOrThrow } from '@/context-store/hooks/useContextStoreCurrentObjectMetadataIdOrThrow';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
-import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
@@ -14,12 +13,10 @@ export const useFindManyRecordsSelectedInContextStore = ({
instanceId?: string;
limit?: number;
}) => {
- const objectMetadataId =
- useContextStoreCurrentObjectMetadataIdOrThrow(instanceId);
-
- const { objectMetadataItem } = useObjectMetadataItemById({
- objectId: objectMetadataId,
- });
+ const objectMetadataItem = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
+ instanceId,
+ );
const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
contextStoreTargetedRecordsRuleComponentState,
@@ -36,12 +33,13 @@ export const useFindManyRecordsSelectedInContextStore = ({
const queryFilter = computeContextStoreFilters(
contextStoreTargetedRecordsRule,
contextStoreFilters,
- objectMetadataItem,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ objectMetadataItem!,
filterValueDependencies,
);
const { records, loading, totalCount } = useFindManyRecords({
- objectNameSingular: objectMetadataItem.nameSingular,
+ objectNameSingular: objectMetadataItem?.nameSingular ?? '',
filter: queryFilter,
withSoftDeleted: true,
orderBy: [
diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdComponentState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataItemComponentState.ts
similarity index 50%
rename from packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdComponentState.ts
rename to packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataItemComponentState.ts
index 9898e6c6f540..4d9d8eb983f1 100644
--- a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdComponentState.ts
+++ b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataItemComponentState.ts
@@ -1,9 +1,10 @@
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
+import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
-export const contextStoreCurrentObjectMetadataIdComponentState =
- createComponentStateV2({
- key: 'contextStoreCurrentObjectMetadataIdComponentState',
- defaultValue: null,
+export const contextStoreCurrentObjectMetadataItemComponentState =
+ createComponentStateV2({
+ key: 'contextStoreCurrentObjectMetadataItemComponentState',
+ defaultValue: undefined,
componentInstanceContext: ContextStoreComponentInstanceContext,
});
diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdComponentState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdComponentState.ts
index 10136c28d004..c351a849584f 100644
--- a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdComponentState.ts
+++ b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdComponentState.ts
@@ -2,9 +2,9 @@ import { ContextStoreComponentInstanceContext } from '@/context-store/states/con
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
export const contextStoreCurrentViewIdComponentState = createComponentStateV2<
- string | null
+ string | undefined
>({
key: 'contextStoreCurrentViewIdComponentState',
- defaultValue: null,
+ defaultValue: undefined,
componentInstanceContext: ContextStoreComponentInstanceContext,
});
diff --git a/packages/twenty-front/src/modules/favorites/hooks/useDeleteFavoriteFolder.ts b/packages/twenty-front/src/modules/favorites/hooks/useDeleteFavoriteFolder.ts
index c10adccb88f3..7b1ed284c87e 100644
--- a/packages/twenty-front/src/modules/favorites/hooks/useDeleteFavoriteFolder.ts
+++ b/packages/twenty-front/src/modules/favorites/hooks/useDeleteFavoriteFolder.ts
@@ -1,47 +1,13 @@
-import { Favorite } from '@/favorites/types/Favorite';
-import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
-import { useReadFindManyRecordsQueryInCache } from '@/object-record/cache/hooks/useReadFindManyRecordsQueryInCache';
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
-import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig';
-import { useUpsertRecordsInCacheForPrefetchKey } from '@/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
export const useDeleteFavoriteFolder = () => {
const { deleteOneRecord } = useDeleteOneRecord({
objectNameSingular: CoreObjectNameSingular.FavoriteFolder,
});
- const { upsertRecordsInCache } =
- useUpsertRecordsInCacheForPrefetchKey({
- prefetchKey: PrefetchKey.AllFavorites,
- });
-
- const { objectMetadataItem } = useObjectMetadataItem({
- objectNameSingular:
- PREFETCH_CONFIG[PrefetchKey.AllFavorites].objectNameSingular,
- });
-
- const { readFindManyRecordsQueryInCache } =
- useReadFindManyRecordsQueryInCache({
- objectMetadataItem,
- });
-
const deleteFavoriteFolder = async (folderId: string): Promise => {
await deleteOneRecord(folderId);
-
- const allFavorites = readFindManyRecordsQueryInCache({
- queryVariables: {},
- recordGqlFields: PREFETCH_CONFIG[
- PrefetchKey.AllFavorites
- ].operationSignatureFactory({ objectMetadataItem }).fields,
- });
-
- const updatedFavorites = allFavorites.filter(
- (favorite) => favorite.favoriteFolderId !== folderId,
- );
-
- upsertRecordsInCache(updatedFavorites);
};
return {
diff --git a/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts
index e528ee5e8dc0..6662fd71e671 100644
--- a/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts
+++ b/packages/twenty-front/src/modules/favorites/hooks/useFavorites.ts
@@ -1,11 +1,9 @@
+import { favoriteViewsWithMinimalDataSelector } from '@/favorites/states/selectors/favoriteViewsWithMinimalDataSelector';
import { sortFavorites } from '@/favorites/utils/sortFavorites';
import { useGetObjectRecordIdentifierByNameSingular } from '@/object-metadata/hooks/useGetObjectRecordIdentifierByNameSingular';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
-import { View } from '@/views/types/View';
import { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { FieldMetadataType } from '~/generated-metadata/graphql';
@@ -13,7 +11,9 @@ import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData';
export const useFavorites = () => {
const { favorites } = usePrefetchedFavoritesData();
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
+ const favoriteViewsWithMinimalData = useRecoilValue(
+ favoriteViewsWithMinimalDataSelector,
+ );
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const { objectMetadataItem: favoriteObjectMetadataItem } =
useObjectMetadataItem({
@@ -40,14 +40,14 @@ export const useFavorites = () => {
favoriteRelationFieldMetadataItems,
getObjectRecordIdentifierByNameSingular,
true,
- views,
+ favoriteViewsWithMinimalData,
objectMetadataItems,
),
[
favorites,
favoriteRelationFieldMetadataItems,
getObjectRecordIdentifierByNameSingular,
- views,
+ favoriteViewsWithMinimalData,
objectMetadataItems,
],
);
diff --git a/packages/twenty-front/src/modules/favorites/hooks/useFavoritesByFolder.ts b/packages/twenty-front/src/modules/favorites/hooks/useFavoritesByFolder.ts
index 2747c1e1f14c..4f9977f1f31d 100644
--- a/packages/twenty-front/src/modules/favorites/hooks/useFavoritesByFolder.ts
+++ b/packages/twenty-front/src/modules/favorites/hooks/useFavoritesByFolder.ts
@@ -1,4 +1,6 @@
import { sortFavorites } from '@/favorites/utils/sortFavorites';
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
+import { useRecoilValue } from 'recoil';
import { useFavoritesMetadata } from './useFavoritesMetadata';
import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData';
import { usePrefetchedFavoritesFoldersData } from './usePrefetchedFavoritesFoldersData';
@@ -7,12 +9,13 @@ export const useFavoritesByFolder = () => {
const { favorites } = usePrefetchedFavoritesData();
const { favoriteFolders } = usePrefetchedFavoritesFoldersData();
const {
- views,
objectMetadataItems,
getObjectRecordIdentifierByNameSingular,
favoriteRelationFields,
} = useFavoritesMetadata();
+ const prefetchViews = useRecoilValue(prefetchViewsState);
+
const favoritesByFolder = favoriteFolders.map((folder) => ({
folderId: folder.id,
folderName: folder.name,
@@ -21,7 +24,7 @@ export const useFavoritesByFolder = () => {
favoriteRelationFields,
getObjectRecordIdentifierByNameSingular,
true,
- views,
+ prefetchViews,
objectMetadataItems,
),
}));
diff --git a/packages/twenty-front/src/modules/favorites/hooks/useFavoritesMetadata.ts b/packages/twenty-front/src/modules/favorites/hooks/useFavoritesMetadata.ts
index 04780f975295..e6c4e9b29b7b 100644
--- a/packages/twenty-front/src/modules/favorites/hooks/useFavoritesMetadata.ts
+++ b/packages/twenty-front/src/modules/favorites/hooks/useFavoritesMetadata.ts
@@ -2,14 +2,10 @@ import { useGetObjectRecordIdentifierByNameSingular } from '@/object-metadata/ho
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
-import { View } from '@/views/types/View';
import { useRecoilValue } from 'recoil';
import { FieldMetadataType } from '~/generated-metadata/graphql';
export const useFavoritesMetadata = () => {
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const getObjectRecordIdentifierByNameSingular =
useGetObjectRecordIdentifierByNameSingular();
@@ -27,7 +23,6 @@ export const useFavoritesMetadata = () => {
);
return {
- views,
objectMetadataItems,
getObjectRecordIdentifierByNameSingular,
favoriteRelationFields,
diff --git a/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesData.ts b/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesData.ts
index ece3d2bdf3f3..c6a8cee7259c 100644
--- a/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesData.ts
+++ b/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesData.ts
@@ -1,46 +1,30 @@
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { Favorite } from '@/favorites/types/Favorite';
-import { useUpsertRecordsInCacheForPrefetchKey } from '@/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchFavoritesState } from '@/prefetch/states/prefetchFavoritesState';
import { useRecoilValue } from 'recoil';
type PrefetchedFavoritesData = {
favorites: Favorite[];
workspaceFavorites: Favorite[];
- upsertFavorites: (records: Favorite[]) => void;
currentWorkspaceMemberId: string | undefined;
};
export const usePrefetchedFavoritesData = (): PrefetchedFavoritesData => {
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const currentWorkspaceMemberId = currentWorkspaceMember?.id;
- const { records: _favorites } = usePrefetchedData(
- PrefetchKey.AllFavorites,
- {
- workspaceMemberId: {
- eq: currentWorkspaceMemberId,
- },
- },
- );
+ const prefetchFavorites = useRecoilValue(prefetchFavoritesState);
- const favorites = _favorites.filter(
+ const favorites = prefetchFavorites.filter(
(favorite) => favorite.workspaceMemberId === currentWorkspaceMemberId,
);
- const workspaceFavorites = _favorites.filter(
+ const workspaceFavorites = prefetchFavorites.filter(
(favorite) => favorite.workspaceMemberId === null,
);
- const { upsertRecordsInCache: upsertFavorites } =
- useUpsertRecordsInCacheForPrefetchKey({
- prefetchKey: PrefetchKey.AllFavorites,
- });
-
return {
favorites,
workspaceFavorites,
- upsertFavorites,
currentWorkspaceMemberId,
};
};
diff --git a/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesFoldersData.ts b/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesFoldersData.ts
index 32972ed05697..4c53d5dd8d64 100644
--- a/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesFoldersData.ts
+++ b/packages/twenty-front/src/modules/favorites/hooks/usePrefetchedFavoritesFoldersData.ts
@@ -1,13 +1,10 @@
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { FavoriteFolder } from '@/favorites/types/FavoriteFolder';
-import { useUpsertRecordsInCacheForPrefetchKey } from '@/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchFavoriteFoldersState } from '@/prefetch/states/prefetchFavoriteFoldersState';
import { useRecoilValue } from 'recoil';
type PrefetchedFavoritesFoldersData = {
favoriteFolders: FavoriteFolder[];
- upsertFavoriteFolders: (records: FavoriteFolder[]) => void;
currentWorkspaceMemberId: string | undefined;
};
@@ -16,23 +13,12 @@ export const usePrefetchedFavoritesFoldersData =
const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState);
const currentWorkspaceMemberId = currentWorkspaceMember?.id;
- const { records: favoriteFolders } = usePrefetchedData(
- PrefetchKey.AllFavoritesFolders,
- {
- workspaceMemberId: {
- eq: currentWorkspaceMemberId,
- },
- },
+ const prefetchFavoriteFolders = useRecoilValue(
+ prefetchFavoriteFoldersState,
);
- const { upsertRecordsInCache: upsertFavoriteFolders } =
- useUpsertRecordsInCacheForPrefetchKey({
- prefetchKey: PrefetchKey.AllFavoritesFolders,
- });
-
return {
- favoriteFolders,
- upsertFavoriteFolders,
+ favoriteFolders: prefetchFavoriteFolders,
currentWorkspaceMemberId,
};
};
diff --git a/packages/twenty-front/src/modules/favorites/hooks/useSortedFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/useSortedFavorites.ts
index 3ec57bf5d5df..582a2abfc1b2 100644
--- a/packages/twenty-front/src/modules/favorites/hooks/useSortedFavorites.ts
+++ b/packages/twenty-front/src/modules/favorites/hooks/useSortedFavorites.ts
@@ -1,32 +1,35 @@
import { sortFavorites } from '@/favorites/utils/sortFavorites';
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { useMemo } from 'react';
+import { useRecoilValue } from 'recoil';
import { useFavoritesMetadata } from './useFavoritesMetadata';
import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData';
export const useSortedFavorites = () => {
const { favorites, workspaceFavorites } = usePrefetchedFavoritesData();
const {
- views,
objectMetadataItems,
getObjectRecordIdentifierByNameSingular,
favoriteRelationFields,
} = useFavoritesMetadata();
+ const prefetchViews = useRecoilValue(prefetchViewsState);
+
const favoritesSorted = useMemo(() => {
return sortFavorites(
favorites,
favoriteRelationFields,
getObjectRecordIdentifierByNameSingular,
true,
- views,
+ prefetchViews,
objectMetadataItems,
);
}, [
favoriteRelationFields,
favorites,
getObjectRecordIdentifierByNameSingular,
- views,
objectMetadataItems,
+ prefetchViews,
]);
const workspaceFavoritesSorted = useMemo(() => {
@@ -35,14 +38,14 @@ export const useSortedFavorites = () => {
favoriteRelationFields,
getObjectRecordIdentifierByNameSingular,
false,
- views,
+ prefetchViews,
objectMetadataItems,
);
}, [
+ workspaceFavorites,
favoriteRelationFields,
getObjectRecordIdentifierByNameSingular,
- workspaceFavorites,
- views,
+ prefetchViews,
objectMetadataItems,
]);
diff --git a/packages/twenty-front/src/modules/favorites/hooks/useWorkspaceFavorites.ts b/packages/twenty-front/src/modules/favorites/hooks/useWorkspaceFavorites.ts
index 04d52cb229e9..d41a6ca3215f 100644
--- a/packages/twenty-front/src/modules/favorites/hooks/useWorkspaceFavorites.ts
+++ b/packages/twenty-front/src/modules/favorites/hooks/useWorkspaceFavorites.ts
@@ -4,9 +4,7 @@ import { useGetObjectRecordIdentifierByNameSingular } from '@/object-metadata/ho
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
-import { View } from '@/views/types/View';
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { FieldMetadataType } from '~/generated-metadata/graphql';
@@ -14,8 +12,7 @@ import { usePrefetchedFavoritesData } from './usePrefetchedFavoritesData';
export const useWorkspaceFavorites = () => {
const { workspaceFavorites } = usePrefetchedFavoritesData();
-
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
+ const prefetchViews = useRecoilValue(prefetchViewsState);
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const { objectMetadataItem: favoriteObjectMetadataItem } =
useObjectMetadataItem({
@@ -42,14 +39,14 @@ export const useWorkspaceFavorites = () => {
favoriteRelationFieldMetadataItems,
getObjectRecordIdentifierByNameSingular,
false,
- views,
+ prefetchViews,
objectMetadataItems,
),
[
workspaceFavorites,
favoriteRelationFieldMetadataItems,
getObjectRecordIdentifierByNameSingular,
- views,
+ prefetchViews,
objectMetadataItems,
],
);
@@ -59,7 +56,7 @@ export const useWorkspaceFavorites = () => {
);
const favoriteViewObjectMetadataIds = new Set(
- views.reduce((acc, view) => {
+ prefetchViews.reduce((acc, view) => {
if (workspaceFavoriteIds.has(view.id)) {
acc.push(view.objectMetadataId);
}
diff --git a/packages/twenty-front/src/modules/favorites/states/selectors/favoriteViewsWithMinimalDataSelector.ts b/packages/twenty-front/src/modules/favorites/states/selectors/favoriteViewsWithMinimalDataSelector.ts
new file mode 100644
index 000000000000..f963a69fffda
--- /dev/null
+++ b/packages/twenty-front/src/modules/favorites/states/selectors/favoriteViewsWithMinimalDataSelector.ts
@@ -0,0 +1,18 @@
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
+import { View } from '@/views/types/View';
+import { selector } from 'recoil';
+
+export const favoriteViewsWithMinimalDataSelector = selector<
+ Pick[]
+>({
+ key: 'favoriteViewsWithMinimalDataSelector',
+ get: ({ get }) => {
+ const views = get(prefetchViewsState);
+ return views.map((view) => ({
+ id: view.id,
+ name: view.name,
+ objectMetadataId: view.objectMetadataId,
+ icon: view.icon,
+ }));
+ },
+});
diff --git a/packages/twenty-front/src/modules/favorites/utils/getObjectMetadataLabelPluralFromViewId.ts b/packages/twenty-front/src/modules/favorites/utils/getObjectMetadataLabelPluralFromViewId.ts
index 91e3a0ec0ff2..53e8771721a4 100644
--- a/packages/twenty-front/src/modules/favorites/utils/getObjectMetadataLabelPluralFromViewId.ts
+++ b/packages/twenty-front/src/modules/favorites/utils/getObjectMetadataLabelPluralFromViewId.ts
@@ -4,23 +4,13 @@ import { isDefined } from 'twenty-shared';
type ReturnType = {
labelPlural: string;
- view: View | null;
+ view: Pick;
};
export const getObjectMetadataLabelPluralFromViewId = (
- views: View[],
+ view: Pick,
objectMetadataItems: ObjectMetadataItem[],
- viewId: string,
): ReturnType => {
- const view = views.find((view) => view.id === viewId);
-
- if (!view) {
- return {
- labelPlural: '',
- view: null,
- };
- }
-
const objectMetadataItem = objectMetadataItems.find(
(objectMetadataItem) => objectMetadataItem.id === view.objectMetadataId,
);
diff --git a/packages/twenty-front/src/modules/favorites/utils/sortFavorites.ts b/packages/twenty-front/src/modules/favorites/utils/sortFavorites.ts
index 46d6d32fb21d..1f848e6c8c4d 100644
--- a/packages/twenty-front/src/modules/favorites/utils/sortFavorites.ts
+++ b/packages/twenty-front/src/modules/favorites/utils/sortFavorites.ts
@@ -22,16 +22,23 @@ export const sortFavorites = (
objectNameSingular: string,
) => ObjectRecordIdentifier,
hasLinkToShowPage: boolean,
- views: View[],
+ views: Pick[],
objectMetadataItems: ObjectMetadataItem[],
) => {
return favorites
.map((favorite) => {
if (isDefined(favorite.viewId) && isDefined(favorite.workspaceMemberId)) {
- const { labelPlural, view } = getObjectMetadataLabelPluralFromViewId(
- views,
+ const view = views.find((view) => view.id === favorite.viewId);
+
+ if (!isDefined(view)) {
+ return {
+ ...favorite,
+ } as ProcessedFavorite;
+ }
+
+ const { labelPlural } = getObjectMetadataLabelPluralFromViewId(
+ view,
objectMetadataItems,
- favorite.viewId,
);
return {
diff --git a/packages/twenty-front/src/modules/navigation/hooks/__tests__/useDefaultHomePagePath.test.ts b/packages/twenty-front/src/modules/navigation/hooks/__tests__/useDefaultHomePagePath.test.ts
index 31a7172dfa9e..2b55546786e4 100644
--- a/packages/twenty-front/src/modules/navigation/hooks/__tests__/useDefaultHomePagePath.test.ts
+++ b/packages/twenty-front/src/modules/navigation/hooks/__tests__/useDefaultHomePagePath.test.ts
@@ -4,41 +4,54 @@ import { RecoilRoot, useSetRecoilState } from 'recoil';
import { currentUserState } from '@/auth/states/currentUserState';
import { useDefaultHomePagePath } from '@/navigation/hooks/useDefaultHomePagePath';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
+import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { AppPath } from '@/types/AppPath';
+import { ViewType } from '@/views/types/ViewType';
+import { getCompanyObjectMetadataItem } from '~/testing/mock-data/companies';
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
import { mockedUserData } from '~/testing/mock-data/users';
-jest.mock('@/prefetch/hooks/usePrefetchedData');
-const setupMockPrefetchedData = (viewId?: string) => {
- const companyObjectMetadata = generatedMockObjectMetadataItems.find(
- (item) => item.nameSingular === 'company',
- );
-
- jest.mocked(usePrefetchedData).mockReturnValue({
- isDataPrefetched: true,
- records: viewId
- ? [
- {
- id: viewId,
- __typename: 'object',
- objectMetadataId: companyObjectMetadata?.id,
- },
- ]
- : [],
- });
-};
-
-const renderHooks = (withCurrentUser: boolean) => {
+const renderHooks = ({
+ withCurrentUser,
+ withExistingView,
+}: {
+ withCurrentUser: boolean;
+ withExistingView: boolean;
+}) => {
const { result } = renderHook(
() => {
const setCurrentUser = useSetRecoilState(currentUserState);
const setObjectMetadataItems = useSetRecoilState(
objectMetadataItemsState,
);
+ const setPrefetchViews = useSetRecoilState(prefetchViewsState);
setObjectMetadataItems(generatedMockObjectMetadataItems);
+ if (withExistingView) {
+ setPrefetchViews([
+ {
+ id: 'viewId',
+ name: 'Test View',
+ objectMetadataId: getCompanyObjectMetadataItem().id,
+ type: ViewType.Table,
+ key: null,
+ isCompact: false,
+ viewFields: [],
+ viewGroups: [],
+ viewSorts: [],
+ kanbanFieldMetadataId: '',
+ kanbanAggregateOperation: AGGREGATE_OPERATIONS.count,
+ icon: '',
+ kanbanAggregateOperationFieldMetadataId: '',
+ position: 0,
+ viewFilters: [],
+ __typename: 'View',
+ },
+ ]);
+ }
+
if (withCurrentUser) {
setCurrentUser(mockedUserData);
}
@@ -52,23 +65,31 @@ const renderHooks = (withCurrentUser: boolean) => {
};
describe('useDefaultHomePagePath', () => {
it('should return proper path when no currentUser', () => {
- setupMockPrefetchedData();
- const { result } = renderHooks(false);
+ const { result } = renderHooks({
+ withCurrentUser: false,
+ withExistingView: false,
+ });
expect(result.current.defaultHomePagePath).toEqual(AppPath.SignInUp);
});
it('should return proper path when no currentUser and existing view', () => {
- setupMockPrefetchedData('viewId');
- const { result } = renderHooks(false);
+ const { result } = renderHooks({
+ withCurrentUser: false,
+ withExistingView: true,
+ });
expect(result.current.defaultHomePagePath).toEqual(AppPath.SignInUp);
});
it('should return proper path when currentUser is defined', () => {
- setupMockPrefetchedData();
- const { result } = renderHooks(true);
+ const { result } = renderHooks({
+ withCurrentUser: true,
+ withExistingView: false,
+ });
expect(result.current.defaultHomePagePath).toEqual('/objects/companies');
});
it('should return proper path when currentUser is defined and view exists', () => {
- setupMockPrefetchedData('viewId');
- const { result } = renderHooks(true);
+ const { result } = renderHooks({
+ withCurrentUser: true,
+ withExistingView: true,
+ });
expect(result.current.defaultHomePagePath).toEqual(
'/objects/companies?viewId=viewId',
);
diff --git a/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts b/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts
index fe8d45a6c60c..dea010525071 100644
--- a/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts
+++ b/packages/twenty-front/src/modules/navigation/hooks/useDefaultHomePagePath.ts
@@ -2,10 +2,8 @@ import { currentUserState } from '@/auth/states/currentUserState';
import { lastVisitedObjectMetadataItemIdState } from '@/navigation/states/lastVisitedObjectMetadataItemIdState';
import { ObjectPathInfo } from '@/navigation/types/ObjectPathInfo';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { AppPath } from '@/types/AppPath';
-import { View } from '@/views/types/View';
import { useCallback, useMemo } from 'react';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
@@ -15,7 +13,7 @@ export const useDefaultHomePagePath = () => {
const currentUser = useRecoilValue(currentUserState);
const { activeObjectMetadataItems, alphaSortedActiveObjectMetadataItems } =
useFilteredObjectMetadataItems();
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
+ const prefetchViews = useRecoilValue(prefetchViewsState);
const lastVisitedObjectMetadataItemId = useRecoilValue(
lastVisitedObjectMetadataItemIdState,
);
@@ -31,8 +29,10 @@ export const useDefaultHomePagePath = () => {
const getFirstView = useCallback(
(objectMetadataItemId: string | undefined | null) =>
- views.find((view) => view.objectMetadataId === objectMetadataItemId),
- [views],
+ prefetchViews.find(
+ (view) => view.objectMetadataId === objectMetadataItemId,
+ ),
+ [prefetchViews],
);
const firstObjectPathInfo = useMemo(() => {
diff --git a/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural.ts b/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural.ts
index 762c75b27052..ede4ec62b8d6 100644
--- a/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural.ts
+++ b/packages/twenty-front/src/modules/navigation/hooks/useSetLastVisitedViewForObjectMetadataNamePlural.ts
@@ -1,16 +1,11 @@
import { lastVisitedViewPerObjectMetadataItemState } from '@/navigation/states/lastVisitedViewPerObjectMetadataItemState';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
-import { useLazyPrefetchedData } from '@/prefetch/hooks/useLazyPrefetchData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { View } from '@/views/types/View';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared';
export const useSetLastVisitedViewForObjectMetadataNamePlural = () => {
- const { records: views, findManyRecords } = useLazyPrefetchedData(
- PrefetchKey.AllViews,
- );
-
const setLastVisitedViewForObjectMetadataNamePlural = useRecoilCallback(
({ set, snapshot }) =>
async ({
@@ -20,7 +15,7 @@ export const useSetLastVisitedViewForObjectMetadataNamePlural = () => {
objectNamePlural: string;
viewId: string;
}) => {
- await findManyRecords();
+ const views = snapshot.getLoadable(prefetchViewsState).getValue();
const view = views.find((view: View) => view.id === viewId);
@@ -54,7 +49,7 @@ export const useSetLastVisitedViewForObjectMetadataNamePlural = () => {
});
}
},
- [findManyRecords, views],
+ [],
);
return {
diff --git a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx
index b93a9df2c734..12ac9a208879 100644
--- a/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx
+++ b/packages/twenty-front/src/modules/object-metadata/components/NavigationDrawerItemForObjectMetadataItem.tsx
@@ -2,16 +2,13 @@ import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/
import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId';
import { lastVisitedViewPerObjectMetadataItemState } from '@/navigation/states/lastVisitedViewPerObjectMetadataItemState';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchViewsFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchViewsFromObjectMetadataItemFamilySelector';
import { AppPath } from '@/types/AppPath';
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
import { NavigationDrawerItemsCollapsableContainer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItemsCollapsableContainer';
import { NavigationDrawerSubItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSubItem';
import { getNavigationSubItemLeftAdornment } from '@/ui/navigation/navigation-drawer/utils/getNavigationSubItemLeftAdornment';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
-import { View } from '@/views/types/View';
-import { getObjectMetadataItemViews } from '@/views/utils/getObjectMetadataItemViews';
import { useLocation } from 'react-router-dom';
import { useRecoilValue } from 'recoil';
import { AnimatedExpandableContainer, useIcons } from 'twenty-ui';
@@ -24,11 +21,10 @@ export type NavigationDrawerItemForObjectMetadataItemProps = {
export const NavigationDrawerItemForObjectMetadataItem = ({
objectMetadataItem,
}: NavigationDrawerItemForObjectMetadataItemProps) => {
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
-
- const objectMetadataViews = getObjectMetadataItemViews(
- objectMetadataItem.id,
- views,
+ const views = useRecoilValue(
+ prefetchViewsFromObjectMetadataItemFamilySelector({
+ objectMetadataItemId: objectMetadataItem.id,
+ }),
);
const mainContextStoreComponentInstanceId = useRecoilValue(
@@ -68,9 +64,9 @@ export const NavigationDrawerItemForObjectMetadataItem = ({
}) + '/',
);
- const shouldSubItemsBeDisplayed = isActive && objectMetadataViews.length > 1;
+ const shouldSubItemsBeDisplayed = isActive && views.length > 1;
- const sortedObjectMetadataViews = [...objectMetadataViews].sort(
+ const sortedObjectMetadataViews = [...views].sort(
(viewA, viewB) => viewA.position - viewB.position,
);
diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata.ts
index e1b50dc6d7d0..7a3dd4ec873d 100644
--- a/packages/twenty-front/src/modules/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata.ts
+++ b/packages/twenty-front/src/modules/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata.ts
@@ -1,5 +1,3 @@
-import { useMemo } from 'react';
-
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
@@ -13,14 +11,8 @@ import { formatFieldMetadataItemsAsSortDefinitions } from '../utils/formatFieldM
export const useColumnDefinitionsFromFieldMetadata = (
objectMetadataItem: ObjectMetadataItem,
) => {
- const activeFieldMetadataItems = useMemo(
- () =>
- objectMetadataItem
- ? objectMetadataItem.fields.filter(
- ({ isActive, isSystem }) => isActive && !isSystem,
- )
- : [],
- [objectMetadataItem],
+ const activeFieldMetadataItems = objectMetadataItem.fields.filter(
+ ({ isActive, isSystem }) => isActive && !isSystem,
);
const filterableFieldMetadataItems = useRecoilValue(
@@ -33,43 +25,30 @@ export const useColumnDefinitionsFromFieldMetadata = (
fields: activeFieldMetadataItems,
});
- const columnDefinitions: ColumnDefinition[] = useMemo(
- () =>
- objectMetadataItem
- ? activeFieldMetadataItems
- .map((field, index) =>
- formatFieldMetadataItemAsColumnDefinition({
- position: index,
- field,
- objectMetadataItem,
- }),
- )
- .filter(filterAvailableTableColumns)
- .map((column) => {
- const existsInFilterDefinitions =
- filterableFieldMetadataItems.some(
- (fieldMetadataItem) =>
- fieldMetadataItem.id === column.fieldMetadataId,
- );
-
- const existsInSortDefinitions = sortDefinitions.some(
- (sort) => sort.fieldMetadataId === column.fieldMetadataId,
- );
-
- return {
- ...column,
- isFilterable: existsInFilterDefinitions,
- isSortable: existsInSortDefinitions,
- };
- })
- : [],
- [
- filterableFieldMetadataItems,
- activeFieldMetadataItems,
- objectMetadataItem,
- sortDefinitions,
- ],
- );
+ const columnDefinitions: ColumnDefinition[] =
+ activeFieldMetadataItems
+ .map((field, index) =>
+ formatFieldMetadataItemAsColumnDefinition({
+ position: index,
+ field,
+ objectMetadataItem,
+ }),
+ )
+ .filter(filterAvailableTableColumns)
+ .map((column) => {
+ const existsInFilterDefinitions = filterableFieldMetadataItems.some(
+ (fieldMetadataItem) =>
+ fieldMetadataItem.id === column.fieldMetadataId,
+ );
+ const existsInSortDefinitions = sortDefinitions.some(
+ (sort) => sort.fieldMetadataId === column.fieldMetadataId,
+ );
+ return {
+ ...column,
+ isFilterable: existsInFilterDefinitions,
+ isSortable: existsInSortDefinitions,
+ };
+ });
return {
columnDefinitions,
diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup.ts b/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup.ts
index c9a7ad93ca81..0e0150e8ab4d 100644
--- a/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup.ts
+++ b/packages/twenty-front/src/modules/object-record/advanced-filter/hooks/useDeleteCombinedViewFilterGroup.ts
@@ -1,9 +1,9 @@
import { useRecoilCallback } from 'recoil';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
+import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState';
import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState';
import { isDefined } from 'twenty-shared';
@@ -24,11 +24,10 @@ export const useDeleteCombinedViewFilterGroup = (
);
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
- currentViewIdComponentState,
- viewBarComponentId,
+ contextStoreCurrentViewIdComponentState,
);
- const { getViewFromCache } = useGetViewFromCache();
+ const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const deleteCombinedViewFilterGroup = useRecoilCallback(
({ snapshot, set }) =>
@@ -56,7 +55,7 @@ export const useDeleteCombinedViewFilterGroup = (
return;
}
- const currentView = await getViewFromCache(currentViewId);
+ const currentView = await getViewFromPrefetchState(currentViewId);
if (!currentView) {
return;
@@ -99,7 +98,7 @@ export const useDeleteCombinedViewFilterGroup = (
},
[
currentViewIdCallbackState,
- getViewFromCache,
+ getViewFromPrefetchState,
unsavedToDeleteViewFilterGroupIdsCallbackState,
unsavedToUpsertViewFilterGroupsCallbackState,
],
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 f4555f7e6b24..8f33b31d67f1 100644
--- a/packages/twenty-front/src/modules/object-record/hooks/useCreateOneRecord.ts
+++ b/packages/twenty-front/src/modules/object-record/hooks/useCreateOneRecord.ts
@@ -116,6 +116,7 @@ export const useCreateOneRecord = <
objectMetadataItem,
objectMetadataItems,
record: recordCreatedInCache,
+ recordGqlFields: computedRecordGqlFields,
computeReferences: false,
});
diff --git a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/__stories__/MultipleFiltersDropdownButton.stories.tsx b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/__stories__/MultipleFiltersDropdownButton.stories.tsx
index 5f67343a98e7..a73505d69bd6 100644
--- a/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/__stories__/MultipleFiltersDropdownButton.stories.tsx
+++ b/packages/twenty-front/src/modules/object-record/object-filter-dropdown/components/__stories__/MultipleFiltersDropdownButton.stories.tsx
@@ -17,6 +17,7 @@ import {
ComponentDecorator,
getCanvasElementForDropdownTesting,
} from 'twenty-ui';
+import { ContextStoreDecorator } from '~/testing/decorators/ContextStoreDecorator';
import { I18nFrontDecorator } from '~/testing/decorators/I18nFrontDecorator';
import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator';
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
@@ -79,6 +80,7 @@ const meta: Meta = {
);
},
+ ContextStoreDecorator,
ObjectMetadataItemsDecorator,
SnackBarDecorator,
ComponentDecorator,
diff --git a/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupFieldsContent.tsx b/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupFieldsContent.tsx
index 314b49c95cef..aaf0287b172a 100644
--- a/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupFieldsContent.tsx
+++ b/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/ObjectOptionsDropdownRecordGroupFieldsContent.tsx
@@ -36,7 +36,6 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
const {
viewType,
currentContentId,
- recordIndexId,
objectMetadataItem,
onContentChange,
resetContent,
@@ -64,9 +63,7 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
const {
handleRecordGroupFieldChange: setRecordGroupField,
resetRecordGroupField,
- } = useHandleRecordGroupField({
- viewBarComponentId: recordIndexId,
- });
+ } = useHandleRecordGroupField();
const newSelectFieldSettingsUrl = getSettingsPath(
SettingsPath.ObjectNewFieldConfigure,
diff --git a/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/__stories__/ObjectOptionsDropdownContent.stories.tsx b/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/__stories__/ObjectOptionsDropdownContent.stories.tsx
index bb06fb6617fc..94251ab53370 100644
--- a/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/__stories__/ObjectOptionsDropdownContent.stories.tsx
+++ b/packages/twenty-front/src/modules/object-record/object-options-dropdown/components/__stories__/ObjectOptionsDropdownContent.stories.tsx
@@ -1,7 +1,6 @@
import { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from 'twenty-ui';
-import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { ObjectOptionsDropdownContent } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdownContent';
import { OBJECT_OPTIONS_DROPDOWN_ID } from '@/object-record/object-options-dropdown/constants/ObjectOptionsDropdownId';
@@ -16,6 +15,7 @@ import { ViewType } from '@/views/types/ViewType';
import { useEffect } from 'react';
import { MemoryRouter } from 'react-router-dom';
import { useSetRecoilState } from 'recoil';
+import { ContextStoreDecorator } from '~/testing/decorators/ContextStoreDecorator';
import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator';
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
@@ -45,21 +45,18 @@ const meta: Meta = {
value={{ instanceId, onColumnsChange: () => {} }}
>
-
-
-
-
-
+
+
);
},
+ ContextStoreDecorator,
ObjectMetadataItemsDecorator,
SnackBarDecorator,
ComponentDecorator,
diff --git a/packages/twenty-front/src/modules/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard.ts b/packages/twenty-front/src/modules/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard.ts
index 3dba54dc3835..607eab23fafc 100644
--- a/packages/twenty-front/src/modules/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard.ts
+++ b/packages/twenty-front/src/modules/object-record/object-options-dropdown/hooks/useObjectOptionsForBoard.ts
@@ -26,13 +26,12 @@ type useObjectOptionsForBoardParams = {
export const useObjectOptionsForBoard = ({
objectNameSingular,
recordBoardId,
- viewBarId,
}: useObjectOptionsForBoardParams) => {
const [recordIndexFieldDefinitions, setRecordIndexFieldDefinitions] =
useRecoilState(recordIndexFieldDefinitionsState);
- const { saveViewFields } = useSaveCurrentViewFields(viewBarId);
- const { updateCurrentView } = useUpdateCurrentView(viewBarId);
+ const { saveViewFields } = useSaveCurrentViewFields();
+ const { updateCurrentView } = useUpdateCurrentView();
const [isCompactModeActive, setIsCompactModeActive] =
useRecoilComponentStateV2(
diff --git a/packages/twenty-front/src/modules/object-record/record-group/hooks/useRecordGroupReorder.ts b/packages/twenty-front/src/modules/object-record/record-group/hooks/useRecordGroupReorder.ts
index e7d124118113..3aeb93d34ed8 100644
--- a/packages/twenty-front/src/modules/object-record/record-group/hooks/useRecordGroupReorder.ts
+++ b/packages/twenty-front/src/modules/object-record/record-group/hooks/useRecordGroupReorder.ts
@@ -23,7 +23,7 @@ export const useRecordGroupReorder = ({
viewBarId,
viewType,
}: UseRecordGroupHandlersParams) => {
- const setRecordGroup = useSetRecordGroup(viewBarId);
+ const setRecordGroup = useSetRecordGroup();
const visibleRecordGroupIdsFamilySelector = useRecoilComponentCallbackStateV2(
visibleRecordGroupIdsComponentFamilySelector,
@@ -78,7 +78,7 @@ export const useRecordGroupReorder = ({
];
}, []);
- setRecordGroup(updatedRecordGroups);
+ setRecordGroup(updatedRecordGroups, viewBarId);
saveViewGroups(
mapRecordGroupDefinitionsToViewGroups(updatedRecordGroups),
);
@@ -86,6 +86,7 @@ export const useRecordGroupReorder = ({
[
saveViewGroups,
setRecordGroup,
+ viewBarId,
viewType,
visibleRecordGroupIdsFamilySelector,
],
diff --git a/packages/twenty-front/src/modules/object-record/record-group/hooks/useSetRecordGroup.ts b/packages/twenty-front/src/modules/object-record/record-group/hooks/useSetRecordGroup.ts
index 96b5d0184f11..fe4c12d0924b 100644
--- a/packages/twenty-front/src/modules/object-record/record-group/hooks/useSetRecordGroup.ts
+++ b/packages/twenty-front/src/modules/object-record/record-group/hooks/useSetRecordGroup.ts
@@ -1,32 +1,33 @@
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
import { recordGroupFieldMetadataComponentState } from '@/object-record/record-group/states/recordGroupFieldMetadataComponentState';
import { recordGroupIdsComponentState } from '@/object-record/record-group/states/recordGroupIdsComponentState';
import { RecordGroupDefinition } from '@/object-record/record-group/types/RecordGroupDefinition';
-import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
-import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
import { useRecoilCallback } from 'recoil';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
-export const useSetRecordGroup = (viewId?: string) => {
- const { objectMetadataItem } = useRecordIndexContextOrThrow();
-
- const recordIndexRecordGroupIdsState = useRecoilComponentCallbackStateV2(
- recordGroupIdsComponentState,
- viewId,
- );
-
- const recordGroupFieldMetadataState = useRecoilComponentCallbackStateV2(
- recordGroupFieldMetadataComponentState,
- viewId,
- );
-
+export const useSetRecordGroup = () => {
return useRecoilCallback(
({ snapshot, set }) =>
- (recordGroups: RecordGroupDefinition[]) => {
+ (recordGroups: RecordGroupDefinition[], recordIndexId: string) => {
+ const objectMetadataItem = snapshot
+ .getLoadable(
+ contextStoreCurrentObjectMetadataItemComponentState.atomFamily({
+ instanceId: 'main-context-store',
+ }),
+ )
+ .getValue();
+
+ if (!objectMetadataItem) {
+ return;
+ }
+
const currentRecordGroupIds = getSnapshotValue(
snapshot,
- recordIndexRecordGroupIdsState,
+ recordGroupIdsComponentState.atomFamily({
+ instanceId: recordIndexId,
+ }),
);
const fieldMetadataId = recordGroups?.[0]?.fieldMetadataId;
const fieldMetadata = fieldMetadataId
@@ -36,12 +37,19 @@ export const useSetRecordGroup = (viewId?: string) => {
: undefined;
const currentFieldMetadata = getSnapshotValue(
snapshot,
- recordGroupFieldMetadataState,
+ recordGroupFieldMetadataComponentState.atomFamily({
+ instanceId: recordIndexId,
+ }),
);
// Set the field metadata linked to the record groups
if (!isDeeplyEqual(fieldMetadata, currentFieldMetadata)) {
- set(recordGroupFieldMetadataState, fieldMetadata);
+ set(
+ recordGroupFieldMetadataComponentState.atomFamily({
+ instanceId: recordIndexId,
+ }),
+ fieldMetadata,
+ );
}
// Set the record groups by id
@@ -75,12 +83,13 @@ export const useSetRecordGroup = (viewId?: string) => {
}
// Set the record group ids
- set(recordIndexRecordGroupIdsState, recordGroupIds);
+ set(
+ recordGroupIdsComponentState.atomFamily({
+ instanceId: recordIndexId,
+ }),
+ recordGroupIds,
+ );
},
- [
- objectMetadataItem.fields,
- recordGroupFieldMetadataState,
- recordIndexRecordGroupIdsState,
- ],
+ [],
);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx
index b2c24e4d7e0f..ad131b51cd08 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx
@@ -1,52 +1,26 @@
import styled from '@emotion/styled';
-import { useRecoilCallback, useRecoilState, useSetRecoilState } from 'recoil';
-import { isDefined } from 'twenty-shared';
+import { useRecoilState } from 'recoil';
-import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
import { ObjectOptionsDropdown } from '@/object-record/object-options-dropdown/components/ObjectOptionsDropdown';
import { RecordIndexBoardContainer } from '@/object-record/record-index/components/RecordIndexBoardContainer';
import { RecordIndexBoardDataLoader } from '@/object-record/record-index/components/RecordIndexBoardDataLoader';
import { RecordIndexBoardDataLoaderEffect } from '@/object-record/record-index/components/RecordIndexBoardDataLoaderEffect';
import { RecordIndexTableContainer } from '@/object-record/record-index/components/RecordIndexTableContainer';
import { RecordIndexViewBarEffect } from '@/object-record/record-index/components/RecordIndexViewBarEffect';
-import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
-import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
-import { recordIndexIsCompactModeActiveState } from '@/object-record/record-index/states/recordIndexIsCompactModeActiveState';
-import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState';
-import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState';
import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState';
import { InformationBannerWrapper } from '@/information-banner/components/InformationBannerWrapper';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
-import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
import { RecordIndexActionMenu } from '@/action-menu/components/RecordIndexActionMenu';
-import { ContextStoreCurrentViewTypeEffect } from '@/context-store/components/ContextStoreCurrentViewTypeEffect';
-import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
-import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType';
-import { useFilterableFieldMetadataItems } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItems';
-import { useSetRecordGroup } from '@/object-record/record-group/hooks/useSetRecordGroup';
import { RecordIndexFiltersToContextStoreEffect } from '@/object-record/record-index/components/RecordIndexFiltersToContextStoreEffect';
import { RecordIndexTableContainerEffect } from '@/object-record/record-index/components/RecordIndexTableContainerEffect';
-import { recordIndexKanbanAggregateOperationState } from '@/object-record/record-index/states/recordIndexKanbanAggregateOperationState';
-import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
-import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState';
-import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation';
-import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { ViewBar } from '@/views/components/ViewBar';
-import { ViewField } from '@/views/types/ViewField';
-import { ViewGroup } from '@/views/types/ViewGroup';
import { ViewType } from '@/views/types/ViewType';
-import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
-import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
-import { mapViewGroupsToRecordGroupDefinitions } from '@/views/utils/mapViewGroupsToRecordGroupDefinitions';
-import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
-import { useCallback } from 'react';
import { FeatureFlagKey } from '~/generated/graphql';
-import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
const StyledContainer = styled.div`
display: flex;
@@ -64,9 +38,7 @@ const StyledContainerWithPadding = styled.div`
`;
export const RecordIndexContainer = () => {
- const [recordIndexViewType, setRecordIndexViewType] = useRecoilState(
- recordIndexViewTypeState,
- );
+ const [recordIndexViewType] = useRecoilState(recordIndexViewTypeState);
const {
objectNamePlural,
@@ -75,128 +47,12 @@ export const RecordIndexContainer = () => {
objectNameSingular,
} = useRecordIndexContextOrThrow();
- const setRecordGroup = useSetRecordGroup(recordIndexId);
-
- const { columnDefinitions, sortDefinitions } =
- useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
-
- const setRecordIndexViewFilterGroups = useSetRecoilState(
- recordIndexViewFilterGroupsState,
- );
- const setRecordIndexFilters = useSetRecoilState(recordIndexFiltersState);
- const setRecordIndexSorts = useSetRecoilState(recordIndexSortsState);
- const setRecordIndexIsCompactModeActive = useSetRecoilState(
- recordIndexIsCompactModeActiveState,
- );
- const setRecordIndexViewKanbanFieldMetadataIdState = useSetRecoilState(
- recordIndexKanbanFieldMetadataIdState,
- );
- const setRecordIndexViewKanbanAggregateOperationState = useSetRecoilState(
- recordIndexKanbanAggregateOperationState,
- );
-
- const {
- setTableViewFilterGroups,
- setTableFilters,
- setTableSorts,
- setTableColumns,
- } = useRecordTable({
- recordTableId: recordIndexId,
- });
-
- const onViewFieldsChange = useRecoilCallback(
- ({ set, snapshot }) =>
- (viewFields: ViewField[]) => {
- const newFieldDefinitions = mapViewFieldsToColumnDefinitions({
- viewFields,
- columnDefinitions,
- });
-
- setTableColumns(newFieldDefinitions);
-
- const existingRecordIndexFieldDefinitions = snapshot
- .getLoadable(recordIndexFieldDefinitionsState)
- .getValue();
-
- if (
- !isDeeplyEqual(
- existingRecordIndexFieldDefinitions,
- newFieldDefinitions,
- )
- ) {
- set(recordIndexFieldDefinitionsState, newFieldDefinitions);
- }
-
- for (const viewField of viewFields) {
- const viewFieldMetadataType = objectMetadataItem.fields?.find(
- (field) => field.id === viewField.fieldMetadataId,
- )?.type;
- const aggregateOperationForViewField = snapshot
- .getLoadable(
- viewFieldAggregateOperationState({
- viewFieldId: viewField.id,
- }),
- )
- .getValue();
-
- const convertedViewFieldAggregateOperation = isDefined(
- viewField.aggregateOperation,
- )
- ? convertAggregateOperationToExtendedAggregateOperation(
- viewField.aggregateOperation,
- viewFieldMetadataType,
- )
- : viewField.aggregateOperation;
-
- if (
- aggregateOperationForViewField !==
- convertedViewFieldAggregateOperation
- ) {
- set(
- viewFieldAggregateOperationState({
- viewFieldId: viewField.id,
- }),
- convertedViewFieldAggregateOperation,
- );
- }
- }
- },
- [columnDefinitions, objectMetadataItem.fields, setTableColumns],
- );
-
- const onViewGroupsChange = useCallback(
- (viewGroups: ViewGroup[]) => {
- const newGroupDefinitions = mapViewGroupsToRecordGroupDefinitions({
- objectMetadataItem,
- viewGroups,
- });
-
- setRecordGroup(newGroupDefinitions);
- },
- [objectMetadataItem, setRecordGroup],
- );
-
- const setContextStoreTargetedRecordsRule = useSetRecoilComponentStateV2(
- contextStoreTargetedRecordsRuleComponentState,
- );
-
- const { filterableFieldMetadataItems } = useFilterableFieldMetadataItems(
- objectMetadataItem.id,
- );
-
const isCommandMenuV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsCommandMenuV2Enabled,
);
return (
<>
-
@@ -210,60 +66,6 @@ export const RecordIndexContainer = () => {
viewType={recordIndexViewType ?? ViewType.Table}
/>
}
- onCurrentViewChange={(view) => {
- if (!view) {
- return;
- }
-
- onViewFieldsChange(view.viewFields);
- onViewGroupsChange(view.viewGroups);
- setTableViewFilterGroups(view.viewFilterGroups ?? []);
- setTableFilters(
- mapViewFiltersToFilters(
- view.viewFilters,
- filterableFieldMetadataItems,
- ),
- );
- setRecordIndexFilters(
- mapViewFiltersToFilters(
- view.viewFilters,
- filterableFieldMetadataItems,
- ),
- );
- setRecordIndexViewFilterGroups(view.viewFilterGroups ?? []);
- setContextStoreTargetedRecordsRule((prev) => ({
- ...prev,
- filters: mapViewFiltersToFilters(
- view.viewFilters,
- filterableFieldMetadataItems,
- ),
- }));
- setTableSorts(
- mapViewSortsToSorts(view.viewSorts, sortDefinitions),
- );
- setRecordIndexSorts(
- mapViewSortsToSorts(view.viewSorts, sortDefinitions),
- );
- setRecordIndexViewType(view.type);
- setRecordIndexViewKanbanFieldMetadataIdState(
- view.kanbanFieldMetadataId,
- );
- const kanbanAggregateOperationFieldMetadataType =
- objectMetadataItem.fields?.find(
- (field) =>
- field.id === view.kanbanAggregateOperationFieldMetadataId,
- )?.type;
- setRecordIndexViewKanbanAggregateOperationState({
- operation: isDefined(view.kanbanAggregateOperation)
- ? convertAggregateOperationToExtendedAggregateOperation(
- view.kanbanAggregateOperation,
- kanbanAggregateOperationFieldMetadataType,
- )
- : view.kanbanAggregateOperation,
- fieldMetadataId: view.kanbanAggregateOperationFieldMetadataId,
- });
- setRecordIndexIsCompactModeActive(view.isCompact);
- }}
/>
{
- const setContextStoreCurrentObjectMetadataItem = useSetRecoilComponentStateV2(
- contextStoreCurrentObjectMetadataIdComponentState,
- );
- const { objectNamePlural } = useRecordIndexContextOrThrow();
-
- const { objectNameSingular } = useObjectNameSingularFromPlural({
- objectNamePlural,
- });
-
- const { objectMetadataItem } = useObjectMetadataItem({
- objectNameSingular,
- });
-
- useEffect(() => {
- setContextStoreCurrentObjectMetadataItem(objectMetadataItem.id);
-
- return () => {
- setContextStoreCurrentObjectMetadataItem(null);
- };
- }, [objectMetadataItem.id, setContextStoreCurrentObjectMetadataItem]);
-
- return null;
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx
new file mode 100644
index 000000000000..5c66bfe5224b
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx
@@ -0,0 +1,97 @@
+import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext';
+
+import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
+import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
+import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
+import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId';
+import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId';
+import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext';
+import { RecordIndexContainer } from '@/object-record/record-index/components/RecordIndexContainer';
+import { RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect } from '@/object-record/record-index/components/RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect';
+import { RecordIndexLoadBaseOnContextStoreEffect } from '@/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect';
+import { RecordIndexPageHeader } from '@/object-record/record-index/components/RecordIndexPageHeader';
+import { useHandleIndexIdentifierClick } from '@/object-record/record-index/hooks/useHandleIndexIdentifierClick';
+import { PageBody } from '@/ui/layout/page/components/PageBody';
+import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
+import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
+import styled from '@emotion/styled';
+import { useRecoilCallback, useRecoilValue } from 'recoil';
+import { capitalize } from 'twenty-shared';
+
+const StyledIndexContainer = styled.div`
+ display: flex;
+ height: 100%;
+ width: 100%;
+`;
+
+export const RecordIndexContainerGater = () => {
+ const mainContextStoreComponentInstanceId = useRecoilValue(
+ mainContextStoreComponentInstanceIdState,
+ );
+
+ const contextStoreCurrentViewId = useRecoilComponentValueV2(
+ contextStoreCurrentViewIdComponentState,
+ mainContextStoreComponentInstanceId,
+ );
+
+ const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
+
+ const recordIndexId = `${objectMetadataItem.namePlural}-${contextStoreCurrentViewId}`;
+
+ const handleIndexRecordsLoaded = useRecoilCallback(
+ ({ set }) =>
+ () => {
+ // TODO: find a better way to reset this state ?
+ set(lastShowPageRecordIdState, null);
+ },
+ [],
+ );
+
+ const { indexIdentifierUrl } = useHandleIndexIdentifierClick({
+ objectMetadataItem,
+ recordIndexId,
+ });
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx
new file mode 100644
index 000000000000..1521b2a5fa23
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexLoadBaseOnContextStoreEffect.tsx
@@ -0,0 +1,52 @@
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
+import { useLoadRecordIndexStates } from '@/object-record/record-index/hooks/useLoadRecordIndexStates';
+import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
+import { useEffect, useState } from 'react';
+import { useRecoilValue } from 'recoil';
+import { isDefined } from 'twenty-shared';
+
+export const RecordIndexLoadBaseOnContextStoreEffect = () => {
+ const { loadRecordIndexStates } = useLoadRecordIndexStates();
+ const contextStoreCurrentViewId = useRecoilComponentValueV2(
+ contextStoreCurrentViewIdComponentState,
+ );
+
+ const [loadedViewId, setLoadedViewId] = useState(
+ undefined,
+ );
+
+ const view = useRecoilValue(
+ prefetchViewFromViewIdFamilySelector({
+ viewId: contextStoreCurrentViewId ?? '',
+ }),
+ );
+
+ const objectMetadataItem = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
+ );
+
+ useEffect(() => {
+ if (loadedViewId === contextStoreCurrentViewId) {
+ return;
+ }
+
+ if (!isDefined(objectMetadataItem)) {
+ return;
+ }
+
+ if (isDefined(view)) {
+ loadRecordIndexStates(view, objectMetadataItem);
+ setLoadedViewId(contextStoreCurrentViewId);
+ }
+ }, [
+ contextStoreCurrentViewId,
+ loadRecordIndexStates,
+ loadedViewId,
+ objectMetadataItem,
+ view,
+ ]);
+
+ return <>>;
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts
index 0cd17e877e1c..efb30e485852 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts
+++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts
@@ -1,7 +1,7 @@
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { AppPath } from '@/types/AppPath';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { getAppPath } from '~/utils/navigation/getAppPath';
export const useHandleIndexIdentifierClick = ({
@@ -12,7 +12,7 @@ export const useHandleIndexIdentifierClick = ({
objectMetadataItem: ObjectMetadataItem;
}) => {
const currentViewId = useRecoilComponentValueV2(
- currentViewIdComponentState,
+ contextStoreCurrentViewIdComponentState,
recordIndexId,
);
diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts
index 2666578bc178..6a0c5d03bd1c 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts
+++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleRecordGroupField.ts
@@ -1,29 +1,22 @@
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { usePersistViewGroupRecords } from '@/views/hooks/internal/usePersistViewGroupRecords';
-import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
+import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { ViewGroup } from '@/views/types/ViewGroup';
import { useRecoilCallback } from 'recoil';
import { v4 } from 'uuid';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
-type UseHandleRecordGroupFieldParams = {
- viewBarComponentId: string;
-};
-
-export const useHandleRecordGroupField = ({
- viewBarComponentId,
-}: UseHandleRecordGroupFieldParams) => {
+export const useHandleRecordGroupField = () => {
const { createViewGroupRecords, deleteViewGroupRecords } =
usePersistViewGroupRecords();
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
- currentViewIdComponentState,
- viewBarComponentId,
+ contextStoreCurrentViewIdComponentState,
);
- const { getViewFromCache } = useGetViewFromCache();
+ const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const handleRecordGroupFieldChange = useRecoilCallback(
({ snapshot }) =>
@@ -36,7 +29,7 @@ export const useHandleRecordGroupField = ({
return;
}
- const view = await getViewFromCache(currentViewId);
+ const view = await getViewFromPrefetchState(currentViewId);
if (isUndefinedOrNull(view)) {
return;
@@ -105,7 +98,7 @@ export const useHandleRecordGroupField = ({
createViewGroupRecords,
deleteViewGroupRecords,
currentViewIdCallbackState,
- getViewFromCache,
+ getViewFromPrefetchState,
],
);
@@ -120,7 +113,7 @@ export const useHandleRecordGroupField = ({
return;
}
- const view = await getViewFromCache(currentViewId);
+ const view = await getViewFromPrefetchState(currentViewId);
if (isUndefinedOrNull(view)) {
return;
@@ -132,7 +125,11 @@ export const useHandleRecordGroupField = ({
await deleteViewGroupRecords(view.viewGroups);
},
- [deleteViewGroupRecords, currentViewIdCallbackState, getViewFromCache],
+ [
+ deleteViewGroupRecords,
+ currentViewIdCallbackState,
+ getViewFromPrefetchState,
+ ],
);
return { handleRecordGroupFieldChange, resetRecordGroupField };
diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoardColumn.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoardColumn.ts
index e105cca850a4..d83eecfb79cd 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoardColumn.ts
+++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexBoardColumn.ts
@@ -6,13 +6,14 @@ import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy';
import { useSetRecordIdsForColumn } from '@/object-record/record-board/hooks/useSetRecordIdsForColumn';
import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies';
+import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { computeViewRecordGqlOperationFilter } from '@/object-record/record-filter/utils/computeViewRecordGqlOperationFilter';
import { recordGroupDefinitionFamilyState } from '@/object-record/record-group/states/recordGroupDefinitionFamilyState';
import { useRecordBoardRecordGqlFields } from '@/object-record/record-index/hooks/useRecordBoardRecordGqlFields';
-import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState';
import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
import { useUpsertRecordsInStore } from '@/object-record/record-store/hooks/useUpsertRecordsInStore';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { isDefined } from 'twenty-shared';
type UseLoadRecordIndexBoardProps = {
@@ -41,14 +42,16 @@ export const useLoadRecordIndexBoardColumn = ({
const recordIndexViewFilterGroups = useRecoilValue(
recordIndexViewFilterGroupsState,
);
- const recordIndexFilters = useRecoilValue(recordIndexFiltersState);
+ const currentRecordFilters = useRecoilComponentValueV2(
+ currentRecordFiltersComponentState,
+ );
const recordIndexSorts = useRecoilValue(recordIndexSortsState);
const { filterValueDependencies } = useFilterValueDependencies();
const requestFilters = computeViewRecordGqlOperationFilter(
filterValueDependencies,
- recordIndexFilters,
+ currentRecordFilters,
objectMetadataItem?.fields ?? [],
recordIndexViewFilterGroups,
);
diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts
new file mode 100644
index 000000000000..ac0a4b8bb472
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useLoadRecordIndexStates.ts
@@ -0,0 +1,281 @@
+import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
+import { availableFieldMetadataItemsForFilterFamilySelector } from '@/object-metadata/states/availableFieldMetadataItemsForFilterFamilySelector';
+import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
+import { formatFieldMetadataItemAsColumnDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsColumnDefinition';
+import { formatFieldMetadataItemsAsSortDefinitions } from '@/object-metadata/utils/formatFieldMetadataItemsAsSortDefinitions';
+import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
+import { useSetRecordGroup } from '@/object-record/record-group/hooks/useSetRecordGroup';
+import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
+import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
+import { recordIndexIsCompactModeActiveState } from '@/object-record/record-index/states/recordIndexIsCompactModeActiveState';
+import { recordIndexKanbanAggregateOperationState } from '@/object-record/record-index/states/recordIndexKanbanAggregateOperationState';
+import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState';
+import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState';
+import { recordIndexViewFilterGroupsState } from '@/object-record/record-index/states/recordIndexViewFilterGroupsState';
+import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState';
+import { useSetTableColumns } from '@/object-record/record-table/hooks/useSetTableColumns';
+import { viewFieldAggregateOperationState } from '@/object-record/record-table/record-table-footer/states/viewFieldAggregateOperationState';
+import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState';
+import { tableSortsComponentState } from '@/object-record/record-table/states/tableSortsComponentState';
+import { tableViewFilterGroupsComponentState } from '@/object-record/record-table/states/tableViewFilterGroupsComponentState';
+import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
+import { convertAggregateOperationToExtendedAggregateOperation } from '@/object-record/utils/convertAggregateOperationToExtendedAggregateOperation';
+import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns';
+import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
+import { View } from '@/views/types/View';
+import { ViewField } from '@/views/types/ViewField';
+import { ViewGroup } from '@/views/types/ViewGroup';
+import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
+import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
+import { mapViewGroupsToRecordGroupDefinitions } from '@/views/utils/mapViewGroupsToRecordGroupDefinitions';
+import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
+import { useCallback } from 'react';
+import { useRecoilCallback, useSetRecoilState } from 'recoil';
+import { isDefined } from 'twenty-shared';
+import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
+
+export const useLoadRecordIndexStates = () => {
+ const setContextStoreTargetedRecordsRuleComponentState =
+ useSetRecoilComponentStateV2(contextStoreTargetedRecordsRuleComponentState);
+
+ const setRecordIndexViewFilterGroups = useSetRecoilState(
+ recordIndexViewFilterGroupsState,
+ );
+
+ const setRecordIndexFilters = useSetRecoilState(recordIndexFiltersState);
+ const setRecordIndexSorts = useSetRecoilState(recordIndexSortsState);
+ const setRecordIndexIsCompactModeActive = useSetRecoilState(
+ recordIndexIsCompactModeActiveState,
+ );
+ const setRecordIndexViewType = useSetRecoilState(recordIndexViewTypeState);
+ const setRecordIndexViewKanbanFieldMetadataIdState = useSetRecoilState(
+ recordIndexKanbanFieldMetadataIdState,
+ );
+ const setRecordIndexViewKanbanAggregateOperationState = useSetRecoilState(
+ recordIndexKanbanAggregateOperationState,
+ );
+ const setRecordGroup = useSetRecordGroup();
+
+ const { setTableColumns } = useSetTableColumns();
+
+ const onViewFieldsChange = useRecoilCallback(
+ ({ set, snapshot }) =>
+ (
+ viewFields: ViewField[],
+ objectMetadataItem: ObjectMetadataItem,
+ recordIndexId: string,
+ ) => {
+ const activeFieldMetadataItems = objectMetadataItem.fields.filter(
+ ({ isActive, isSystem }) => isActive && !isSystem,
+ );
+
+ const filterableFieldMetadataItems = snapshot
+ .getLoadable(
+ availableFieldMetadataItemsForFilterFamilySelector({
+ objectMetadataItemId: objectMetadataItem.id,
+ }),
+ )
+ .getValue();
+
+ const sortDefinitions = formatFieldMetadataItemsAsSortDefinitions({
+ fields: activeFieldMetadataItems,
+ });
+
+ const columnDefinitions: ColumnDefinition[] =
+ activeFieldMetadataItems
+ .map((field, index) =>
+ formatFieldMetadataItemAsColumnDefinition({
+ position: index,
+ field,
+ objectMetadataItem,
+ }),
+ )
+ .filter(filterAvailableTableColumns)
+ .map((column) => {
+ const existsInFilterDefinitions =
+ filterableFieldMetadataItems.some(
+ (fieldMetadataItem) =>
+ fieldMetadataItem.id === column.fieldMetadataId,
+ );
+ const existsInSortDefinitions = sortDefinitions.some(
+ (sort) => sort.fieldMetadataId === column.fieldMetadataId,
+ );
+ return {
+ ...column,
+ isFilterable: existsInFilterDefinitions,
+ isSortable: existsInSortDefinitions,
+ };
+ });
+
+ const newFieldDefinitions = mapViewFieldsToColumnDefinitions({
+ viewFields,
+ columnDefinitions,
+ });
+
+ setTableColumns(newFieldDefinitions, recordIndexId);
+
+ const existingRecordIndexFieldDefinitions = snapshot
+ .getLoadable(recordIndexFieldDefinitionsState)
+ .getValue();
+ if (
+ !isDeeplyEqual(
+ existingRecordIndexFieldDefinitions,
+ newFieldDefinitions,
+ )
+ ) {
+ set(recordIndexFieldDefinitionsState, newFieldDefinitions);
+ }
+
+ for (const viewField of viewFields) {
+ const viewFieldMetadataType = objectMetadataItem.fields?.find(
+ (field) => field.id === viewField.fieldMetadataId,
+ )?.type;
+
+ const aggregateOperationForViewField = snapshot
+ .getLoadable(
+ viewFieldAggregateOperationState({
+ viewFieldId: viewField.id,
+ }),
+ )
+ .getValue();
+ const convertedViewFieldAggregateOperation = isDefined(
+ viewField.aggregateOperation,
+ )
+ ? convertAggregateOperationToExtendedAggregateOperation(
+ viewField.aggregateOperation,
+ viewFieldMetadataType,
+ )
+ : viewField.aggregateOperation;
+
+ if (
+ aggregateOperationForViewField !==
+ convertedViewFieldAggregateOperation
+ ) {
+ set(
+ viewFieldAggregateOperationState({
+ viewFieldId: viewField.id,
+ }),
+ convertedViewFieldAggregateOperation,
+ );
+ }
+ }
+ },
+ [setTableColumns],
+ );
+
+ const onViewGroupsChange = useCallback(
+ (
+ viewGroups: ViewGroup[],
+ objectMetadataItem: ObjectMetadataItem,
+ recordIndexId: string,
+ ) => {
+ const newGroupDefinitions = mapViewGroupsToRecordGroupDefinitions({
+ objectMetadataItem,
+ viewGroups,
+ });
+
+ setRecordGroup(newGroupDefinitions, recordIndexId);
+ },
+ [setRecordGroup],
+ );
+
+ const loadRecordIndexStates = useRecoilCallback(
+ ({ snapshot, set }) =>
+ async (view: View, objectMetadataItem: ObjectMetadataItem) => {
+ const recordIndexId = `${objectMetadataItem.namePlural}-${view.id}`;
+
+ const filterableFieldMetadataItems = snapshot
+ .getLoadable(
+ availableFieldMetadataItemsForFilterFamilySelector({
+ objectMetadataItemId: objectMetadataItem.id,
+ }),
+ )
+ .getValue();
+
+ onViewFieldsChange(view.viewFields, objectMetadataItem, recordIndexId);
+ onViewGroupsChange(view.viewGroups, objectMetadataItem, recordIndexId);
+ set(
+ tableViewFilterGroupsComponentState.atomFamily({
+ instanceId: recordIndexId,
+ }),
+ view.viewFilterGroups ?? [],
+ );
+ set(
+ tableFiltersComponentState.atomFamily({
+ instanceId: recordIndexId,
+ }),
+ mapViewFiltersToFilters(
+ view.viewFilters,
+ filterableFieldMetadataItems,
+ ),
+ );
+ setRecordIndexFilters(
+ mapViewFiltersToFilters(
+ view.viewFilters,
+ filterableFieldMetadataItems,
+ ),
+ );
+ setRecordIndexViewFilterGroups(view.viewFilterGroups ?? []);
+ setContextStoreTargetedRecordsRuleComponentState((prev) => ({
+ ...prev,
+ filters: mapViewFiltersToFilters(
+ view.viewFilters,
+ filterableFieldMetadataItems,
+ ),
+ }));
+
+ const activeFieldMetadataItems = objectMetadataItem.fields.filter(
+ ({ isActive, isSystem }) => isActive && !isSystem,
+ );
+
+ const sortDefinitions = formatFieldMetadataItemsAsSortDefinitions({
+ fields: activeFieldMetadataItems,
+ });
+
+ set(
+ tableSortsComponentState.atomFamily({
+ instanceId: recordIndexId,
+ }),
+ mapViewSortsToSorts(view.viewSorts, sortDefinitions),
+ );
+ setRecordIndexSorts(
+ mapViewSortsToSorts(view.viewSorts, sortDefinitions),
+ );
+ setRecordIndexViewType(view.type);
+ setRecordIndexViewKanbanFieldMetadataIdState(
+ view.kanbanFieldMetadataId,
+ );
+ const kanbanAggregateOperationFieldMetadataType =
+ objectMetadataItem.fields?.find(
+ (field) =>
+ field.id === view.kanbanAggregateOperationFieldMetadataId,
+ )?.type;
+ setRecordIndexViewKanbanAggregateOperationState({
+ operation: isDefined(view.kanbanAggregateOperation)
+ ? convertAggregateOperationToExtendedAggregateOperation(
+ view.kanbanAggregateOperation,
+ kanbanAggregateOperationFieldMetadataType,
+ )
+ : view.kanbanAggregateOperation,
+ fieldMetadataId: view.kanbanAggregateOperationFieldMetadataId,
+ });
+ setRecordIndexIsCompactModeActive(view.isCompact);
+ },
+ [
+ onViewFieldsChange,
+ onViewGroupsChange,
+ setContextStoreTargetedRecordsRuleComponentState,
+ setRecordIndexFilters,
+ setRecordIndexIsCompactModeActive,
+ setRecordIndexSorts,
+ setRecordIndexViewFilterGroups,
+ setRecordIndexViewKanbanAggregateOperationState,
+ setRecordIndexViewKanbanFieldMetadataIdState,
+ setRecordIndexViewType,
+ ],
+ );
+
+ return {
+ loadRecordIndexStates,
+ };
+};
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 2b837c33fa19..0e572e3ccf7f 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
@@ -3,9 +3,6 @@ import { ShowPageContainer } from '@/ui/layout/page/components/ShowPageContainer
import { InformationBannerDeletedRecord } from '@/information-banner/components/deleted-record/InformationBannerDeletedRecord';
-import { ContextStoreCurrentViewTypeEffect } from '@/context-store/components/ContextStoreCurrentViewTypeEffect';
-import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType';
-import { RecordShowContainerContextStoreObjectMetadataIdEffect } from '@/object-record/record-show/components/RecordShowContainerContextStoreObjectMetadataIdEffect';
import { RecordShowContainerContextStoreTargetedRecordsEffect } from '@/object-record/record-show/components/RecordShowContainerContextStoreTargetedRecordsEffect';
import { useRecordShowContainerData } from '@/object-record/record-show/hooks/useRecordShowContainerData';
import { useRecordShowContainerTabs } from '@/object-record/record-show/hooks/useRecordShowContainerTabs';
@@ -45,16 +42,9 @@ export const RecordShowContainer = ({
return (
<>
-
-
{recordFromStore && recordFromStore.deletedAt && (
{
- const setContextStoreCurrentObjectMetadataId = useSetRecoilComponentStateV2(
- contextStoreCurrentObjectMetadataIdComponentState,
- );
-
- const { objectMetadataItem } = useObjectMetadataItem({
- objectNameSingular: objectNameSingular,
- });
-
- useEffect(() => {
- setContextStoreCurrentObjectMetadataId(objectMetadataItem?.id);
-
- return () => {
- setContextStoreCurrentObjectMetadataId(null);
- };
- }, [recordId, setContextStoreCurrentObjectMetadataId, objectMetadataItem.id]);
-
- return null;
-};
diff --git a/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
index 460f60a1ab20..f089ee8c7a4b 100644
--- a/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
+++ b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts
@@ -39,7 +39,6 @@ export const useRecordShowPagePagination = (
const { filter, orderBy } =
useQueryVariablesFromActiveFieldsOfViewOrDefaultView({
objectMetadataItem,
- viewId: viewIdQueryParam,
});
const { loading: loadingCursor, pageInfo: currentRecordsPageInfo } =
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 dfee520a74b1..6d70fa91698a 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
@@ -23,14 +23,12 @@ import { useRecordPicker } from '@/object-record/relation-picker/hooks/useRecord
import { RecordPickerComponentInstanceContext } from '@/object-record/relation-picker/states/contexts/RecordPickerComponentInstanceContext';
import { RecordForSelect } from '@/object-record/relation-picker/types/RecordForSelect';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchIndexViewIdFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector';
import { AppPath } from '@/types/AppPath';
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 { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
-import { View } from '@/views/types/View';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { useLingui } from '@lingui/react/macro';
import { RelationDefinitionType } from '~/generated-metadata/graphql';
@@ -123,12 +121,10 @@ export const RecordDetailRelationSection = ({
scopeId: dropdownId,
});
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
-
- const indexView = views.find(
- (view) =>
- view.key === 'INDEX' &&
- view.objectMetadataId === relationObjectMetadataItem.id,
+ const indexViewId = useRecoilValue(
+ prefetchIndexViewIdFromObjectMetadataItemFamilySelector({
+ objectMetadataItemId: relationObjectMetadataItem.id,
+ }),
);
const filterQueryParams = {
@@ -139,7 +135,7 @@ export const RecordDetailRelationSection = ({
},
},
},
- view: indexView?.id,
+ view: indexViewId,
};
const filterLinkHref = getAppPath(
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx
index 30827c224998..575dd0673012 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableWithWrappers.tsx
@@ -75,7 +75,7 @@ export const RecordTableWithWrappers = ({
ActionBarHotkeyScope.ActionBar,
);
- const { saveViewFields } = useSaveCurrentViewFields(viewBarId);
+ const { saveViewFields } = useSaveCurrentViewFields();
const { deleteOneRecord } = useDeleteOneRecord({ objectNameSingular });
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts
index cd54668fd1d9..d0d6784ea033 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useRecordTable.ts
@@ -22,11 +22,9 @@ import { onColumnsChangeComponentState } from '@/object-record/record-table/stat
import { onEntityCountChangeComponentState } from '@/object-record/record-table/states/onEntityCountChangeComponentState';
import { onToggleColumnFilterComponentState } from '@/object-record/record-table/states/onToggleColumnFilterComponentState';
import { onToggleColumnSortComponentState } from '@/object-record/record-table/states/onToggleColumnSortComponentState';
-import { tableColumnsComponentState } from '@/object-record/record-table/states/tableColumnsComponentState';
import { tableFiltersComponentState } from '@/object-record/record-table/states/tableFiltersComponentState';
import { tableLastRowVisibleComponentState } from '@/object-record/record-table/states/tableLastRowVisibleComponentState';
import { tableSortsComponentState } from '@/object-record/record-table/states/tableSortsComponentState';
-import { tableViewFilterGroupsComponentState } from '@/object-record/record-table/states/tableViewFilterGroupsComponentState';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
@@ -53,11 +51,6 @@ export const useRecordTable = (props?: useRecordTableProps) => {
recordTableId,
);
- const tableColumnsState = useRecoilComponentCallbackStateV2(
- tableColumnsComponentState,
- recordTableId,
- );
-
const setAvailableTableColumns = useRecoilCallback(
({ snapshot, set }) =>
(columns: ColumnDefinition[]) => {
@@ -74,29 +67,11 @@ export const useRecordTable = (props?: useRecordTableProps) => {
[availableTableColumnsState],
);
- const setTableColumns = useRecoilCallback(
- ({ snapshot, set }) =>
- (columns: ColumnDefinition[]) => {
- const tableColumns = getSnapshotValue(snapshot, tableColumnsState);
-
- if (isDeeplyEqual(tableColumns, columns)) {
- return;
- }
- set(tableColumnsState, columns);
- },
- [tableColumnsState],
- );
-
const setOnEntityCountChange = useSetRecoilComponentStateV2(
onEntityCountChangeComponentState,
recordTableId,
);
- const setTableViewFilterGroups = useSetRecoilComponentStateV2(
- tableViewFilterGroupsComponentState,
- recordTableId,
- );
-
const setTableFilters = useSetRecoilComponentStateV2(
tableFiltersComponentState,
recordTableId,
@@ -255,12 +230,10 @@ export const useRecordTable = (props?: useRecordTableProps) => {
return {
onColumnsChange,
setAvailableTableColumns,
- setTableViewFilterGroups,
setTableFilters,
setTableSorts,
setOnEntityCountChange,
setRecordTableData,
- setTableColumns,
leaveTableFocus,
setRowSelected,
resetTableRowSelection,
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useSetTableColumns.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useSetTableColumns.ts
new file mode 100644
index 000000000000..5739235d85d7
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useSetTableColumns.ts
@@ -0,0 +1,33 @@
+import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
+import { tableColumnsComponentState } from '@/object-record/record-table/states/tableColumnsComponentState';
+import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
+import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
+import { useRecoilCallback } from 'recoil';
+import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
+
+export const useSetTableColumns = () => {
+ const setTableColumns = useRecoilCallback(
+ ({ snapshot, set }) =>
+ (columns: ColumnDefinition[], recordTableId: string) => {
+ const tableColumns = getSnapshotValue(
+ snapshot,
+ tableColumnsComponentState.atomFamily({
+ instanceId: recordTableId,
+ }),
+ );
+
+ if (isDeeplyEqual(tableColumns, columns)) {
+ return;
+ }
+ set(
+ tableColumnsComponentState.atomFamily({
+ instanceId: recordTableId,
+ }),
+ columns,
+ );
+ },
+ [],
+ );
+
+ return { setTableColumns };
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/useTableColumns.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/useTableColumns.ts
index f972e41e97a6..707429be0389 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/hooks/useTableColumns.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/useTableColumns.ts
@@ -4,9 +4,12 @@ import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata'
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { useMoveViewColumns } from '@/views/hooks/useMoveViewColumns';
+import { useSetTableColumns } from '@/object-record/record-table/hooks/useSetTableColumns';
import { availableTableColumnsComponentState } from '@/object-record/record-table/states/availableTableColumnsComponentState';
+import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
import { visibleTableColumnsComponentSelector } from '@/object-record/record-table/states/selectors/visibleTableColumnsComponentSelector';
import { tableColumnsComponentState } from '@/object-record/record-table/states/tableColumnsComponentState';
+import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { ColumnDefinition } from '../types/ColumnDefinition';
@@ -15,10 +18,12 @@ type useRecordTableProps = {
};
export const useTableColumns = (props?: useRecordTableProps) => {
- const { onColumnsChange, setTableColumns } = useRecordTable({
+ const { onColumnsChange } = useRecordTable({
recordTableId: props?.recordTableId,
});
+ const { setTableColumns } = useSetTableColumns();
+
const availableTableColumns = useRecoilComponentValueV2(
availableTableColumnsComponentState,
props?.recordTableId,
@@ -35,13 +40,18 @@ export const useTableColumns = (props?: useRecordTableProps) => {
const { handleColumnMove } = useMoveViewColumns();
+ const instanceId = useAvailableComponentInstanceIdOrThrow(
+ RecordTableComponentInstanceContext,
+ props?.recordTableId,
+ );
+
const handleColumnsChange = useCallback(
async (columns: ColumnDefinition[]) => {
- setTableColumns(columns);
+ setTableColumns(columns, instanceId);
await onColumnsChange?.(columns);
},
- [onColumnsChange, setTableColumns],
+ [setTableColumns, instanceId, onColumnsChange],
);
const handleColumnVisibilityChange = useCallback(
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBodyEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBodyEffect.tsx
index 8e3466afd336..64b994226b0c 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBodyEffect.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableNoRecordGroupBodyEffect.tsx
@@ -55,6 +55,8 @@ export const RecordTableNoRecordGroupBodyEffect = () => {
lastShowPageRecordIdState,
);
+ const [hasInitialized, setHasInitialized] = useState(false);
+
const { scrollToPosition } = useScrollToPosition();
useEffect(() => {
@@ -141,8 +143,11 @@ export const RecordTableNoRecordGroupBodyEffect = () => {
return;
}
- findManyRecords();
- }, [currentWorkspaceMember, findManyRecords]);
+ if (!hasInitialized) {
+ findManyRecords();
+ setHasInitialized(true);
+ }
+ }, [currentWorkspaceMember, findManyRecords, hasInitialized]);
return <>>;
};
diff --git a/packages/twenty-front/src/modules/prefetch/components/PrefetchDataProvider.tsx b/packages/twenty-front/src/modules/prefetch/components/PrefetchDataProvider.tsx
index 04fdb0a21c7b..1b358a3ede63 100644
--- a/packages/twenty-front/src/modules/prefetch/components/PrefetchDataProvider.tsx
+++ b/packages/twenty-front/src/modules/prefetch/components/PrefetchDataProvider.tsx
@@ -1,10 +1,12 @@
-import { PrefetchRunQueriesEffect } from '@/prefetch/components/PrefetchRunQueriesEffect';
+import { PrefetchRunFavoriteQueriesEffect } from '@/prefetch/components/PrefetchRunFavoriteQueriesEffect';
+import { PrefetchRunViewQueryEffect } from '@/prefetch/components/PrefetchRunViewQueryEffect';
import React from 'react';
export const PrefetchDataProvider = ({ children }: React.PropsWithChildren) => {
return (
<>
-
+
+
{children}
>
);
diff --git a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunFavoriteQueriesEffect.tsx b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunFavoriteQueriesEffect.tsx
new file mode 100644
index 000000000000..ef12342d333c
--- /dev/null
+++ b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunFavoriteQueriesEffect.tsx
@@ -0,0 +1,110 @@
+import { useEffect } from 'react';
+import { useRecoilCallback, useRecoilValue, useSetRecoilState } from 'recoil';
+
+import { currentUserState } from '@/auth/states/currentUserState';
+import { Favorite } from '@/favorites/types/Favorite';
+import { FavoriteFolder } from '@/favorites/types/FavoriteFolder';
+import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
+import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
+import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
+import { findAllFavoritesFolderOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllFavoritesFolderOperationSignatureFactory';
+import { findAllFavoritesOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllFavoritesOperationSignatureFactory';
+import { prefetchFavoriteFoldersState } from '@/prefetch/states/prefetchFavoriteFoldersState';
+import { prefetchFavoritesState } from '@/prefetch/states/prefetchFavoritesState';
+import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedFamilyState';
+import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { useIsWorkspaceActivationStatusSuspended } from '@/workspace/hooks/useIsWorkspaceActivationStatusSuspended';
+import { isDefined } from 'twenty-shared';
+import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
+
+export const PrefetchRunFavoriteQueriesEffect = () => {
+ const currentUser = useRecoilValue(currentUserState);
+
+ const isWorkspaceSuspended = useIsWorkspaceActivationStatusSuspended();
+
+ const { objectMetadataItems } = useObjectMetadataItems();
+
+ const setIsPrefetchFavoritesLoaded = useSetRecoilState(
+ prefetchIsLoadedFamilyState(PrefetchKey.AllFavorites),
+ );
+
+ const setIsPrefetchFavoritesFoldersLoaded = useSetRecoilState(
+ prefetchIsLoadedFamilyState(PrefetchKey.AllFavoritesFolders),
+ );
+
+ const findAllFavoritesOperationSignature =
+ findAllFavoritesOperationSignatureFactory({
+ objectMetadataItem: objectMetadataItems.find(
+ (item) => item.nameSingular === CoreObjectNameSingular.Favorite,
+ ),
+ });
+
+ const findAllFavoriteFoldersOperationSignature =
+ findAllFavoritesFolderOperationSignatureFactory({
+ objectMetadataItem: objectMetadataItems.find(
+ (item) => item.nameSingular === CoreObjectNameSingular.FavoriteFolder,
+ ),
+ });
+
+ const { records: favorites } = useFindManyRecords({
+ objectNameSingular: CoreObjectNameSingular.Favorite,
+ filter: findAllFavoritesOperationSignature.variables.filter,
+ recordGqlFields: findAllFavoritesOperationSignature.fields,
+ skip: !currentUser || isWorkspaceSuspended,
+ });
+
+ const { records: favoriteFolders } = useFindManyRecords({
+ objectNameSingular: CoreObjectNameSingular.FavoriteFolder,
+ filter: findAllFavoriteFoldersOperationSignature.variables.filter,
+ recordGqlFields: findAllFavoriteFoldersOperationSignature.fields,
+ skip: !currentUser || isWorkspaceSuspended,
+ });
+
+ const setPrefetchFavoritesState = useRecoilCallback(
+ ({ set, snapshot }) =>
+ (favorites: Favorite[]) => {
+ const existingFavorites = snapshot
+ .getLoadable(prefetchFavoritesState)
+ .getValue();
+
+ if (!isDeeplyEqual(existingFavorites, favorites)) {
+ set(prefetchFavoritesState, favorites);
+ }
+ },
+ [],
+ );
+
+ const setPrefetchFavoriteFoldersState = useRecoilCallback(
+ ({ set, snapshot }) =>
+ (favoriteFolders: FavoriteFolder[]) => {
+ const existingFavoriteFolders = snapshot
+ .getLoadable(prefetchFavoriteFoldersState)
+ .getValue();
+
+ if (!isDeeplyEqual(existingFavoriteFolders, favoriteFolders)) {
+ set(prefetchFavoriteFoldersState, favoriteFolders);
+ }
+ },
+ [],
+ );
+
+ useEffect(() => {
+ if (isDefined(favorites)) {
+ setPrefetchFavoritesState(favorites as Favorite[]);
+ setIsPrefetchFavoritesLoaded(true);
+ }
+ }, [favorites, setPrefetchFavoritesState, setIsPrefetchFavoritesLoaded]);
+
+ useEffect(() => {
+ if (isDefined(favoriteFolders)) {
+ setPrefetchFavoriteFoldersState(favoriteFolders as FavoriteFolder[]);
+ setIsPrefetchFavoritesFoldersLoaded(true);
+ }
+ }, [
+ favoriteFolders,
+ setPrefetchFavoriteFoldersState,
+ setIsPrefetchFavoritesFoldersLoaded,
+ ]);
+
+ return <>>;
+};
diff --git a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx
deleted file mode 100644
index 2c4d1f916992..000000000000
--- a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunQueriesEffect.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-import { useEffect } from 'react';
-import { useRecoilValue } from 'recoil';
-
-import { currentUserState } from '@/auth/states/currentUserState';
-import { Favorite } from '@/favorites/types/Favorite';
-import { FavoriteFolder } from '@/favorites/types/FavoriteFolder';
-import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
-import { useCombinedFindManyRecords } from '@/object-record/multiple-objects/hooks/useCombinedFindManyRecords';
-import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig';
-import { useUpsertRecordsInCacheForPrefetchKey } from '@/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
-import { View } from '@/views/types/View';
-import { useIsWorkspaceActivationStatusSuspended } from '@/workspace/hooks/useIsWorkspaceActivationStatusSuspended';
-import { isDefined } from 'twenty-shared';
-
-export const PrefetchRunQueriesEffect = () => {
- const currentUser = useRecoilValue(currentUserState);
-
- const isWorkspaceSuspended = useIsWorkspaceActivationStatusSuspended();
-
- const { upsertRecordsInCache: upsertViewsInCache } =
- useUpsertRecordsInCacheForPrefetchKey({
- prefetchKey: PrefetchKey.AllViews,
- });
-
- const { upsertRecordsInCache: upsertFavoritesInCache } =
- useUpsertRecordsInCacheForPrefetchKey({
- prefetchKey: PrefetchKey.AllFavorites,
- });
- const { upsertRecordsInCache: upsertFavoritesFoldersInCache } =
- useUpsertRecordsInCacheForPrefetchKey({
- prefetchKey: PrefetchKey.AllFavoritesFolders,
- });
- const { objectMetadataItems } = useObjectMetadataItems();
-
- const operationSignatures = Object.values(PREFETCH_CONFIG)
-
- .map(({ objectNameSingular, operationSignatureFactory }) => {
- const objectMetadataItem = objectMetadataItems.find(
- (item) => item.nameSingular === objectNameSingular,
- );
-
- return operationSignatureFactory({ objectMetadataItem });
- });
-
- const { result } = useCombinedFindManyRecords({
- operationSignatures,
- skip: !currentUser || isWorkspaceSuspended,
- });
-
- useEffect(() => {
- if (isDefined(result.views)) {
- upsertViewsInCache(result.views as View[]);
- }
-
- if (isDefined(result.favorites)) {
- upsertFavoritesInCache(result.favorites as Favorite[]);
- }
- if (isDefined(result.favoriteFolders)) {
- upsertFavoritesFoldersInCache(result.favoriteFolders as FavoriteFolder[]);
- }
- }, [
- result,
- upsertViewsInCache,
- upsertFavoritesInCache,
- upsertFavoritesFoldersInCache,
- ]);
-
- return <>>;
-};
diff --git a/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx
new file mode 100644
index 000000000000..fbb5bb8cd3dc
--- /dev/null
+++ b/packages/twenty-front/src/modules/prefetch/components/PrefetchRunViewQueryEffect.tsx
@@ -0,0 +1,59 @@
+import { useEffect } from 'react';
+import { useRecoilCallback, useRecoilValue } from 'recoil';
+
+import { currentUserState } from '@/auth/states/currentUserState';
+import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
+import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
+import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
+import { findAllViewsOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllViewsOperationSignatureFactory';
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
+import { isPersistingViewFieldsState } from '@/views/states/isPersistingViewFieldsState';
+import { View } from '@/views/types/View';
+import { useIsWorkspaceActivationStatusSuspended } from '@/workspace/hooks/useIsWorkspaceActivationStatusSuspended';
+import { isDefined } from 'twenty-shared';
+import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
+
+export const PrefetchRunViewQueryEffect = () => {
+ const currentUser = useRecoilValue(currentUserState);
+
+ const isWorkspaceSuspended = useIsWorkspaceActivationStatusSuspended();
+
+ const { objectMetadataItems } = useObjectMetadataItems();
+
+ const findAllViewsOperationSignature = findAllViewsOperationSignatureFactory({
+ objectMetadataItem: objectMetadataItems.find(
+ (item) => item.nameSingular === CoreObjectNameSingular.View,
+ ),
+ });
+
+ const { records } = useFindManyRecords({
+ objectNameSingular: CoreObjectNameSingular.View,
+ filter: findAllViewsOperationSignature.variables.filter,
+ recordGqlFields: findAllViewsOperationSignature.fields,
+ skip: !currentUser || isWorkspaceSuspended,
+ });
+
+ const setPrefetchViewsState = useRecoilCallback(
+ ({ set, snapshot }) =>
+ (views: View[]) => {
+ const existingViews = snapshot
+ .getLoadable(prefetchViewsState)
+ .getValue();
+
+ if (!isDeeplyEqual(existingViews, views)) {
+ set(prefetchViewsState, views);
+ }
+ },
+ [],
+ );
+
+ const isPersistingViewFields = useRecoilValue(isPersistingViewFieldsState);
+
+ useEffect(() => {
+ if (isDefined(records) && !isPersistingViewFields) {
+ setPrefetchViewsState(records as View[]);
+ }
+ }, [isPersistingViewFields, records, setPrefetchViewsState]);
+
+ return <>>;
+};
diff --git a/packages/twenty-front/src/modules/prefetch/constants/PrefetchConfig.ts b/packages/twenty-front/src/modules/prefetch/constants/PrefetchConfig.ts
index ee3e1dab0f55..a3fbb9d45508 100644
--- a/packages/twenty-front/src/modules/prefetch/constants/PrefetchConfig.ts
+++ b/packages/twenty-front/src/modules/prefetch/constants/PrefetchConfig.ts
@@ -2,7 +2,6 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
import { RecordGqlOperationSignatureFactory } from '@/object-record/graphql/types/RecordGqlOperationSignatureFactory';
import { findAllFavoritesFolderOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllFavoritesFolderOperationSignatureFactory';
import { findAllFavoritesOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllFavoritesOperationSignatureFactory';
-import { findAllViewsOperationSignatureFactory } from '@/prefetch/graphql/operation-signatures/factories/findAllViewsOperationSignatureFactory';
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
export const PREFETCH_CONFIG: Record<
@@ -12,10 +11,6 @@ export const PREFETCH_CONFIG: Record<
operationSignatureFactory: RecordGqlOperationSignatureFactory;
}
> = {
- ALL_VIEWS: {
- objectNameSingular: CoreObjectNameSingular.View,
- operationSignatureFactory: findAllViewsOperationSignatureFactory,
- },
ALL_FAVORITES: {
objectNameSingular: CoreObjectNameSingular.Favorite,
operationSignatureFactory: findAllFavoritesOperationSignatureFactory,
diff --git a/packages/twenty-front/src/modules/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey.ts b/packages/twenty-front/src/modules/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey.ts
deleted file mode 100644
index 381166c1bbdb..000000000000
--- a/packages/twenty-front/src/modules/prefetch/hooks/internal/useUpsertRecordsInCacheForPrefetchKey.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import { useSetRecoilState } from 'recoil';
-
-import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
-import { useUpsertFindManyRecordsQueryInCache } from '@/object-record/cache/hooks/useUpsertFindManyRecordsQueryInCache';
-import { ObjectRecord } from '@/object-record/types/ObjectRecord';
-import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig';
-import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedFamilyState';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
-
-export type UsePrefetchRunQuery = {
- prefetchKey: PrefetchKey;
-};
-
-export const useUpsertRecordsInCacheForPrefetchKey = ({
- prefetchKey,
-}: UsePrefetchRunQuery) => {
- const setPrefetchDataIsLoaded = useSetRecoilState(
- prefetchIsLoadedFamilyState(prefetchKey),
- );
-
- const { operationSignatureFactory, objectNameSingular } =
- PREFETCH_CONFIG[prefetchKey];
-
- const { objectMetadataItem } = useObjectMetadataItem({
- objectNameSingular,
- });
-
- const operationSignature = operationSignatureFactory({ objectMetadataItem });
-
- const { upsertFindManyRecordsQueryInCache } =
- useUpsertFindManyRecordsQueryInCache({
- objectMetadataItem: objectMetadataItem,
- });
-
- const upsertRecordsInCache = (records: T[]) => {
- setPrefetchDataIsLoaded(false);
-
- upsertFindManyRecordsQueryInCache({
- queryVariables: operationSignature.variables,
- recordGqlFields: operationSignature.fields,
- objectRecordsToOverwrite: records,
- computeReferences: false,
- });
- setPrefetchDataIsLoaded(true);
- };
-
- return {
- objectMetadataItem,
- upsertRecordsInCache,
- };
-};
diff --git a/packages/twenty-front/src/modules/prefetch/hooks/useIsPrefetchLoading.ts b/packages/twenty-front/src/modules/prefetch/hooks/useIsPrefetchLoading.ts
index ceaab4bd61d0..6135236df05e 100644
--- a/packages/twenty-front/src/modules/prefetch/hooks/useIsPrefetchLoading.ts
+++ b/packages/twenty-front/src/modules/prefetch/hooks/useIsPrefetchLoading.ts
@@ -9,17 +9,12 @@ export const useIsPrefetchLoading = () => {
prefetchIsLoadedFamilyState(PrefetchKey.AllFavoritesFolders),
);
- const areViewsPrefetched = useRecoilValue(
- prefetchIsLoadedFamilyState(PrefetchKey.AllViews),
- );
const areFavoritesPrefetched = useRecoilValue(
prefetchIsLoadedFamilyState(PrefetchKey.AllFavorites),
);
return (
!isWorkspaceSuspended &&
- (!areViewsPrefetched ||
- !areFavoritesPrefetched ||
- !isFavoriteFoldersPrefetched)
+ (!areFavoritesPrefetched || !isFavoriteFoldersPrefetched)
);
};
diff --git a/packages/twenty-front/src/modules/prefetch/hooks/useLazyPrefetchData.ts b/packages/twenty-front/src/modules/prefetch/hooks/useLazyPrefetchData.ts
deleted file mode 100644
index 3576b4fe4e8b..000000000000
--- a/packages/twenty-front/src/modules/prefetch/hooks/useLazyPrefetchData.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
-import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
-import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords';
-import { ObjectRecord } from '@/object-record/types/ObjectRecord';
-import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
-
-export const useLazyPrefetchedData = (
- prefetchKey: PrefetchKey,
- filter?: RecordGqlOperationFilter,
-) => {
- const { operationSignatureFactory, objectNameSingular } =
- PREFETCH_CONFIG[prefetchKey];
-
- const { objectMetadataItem } = useObjectMetadataItem({
- objectNameSingular,
- });
-
- const recordGqlFields =
- operationSignatureFactory({ objectMetadataItem }).fields ?? filter;
- const { records, findManyRecords } = useLazyFindManyRecords({
- objectNameSingular: objectNameSingular,
- recordGqlFields,
- });
-
- return {
- findManyRecords,
- records,
- };
-};
diff --git a/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts b/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts
deleted file mode 100644
index 8ffd11478570..000000000000
--- a/packages/twenty-front/src/modules/prefetch/hooks/usePrefetchedData.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { useRecoilValue } from 'recoil';
-
-import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
-import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
-import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
-import { ObjectRecord } from '@/object-record/types/ObjectRecord';
-import { PREFETCH_CONFIG } from '@/prefetch/constants/PrefetchConfig';
-import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedFamilyState';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
-
-export const usePrefetchedData = (
- prefetchKey: PrefetchKey,
- filter?: RecordGqlOperationFilter,
-) => {
- const isDataPrefetched = useRecoilValue(
- prefetchIsLoadedFamilyState(prefetchKey),
- );
-
- const { operationSignatureFactory, objectNameSingular } =
- PREFETCH_CONFIG[prefetchKey];
-
- const { objectMetadataItem } = useObjectMetadataItem({
- objectNameSingular,
- });
-
- const recordGqlFields =
- operationSignatureFactory({ objectMetadataItem }).fields ?? filter;
- const { records } = useFindManyRecords({
- skip: !isDataPrefetched,
- objectNameSingular: objectNameSingular,
- recordGqlFields,
- });
-
- return {
- isDataPrefetched,
- records,
- };
-};
diff --git a/packages/twenty-front/src/modules/prefetch/states/prefetchFavoriteFoldersState.ts b/packages/twenty-front/src/modules/prefetch/states/prefetchFavoriteFoldersState.ts
new file mode 100644
index 000000000000..18ba7398f7c8
--- /dev/null
+++ b/packages/twenty-front/src/modules/prefetch/states/prefetchFavoriteFoldersState.ts
@@ -0,0 +1,7 @@
+import { FavoriteFolder } from '@/favorites/types/FavoriteFolder';
+import { createState } from 'twenty-ui';
+
+export const prefetchFavoriteFoldersState = createState({
+ key: 'prefetchFavoriteFoldersState',
+ defaultValue: [],
+});
diff --git a/packages/twenty-front/src/modules/prefetch/states/prefetchFavoritesState.ts b/packages/twenty-front/src/modules/prefetch/states/prefetchFavoritesState.ts
new file mode 100644
index 000000000000..e3143ab330c8
--- /dev/null
+++ b/packages/twenty-front/src/modules/prefetch/states/prefetchFavoritesState.ts
@@ -0,0 +1,7 @@
+import { Favorite } from '@/favorites/types/Favorite';
+import { createState } from 'twenty-ui';
+
+export const prefetchFavoritesState = createState({
+ key: 'prefetchFavoritesState',
+ defaultValue: [],
+});
diff --git a/packages/twenty-front/src/modules/prefetch/states/prefetchViewsState.ts b/packages/twenty-front/src/modules/prefetch/states/prefetchViewsState.ts
new file mode 100644
index 000000000000..240d8d7a1a13
--- /dev/null
+++ b/packages/twenty-front/src/modules/prefetch/states/prefetchViewsState.ts
@@ -0,0 +1,7 @@
+import { View } from '@/views/types/View';
+import { createState } from 'twenty-ui';
+
+export const prefetchViewsState = createState({
+ key: 'prefetchViewsState',
+ defaultValue: [],
+});
diff --git a/packages/twenty-front/src/modules/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector.ts b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector.ts
new file mode 100644
index 000000000000..9399d602a11a
--- /dev/null
+++ b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector.ts
@@ -0,0 +1,18 @@
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
+import { ViewKey } from '@/views/types/ViewKey';
+import { selectorFamily } from 'recoil';
+
+export const prefetchIndexViewIdFromObjectMetadataItemFamilySelector =
+ selectorFamily({
+ key: 'prefetchIndexViewIdFromObjectMetadataItemFamilySelector',
+ get:
+ ({ objectMetadataItemId }) =>
+ ({ get }) => {
+ const views = get(prefetchViewsState);
+ return views?.find(
+ (view) =>
+ view.objectMetadataId === objectMetadataItemId &&
+ view.key === ViewKey.Index,
+ )?.id;
+ },
+ });
diff --git a/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewFromViewIdFamilySelector.ts b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewFromViewIdFamilySelector.ts
new file mode 100644
index 000000000000..7efb55082ffb
--- /dev/null
+++ b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewFromViewIdFamilySelector.ts
@@ -0,0 +1,16 @@
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
+import { View } from '@/views/types/View';
+import { selectorFamily } from 'recoil';
+
+export const prefetchViewFromViewIdFamilySelector = selectorFamily<
+ View | undefined,
+ { viewId: string }
+>({
+ key: 'prefetchViewFromViewIdFamilySelector',
+ get:
+ ({ viewId }) =>
+ ({ get }) => {
+ const views = get(prefetchViewsState);
+ return views?.find((view) => view.id === viewId);
+ },
+});
diff --git a/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewIdsFromObjectMetadataItemFamilySelector.ts b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewIdsFromObjectMetadataItemFamilySelector.ts
new file mode 100644
index 000000000000..30277752c4f7
--- /dev/null
+++ b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewIdsFromObjectMetadataItemFamilySelector.ts
@@ -0,0 +1,15 @@
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
+import { selectorFamily } from 'recoil';
+
+export const prefetchViewIdsFromObjectMetadataItemFamilySelector =
+ selectorFamily({
+ key: 'prefetchViewIdsFromObjectMetadataItemFamilySelector',
+ get:
+ ({ objectMetadataItemId }) =>
+ ({ get }) => {
+ const views = get(prefetchViewsState);
+ return views
+ .filter((view) => view.objectMetadataId === objectMetadataItemId)
+ .map((view) => view.id);
+ },
+ });
diff --git a/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewLengthFamilySelector.ts b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewLengthFamilySelector.ts
new file mode 100644
index 000000000000..89e525ad6ab1
--- /dev/null
+++ b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewLengthFamilySelector.ts
@@ -0,0 +1,10 @@
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
+import { selector } from 'recoil';
+
+export const prefetchViewLengthSelector = selector({
+ key: 'prefetchViewLengthSelector',
+ get: ({ get }) => {
+ const views = get(prefetchViewsState);
+ return views?.length ?? 0;
+ },
+});
diff --git a/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewsFromObjectMetadataItemFamilySelector.ts b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewsFromObjectMetadataItemFamilySelector.ts
new file mode 100644
index 000000000000..902d4c66cb56
--- /dev/null
+++ b/packages/twenty-front/src/modules/prefetch/states/selector/prefetchViewsFromObjectMetadataItemFamilySelector.ts
@@ -0,0 +1,18 @@
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
+import { View } from '@/views/types/View';
+import { selectorFamily } from 'recoil';
+
+export const prefetchViewsFromObjectMetadataItemFamilySelector = selectorFamily<
+ View[],
+ { objectMetadataItemId: string }
+>({
+ key: 'prefetchViewsFromObjectMetadataItemFamilySelector',
+ get:
+ ({ objectMetadataItemId }) =>
+ ({ get }) => {
+ const views = get(prefetchViewsState);
+ return views.filter(
+ (view) => view.objectMetadataId === objectMetadataItemId,
+ );
+ },
+});
diff --git a/packages/twenty-front/src/modules/prefetch/types/PrefetchKey.ts b/packages/twenty-front/src/modules/prefetch/types/PrefetchKey.ts
index c71fe02e3810..0d076ad0e6bb 100644
--- a/packages/twenty-front/src/modules/prefetch/types/PrefetchKey.ts
+++ b/packages/twenty-front/src/modules/prefetch/types/PrefetchKey.ts
@@ -1,5 +1,4 @@
export enum PrefetchKey {
- AllViews = 'ALL_VIEWS',
AllFavorites = 'ALL_FAVORITES',
AllFavoritesFolders = 'ALL_FAVORITES_FOLDERS',
}
diff --git a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
index 38a1830766ad..c196768d2eaa 100644
--- a/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
+++ b/packages/twenty-front/src/modules/settings/data-model/object-details/components/SettingsObjectFieldItemTableRow.tsx
@@ -6,8 +6,7 @@ import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSi
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
import { useDeleteRecordFromCache } from '@/object-record/cache/hooks/useDeleteRecordFromCache';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { SettingsObjectFieldActiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldActiveActionDropdown';
import { SettingsObjectFieldInactiveActionDropdown } from '@/settings/data-model/object-details/components/SettingsObjectFieldDisabledActionDropdown';
import { settingsObjectFieldsFamilyState } from '@/settings/data-model/object-details/states/settingsObjectFieldsFamilyState';
@@ -16,11 +15,10 @@ import { SettingsPath } from '@/types/SettingsPath';
import { TableCell } from '@/ui/layout/table/components/TableCell';
import { TableRow } from '@/ui/layout/table/components/TableRow';
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
-import { View } from '@/views/types/View';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useMemo } from 'react';
-import { useRecoilState } from 'recoil';
+import { useRecoilState, useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
import {
IconMinus,
@@ -121,8 +119,7 @@ export const SettingsObjectFieldItemTableRow = ({
deleteMetadataField,
} = useFieldMetadataItem();
- const { records: allViews } = usePrefetchedData(PrefetchKey.AllViews);
-
+ const prefetchViews = useRecoilValue(prefetchViewsState);
const deleteViewFromCache = useDeleteRecordFromCache({
objectNameSingular: CoreObjectNameSingular.View,
});
@@ -135,7 +132,7 @@ export const SettingsObjectFieldItemTableRow = ({
objectMetadataItem.id,
);
- const deletedViewIds = allViews
+ const deletedViewIds = prefetchViews
.map((view) => {
if (view.kanbanFieldMetadataId === activeFieldMetadatItem.id) {
deleteViewFromCache(view);
diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx
index 4c2a25958bab..e950bb7912ff 100644
--- a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx
+++ b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainer.tsx
@@ -1,14 +1,18 @@
import styled from '@emotion/styled';
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
-import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
+import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext';
import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext';
import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers';
import { SignInBackgroundMockContainerEffect } from '@/sign-in-background-mock/components/SignInBackgroundMockContainerEffect';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { ViewBar } from '@/views/components/ViewBar';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
+import { useRecoilValue } from 'recoil';
+import { isDefined } from 'twenty-shared';
const StyledContainer = styled.div`
display: flex;
@@ -23,9 +27,12 @@ export const SignInBackgroundMockContainer = () => {
const recordIndexId = 'sign-up-mock-record-table-id';
const viewBarId = 'companies-mock';
- const { objectMetadataItem } = useObjectMetadataItem({
- objectNameSingular,
- });
+ const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
+
+ const objectMetadataItem = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
+ 'main-context-store',
+ );
return (
@@ -34,7 +41,7 @@ export const SignInBackgroundMockContainer = () => {
recordIndexId,
objectNamePlural,
objectNameSingular,
- objectMetadataItem,
+ objectMetadataItem: objectMetadataItem ?? objectMetadataItems[0],
onIndexRecordsLoaded: () => {},
indexIdentifierUrl: () => '',
}}
@@ -47,28 +54,32 @@ export const SignInBackgroundMockContainer = () => {
>
+
- {}}
- optionsDropdownButton={<>>}
- />
-
- {}}
- />
+ {isDefined(objectMetadataItem) && (
+ <>
+ >}
+ />
+
+ {}}
+ />
+ >
+ )}
diff --git a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx
index 75929819a69b..0c501fc92636 100644
--- a/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx
+++ b/packages/twenty-front/src/modules/sign-in-background-mock/components/SignInBackgroundMockContainerEffect.tsx
@@ -1,12 +1,15 @@
import { useEffect } from 'react';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { useSetRecordIndexEntityCount } from '@/object-record/record-index/hooks/useSetRecordIndexEntityCount';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
+import { useSetTableColumns } from '@/object-record/record-table/hooks/useSetTableColumns';
import { SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS } from '@/sign-in-background-mock/constants/SignInBackgroundMockColumnDefinitions';
import { SIGN_IN_BACKGROUND_MOCK_SORT_DEFINITIONS } from '@/sign-in-background-mock/constants/SignInBackgroundMockSortDefinitions';
import { SIGN_IN_BACKGROUND_MOCK_VIEW_FIELDS } from '@/sign-in-background-mock/constants/SignInBackgroundMockViewFields';
+import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { useInitViewBar } from '@/views/hooks/useInitViewBar';
import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
@@ -21,10 +24,16 @@ export const SignInBackgroundMockContainerEffect = ({
recordTableId,
viewId,
}: SignInBackgroundMockContainerEffectProps) => {
- const { setAvailableTableColumns, setOnEntityCountChange, setTableColumns } =
- useRecordTable({
- recordTableId,
- });
+ const setContextStoreCurrentObjectMetadataItem = useSetRecoilComponentStateV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
+ 'main-context-store',
+ );
+
+ const { setAvailableTableColumns, setOnEntityCountChange } = useRecordTable({
+ recordTableId,
+ });
+
+ const { setTableColumns } = useSetTableColumns();
const { objectNameSingular } = useObjectNameSingularFromPlural({
objectNamePlural,
@@ -55,7 +64,10 @@ export const SignInBackgroundMockContainerEffect = ({
viewFields: SIGN_IN_BACKGROUND_MOCK_VIEW_FIELDS,
columnDefinitions: SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS,
}),
+ recordTableId,
);
+
+ setContextStoreCurrentObjectMetadataItem(objectMetadataItem);
}, [
setViewObjectMetadataId,
setAvailableSortDefinitions,
@@ -63,6 +75,8 @@ export const SignInBackgroundMockContainerEffect = ({
objectMetadataItem,
setAvailableTableColumns,
setTableColumns,
+ recordTableId,
+ setContextStoreCurrentObjectMetadataItem,
]);
useEffect(() => {
diff --git a/packages/twenty-front/src/modules/ui/field/display/components/BooleanDisplay.tsx b/packages/twenty-front/src/modules/ui/field/display/components/BooleanDisplay.tsx
index b9568ffbe91f..044a00662f5d 100644
--- a/packages/twenty-front/src/modules/ui/field/display/components/BooleanDisplay.tsx
+++ b/packages/twenty-front/src/modules/ui/field/display/components/BooleanDisplay.tsx
@@ -1,8 +1,6 @@
import { styled } from '@linaria/react';
import { IconCheck, IconX, THEME_COMMON } from 'twenty-ui';
-import { isDefined } from 'twenty-shared';
-
const spacing = THEME_COMMON.spacingMultiplicator * 1;
const iconSizeSm = THEME_COMMON.icon.size.sm;
@@ -15,7 +13,7 @@ type BooleanDisplayProps = {
};
export const BooleanDisplay = ({ value }: BooleanDisplayProps) => {
- if (!isDefined(value)) {
+ if (value === null || value === undefined) {
return <>>;
}
diff --git a/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx b/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx
index 11aca3c3f42c..ca89c5456ae6 100644
--- a/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx
+++ b/packages/twenty-front/src/modules/views/components/QueryParamsFiltersEffect.tsx
@@ -1,18 +1,20 @@
import { useEffect } from 'react';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2';
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
import { useApplyViewFiltersToCurrentRecordFilters } from '@/views/hooks/useApplyViewFiltersToCurrentRecordFilters';
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
export const QueryParamsFiltersEffect = () => {
const { hasFiltersQueryParams, getFiltersFromQueryParams, viewIdQueryParam } =
useViewFromQueryParams();
- const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState);
+ const currentViewId = useRecoilComponentValueV2(
+ contextStoreCurrentViewIdComponentState,
+ );
const setUnsavedViewFilter = useSetRecoilComponentFamilyStateV2(
unsavedToUpsertViewFiltersComponentFamilyState,
diff --git a/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx b/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx
deleted file mode 100644
index d86c2bf1da2c..000000000000
--- a/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
-import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId';
-import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
-import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
-import { useEffect } from 'react';
-import { useRecoilValue } from 'recoil';
-import { isDefined } from 'twenty-shared';
-
-// TODO: This whole code should be removed. currentViewId should be used directly to set the mainContextStore
-// and viewbar / view tooling should be updated to use that state contextStore state directly.
-export const QueryParamsViewIdEffect = () => {
- const [currentViewId, setCurrentViewId] = useRecoilComponentStateV2(
- currentViewIdComponentState,
- );
-
- const mainContextStoreComponentInstanceId = useRecoilValue(
- mainContextStoreComponentInstanceIdState,
- );
-
- const contextStoreCurrentViewId = useRecoilComponentValueV2(
- contextStoreCurrentViewIdComponentState,
- mainContextStoreComponentInstanceId,
- );
-
- useEffect(() => {
- if (isDefined(contextStoreCurrentViewId)) {
- if (currentViewId !== contextStoreCurrentViewId) {
- setCurrentViewId(contextStoreCurrentViewId);
- }
- }
- }, [contextStoreCurrentViewId, currentViewId, setCurrentViewId]);
-
- return <>>;
-};
diff --git a/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx b/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx
index 4cc33451ef8b..0ed97948dc43 100644
--- a/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx
+++ b/packages/twenty-front/src/modules/views/components/UpdateViewButtonGroup.tsx
@@ -7,6 +7,7 @@ import {
MenuItem,
} from 'twenty-ui';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
@@ -19,7 +20,6 @@ import { useAreViewFiltersDifferentFromRecordFilters } from '@/views/hooks/useAr
import { useAreViewSortsDifferentFromRecordSorts } from '@/views/hooks/useAreViewSortsDifferentFromRecordSorts';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { useSaveCurrentViewFiltersAndSorts } from '@/views/hooks/useSaveCurrentViewFiltersAndSorts';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
@@ -44,7 +44,9 @@ export const UpdateViewButtonGroup = ({
const { setViewPickerMode } = useViewPickerMode();
- const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState);
+ const currentViewId = useRecoilComponentValueV2(
+ contextStoreCurrentViewIdComponentState,
+ );
const { closeDropdown: closeUpdateViewButtonDropdown } = useDropdown(
UPDATE_VIEW_BUTTON_DROPDOWN_ID,
diff --git a/packages/twenty-front/src/modules/views/components/ViewBar.tsx b/packages/twenty-front/src/modules/views/components/ViewBar.tsx
index 73f84fdb77df..302da4be4314 100644
--- a/packages/twenty-front/src/modules/views/components/ViewBar.tsx
+++ b/packages/twenty-front/src/modules/views/components/ViewBar.tsx
@@ -7,13 +7,10 @@ import { ObjectSortDropdownButton } from '@/object-record/object-sort-dropdown/c
import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
import { TopBar } from '@/ui/layout/top-bar/components/TopBar';
import { QueryParamsFiltersEffect } from '@/views/components/QueryParamsFiltersEffect';
-import { QueryParamsViewIdEffect } from '@/views/components/QueryParamsViewIdEffect';
-import { ViewBarEffect } from '@/views/components/ViewBarEffect';
import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect';
import { ViewBarPageTitle } from '@/views/components/ViewBarPageTitle';
import { ViewBarSkeletonLoader } from '@/views/components/ViewBarSkeletonLoader';
import { ViewBarSortEffect } from '@/views/components/ViewBarSortEffect';
-import { GraphQLView } from '@/views/types/GraphQLView';
import { ViewPickerDropdown } from '@/views/view-picker/components/ViewPickerDropdown';
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
@@ -22,7 +19,6 @@ import { FiltersHotkeyScope } from '@/object-record/object-filter-dropdown/types
import { VIEW_SORT_DROPDOWN_ID } from '@/object-record/object-sort-dropdown/constants/ViewSortDropdownId';
import { ObjectSortDropdownComponentInstanceContext } from '@/object-record/object-sort-dropdown/states/context/ObjectSortDropdownComponentInstanceContext';
import { ViewBarRecordFilterEffect } from '@/views/components/ViewBarRecordFilterEffect';
-import { ViewEventContext } from '@/views/events/contexts/ViewEventContext';
import { UpdateViewButtonGroup } from './UpdateViewButtonGroup';
import { ViewBarDetails } from './ViewBarDetails';
@@ -30,14 +26,12 @@ export type ViewBarProps = {
viewBarId: string;
className?: string;
optionsDropdownButton: ReactNode;
- onCurrentViewChange: (view: GraphQLView | undefined) => void | Promise;
};
export const ViewBar = ({
viewBarId,
className,
optionsDropdownButton,
- onCurrentViewChange,
}: ViewBarProps) => {
const { objectNamePlural } = useParams();
@@ -53,53 +47,49 @@ export const ViewBar = ({
-
-
-
-
-
-
-
+
+
+
+
-
- :
- }
- rightComponent={
- <>
-
-
+ :
+ }
+ rightComponent={
+ <>
+
+
+ {optionsDropdownButton}
+ >
+ }
+ bottomComponent={
+
- {optionsDropdownButton}
- >
- }
- bottomComponent={
-
- }
- />
- }
- />
-
+ }
+ />
+ }
+ />
);
};
diff --git a/packages/twenty-front/src/modules/views/components/ViewBarEffect.tsx b/packages/twenty-front/src/modules/views/components/ViewBarEffect.tsx
deleted file mode 100644
index 662b4ed49fcb..000000000000
--- a/packages/twenty-front/src/modules/views/components/ViewBarEffect.tsx
+++ /dev/null
@@ -1,56 +0,0 @@
-import { isUndefined } from '@sniptt/guards';
-import { useContext, useEffect, useState } from 'react';
-
-import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
-import { ViewEventContext } from '@/views/events/contexts/ViewEventContext';
-import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
-import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState';
-import { View } from '@/views/types/View';
-import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
-
-type ViewBarEffectProps = {
- viewBarId: string;
-};
-
-export const ViewBarEffect = ({ viewBarId }: ViewBarEffectProps) => {
- const { currentViewWithCombinedFiltersAndSorts } =
- useGetCurrentView(viewBarId);
-
- const { onCurrentViewChange } = useContext(ViewEventContext);
-
- const [currentViewSnapshot, setCurrentViewSnapshot] = useState<
- View | undefined
- >(undefined);
-
- const isPersistingViewFields = useRecoilComponentValueV2(
- isPersistingViewFieldsComponentState,
- viewBarId,
- );
-
- useEffect(() => {
- if (
- !isDeeplyEqual(
- currentViewWithCombinedFiltersAndSorts,
- currentViewSnapshot,
- )
- ) {
- if (isUndefined(currentViewWithCombinedFiltersAndSorts)) {
- setCurrentViewSnapshot(currentViewWithCombinedFiltersAndSorts);
- onCurrentViewChange?.(undefined);
- return;
- }
-
- if (!isPersistingViewFields) {
- setCurrentViewSnapshot(currentViewWithCombinedFiltersAndSorts);
- onCurrentViewChange?.(currentViewWithCombinedFiltersAndSorts);
- }
- }
- }, [
- currentViewSnapshot,
- currentViewWithCombinedFiltersAndSorts,
- isPersistingViewFields,
- onCurrentViewChange,
- ]);
-
- return <>>;
-};
diff --git a/packages/twenty-front/src/modules/views/components/ViewBarRecordFilterEffect.tsx b/packages/twenty-front/src/modules/views/components/ViewBarRecordFilterEffect.tsx
index 09c8ecd84491..8606f537a76e 100644
--- a/packages/twenty-front/src/modules/views/components/ViewBarRecordFilterEffect.tsx
+++ b/packages/twenty-front/src/modules/views/components/ViewBarRecordFilterEffect.tsx
@@ -1,38 +1,24 @@
-import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
-import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { useFilterableFieldMetadataItems } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItems';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { useRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { hasInitializedCurrentRecordFiltersComponentFamilyState } from '@/views/states/hasInitializedCurrentRecordFiltersComponentFamilyState';
-import { View } from '@/views/types/View';
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
import { useEffect } from 'react';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
export const ViewBarRecordFilterEffect = () => {
- const { records: views, isDataPrefetched } = usePrefetchedData(
- PrefetchKey.AllViews,
- );
-
const currentViewId = useRecoilComponentValueV2(
contextStoreCurrentViewIdComponentState,
);
- const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
- contextStoreCurrentObjectMetadataIdComponentState,
- );
-
- const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
-
- const objectMetadataItem = objectMetadataItems.find(
- (objectMetadataItem) =>
- objectMetadataItem.id === contextStoreCurrentObjectMetadataId,
+ const contextStoreCurrentObjectMetadataItem = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
);
const [
@@ -54,14 +40,21 @@ export const ViewBarRecordFilterEffect = () => {
);
const { filterableFieldMetadataItems } = useFilterableFieldMetadataItems(
- objectMetadataItem?.id,
+ contextStoreCurrentObjectMetadataItem?.id,
);
- useEffect(() => {
- if (isDataPrefetched && !hasInitializedCurrentRecordFilters) {
- const currentView = views.find((view) => view.id === currentViewId);
+ const currentView = useRecoilValue(
+ prefetchViewFromViewIdFamilySelector({
+ viewId: currentViewId ?? '',
+ }),
+ );
- if (currentView?.objectMetadataId !== objectMetadataItem?.id) {
+ useEffect(() => {
+ if (isDefined(currentView) && !hasInitializedCurrentRecordFilters) {
+ if (
+ currentView.objectMetadataId !==
+ contextStoreCurrentObjectMetadataItem?.id
+ ) {
return;
}
@@ -76,15 +69,14 @@ export const ViewBarRecordFilterEffect = () => {
}
}
}, [
- isDataPrefetched,
- views,
currentViewId,
setCurrentRecordFilters,
filterableFieldMetadataItems,
currentRecordFilters,
hasInitializedCurrentRecordFilters,
setHasInitializedCurrentRecordFilters,
- objectMetadataItem?.id,
+ contextStoreCurrentObjectMetadataItem?.id,
+ currentView,
]);
return null;
diff --git a/packages/twenty-front/src/modules/views/events/contexts/ViewEventContext.ts b/packages/twenty-front/src/modules/views/events/contexts/ViewEventContext.ts
deleted file mode 100644
index ba02a09aa2e4..000000000000
--- a/packages/twenty-front/src/modules/views/events/contexts/ViewEventContext.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { View } from '@/views/types/View';
-import { createEventContext } from '~/utils/createEventContext';
-
-type ViewEventContextType = {
- onCurrentViewChange: (view: View | undefined) => void | Promise;
-};
-
-export const ViewEventContext = createEventContext();
diff --git a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx
index ebda576b1455..63aaac01b16e 100644
--- a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx
+++ b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx
@@ -1,20 +1,22 @@
-import { act, renderHook } from '@testing-library/react';
+import { renderHook } from '@testing-library/react';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { getFilterTypeFromFieldType } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
+import { AGGREGATE_OPERATIONS } from '@/object-record/record-table/constants/AggregateOperations';
+import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
+import { View } from '@/views/types/View';
import { ViewFilter } from '@/views/types/ViewFilter';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
+import { ViewType } from '@/views/types/ViewType';
+import { act } from 'react';
import { isDefined } from 'twenty-shared';
import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndContextStoreWrapper';
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
import { useApplyCurrentViewFiltersToCurrentRecordFilters } from '../useApplyCurrentViewFiltersToCurrentRecordFilters';
-jest.mock('@/prefetch/hooks/usePrefetchedData');
-
const mockObjectMetadataItemNameSingular = 'company';
describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
@@ -41,18 +43,26 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
positionInViewFilterGroup: 0,
};
- const mockView = {
+ const mockView: View = {
id: 'view-1',
name: 'Test View',
objectMetadataId: mockObjectMetadataItem.id,
viewFilters: [mockViewFilter],
+ type: ViewType.Table,
+ key: null,
+ isCompact: false,
+ viewFields: [],
+ viewGroups: [],
+ viewSorts: [],
+ kanbanFieldMetadataId: '',
+ kanbanAggregateOperation: AGGREGATE_OPERATIONS.count,
+ icon: '',
+ kanbanAggregateOperationFieldMetadataId: '',
+ position: 0,
+ __typename: 'View',
};
it('should apply filters from current view', () => {
- (usePrefetchedData as jest.Mock).mockReturnValue({
- records: [mockView],
- });
-
const { result } = renderHook(
() => {
const { applyCurrentViewFiltersToCurrentRecordFilters } =
@@ -75,11 +85,12 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
mockObjectMetadataItemNameSingular,
onInitializeRecoilSnapshot: (snapshot) => {
snapshot.set(
- currentViewIdComponentState.atomFamily({
+ contextStoreCurrentViewIdComponentState.atomFamily({
instanceId: 'instanceId',
}),
mockView.id,
);
+ snapshot.set(prefetchViewsState, [mockView]);
},
}),
},
@@ -105,10 +116,6 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
});
it('should not apply filters when current view is not found', () => {
- (usePrefetchedData as jest.Mock).mockReturnValue({
- records: [],
- });
-
const { result } = renderHook(
() => {
const { applyCurrentViewFiltersToCurrentRecordFilters } =
@@ -131,11 +138,12 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
mockObjectMetadataItemNameSingular,
onInitializeRecoilSnapshot: (snapshot) => {
snapshot.set(
- currentViewIdComponentState.atomFamily({
+ contextStoreCurrentViewIdComponentState.atomFamily({
instanceId: 'instanceId',
}),
mockView.id,
);
+ snapshot.set(prefetchViewsState, []);
},
}),
},
@@ -149,15 +157,6 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
});
it('should handle view with empty filters', () => {
- const viewWithNoFilters = {
- ...mockView,
- viewFilters: [],
- };
-
- (usePrefetchedData as jest.Mock).mockReturnValue({
- records: [viewWithNoFilters],
- });
-
const { result } = renderHook(
() => {
const { applyCurrentViewFiltersToCurrentRecordFilters } =
@@ -180,11 +179,14 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
mockObjectMetadataItemNameSingular,
onInitializeRecoilSnapshot: (snapshot) => {
snapshot.set(
- currentViewIdComponentState.atomFamily({
+ contextStoreCurrentViewIdComponentState.atomFamily({
instanceId: 'instanceId',
}),
mockView.id,
);
+ snapshot.set(prefetchViewsState, [
+ { ...mockView, viewFilters: [] },
+ ]);
},
}),
},
diff --git a/packages/twenty-front/src/modules/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters.ts b/packages/twenty-front/src/modules/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters.ts
index f35ee75651f4..3d90fabdf47c 100644
--- a/packages/twenty-front/src/modules/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters.ts
@@ -1,19 +1,18 @@
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
-import { View } from '@/views/types/View';
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
+import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared';
export const useApplyCurrentViewFiltersToCurrentRecordFilters = () => {
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
-
- const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState);
+ const currentViewId = useRecoilComponentValueV2(
+ contextStoreCurrentViewIdComponentState,
+ );
const setCurrentRecordFilters = useSetRecoilComponentStateV2(
currentRecordFiltersComponentState,
@@ -22,18 +21,28 @@ export const useApplyCurrentViewFiltersToCurrentRecordFilters = () => {
const { filterableFieldMetadataItems } =
useFilterableFieldMetadataItemsInRecordIndexContext();
- const applyCurrentViewFiltersToCurrentRecordFilters = () => {
- const currentView = views.find((view) => view.id === currentViewId);
-
- if (isDefined(currentView)) {
- setCurrentRecordFilters(
- mapViewFiltersToFilters(
- currentView.viewFilters,
- filterableFieldMetadataItems,
- ),
- );
- }
- };
+ const applyCurrentViewFiltersToCurrentRecordFilters = useRecoilCallback(
+ ({ snapshot }) =>
+ () => {
+ const currentView = snapshot
+ .getLoadable(
+ prefetchViewFromViewIdFamilySelector({
+ viewId: currentViewId ?? '',
+ }),
+ )
+ .getValue();
+
+ if (isDefined(currentView)) {
+ setCurrentRecordFilters(
+ mapViewFiltersToFilters(
+ currentView.viewFilters,
+ filterableFieldMetadataItems,
+ ),
+ );
+ }
+ },
+ [currentViewId, filterableFieldMetadataItems, setCurrentRecordFilters],
+ );
return {
applyCurrentViewFiltersToCurrentRecordFilters,
diff --git a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts
index b246becd55e2..87f6a3f7b668 100644
--- a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts
@@ -1,6 +1,9 @@
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
+import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
+import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords';
@@ -11,9 +14,7 @@ import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistView
import { useGetViewFilterGroupsCombined } from '@/views/hooks/useGetCombinedViewFilterGroups';
import { useGetViewFiltersCombined } from '@/views/hooks/useGetCombinedViewFilters';
import { useGetViewSortsCombined } from '@/views/hooks/useGetCombinedViewSorts';
-import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
-import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState';
+import { isPersistingViewFieldsState } from '@/views/states/isPersistingViewFieldsState';
import { GraphQLView } from '@/views/types/GraphQLView';
import { View } from '@/views/types/View';
import { ViewGroup } from '@/views/types/ViewGroup';
@@ -25,17 +26,10 @@ import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
- currentViewIdComponentState,
+ contextStoreCurrentViewIdComponentState,
viewBarComponentId,
);
- const isPersistingViewFieldsCallbackState = useRecoilComponentCallbackStateV2(
- isPersistingViewFieldsComponentState,
- viewBarComponentId,
- );
-
- const { getViewFromCache } = useGetViewFromCache();
-
const { createOneRecord } = useCreateOneRecord({
objectNameSingular: CoreObjectNameSingular.View,
});
@@ -58,6 +52,11 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
const { objectMetadataItem } = useRecordIndexContextOrThrow();
+ const { findManyRecords } = useLazyFindManyRecords({
+ objectNameSingular: CoreObjectNameSingular.View,
+ fetchPolicy: 'network-only',
+ });
+
const createViewFromCurrentView = useRecoilCallback(
({ snapshot, set }) =>
async (
@@ -84,14 +83,19 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
return;
}
- // Here we might instead want to get view from unsaved filters ?
- const sourceView = await getViewFromCache(currentViewId);
+ const sourceView = snapshot
+ .getLoadable(
+ prefetchViewFromViewIdFamilySelector({
+ viewId: currentViewId,
+ }),
+ )
+ .getValue();
if (!isDefined(sourceView)) {
return;
}
- set(isPersistingViewFieldsCallbackState, true);
+ set(isPersistingViewFieldsState, true);
const newView = await createOneRecord({
id: id ?? v4(),
@@ -123,7 +127,7 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
}
const viewGroupsToCreate =
- objectMetadataItem?.fields
+ objectMetadataItem.fields
?.find((field) => field.id === kanbanFieldMetadataId)
?.options?.map(
(option, index) =>
@@ -169,21 +173,21 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
);
}
- set(isPersistingViewFieldsCallbackState, false);
+ await findManyRecords();
+ set(isPersistingViewFieldsState, false);
},
[
- objectMetadataItem,
- createViewSortRecords,
- createViewFilterRecords,
+ currentViewIdCallbackState,
createOneRecord,
createViewFieldRecords,
- getViewSortsCombined,
- getViewFiltersCombined,
- getViewFilterGroupsCombined,
- currentViewIdCallbackState,
- getViewFromCache,
- isPersistingViewFieldsCallbackState,
+ findManyRecords,
+ objectMetadataItem.fields,
createViewGroupRecords,
+ getViewFilterGroupsCombined,
+ getViewFiltersCombined,
+ getViewSortsCombined,
+ createViewSortRecords,
+ createViewFilterRecords,
createViewFilterGroupRecords,
],
);
diff --git a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts
index 1bdf6aec3227..67dc018739c3 100644
--- a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewFilters.ts
@@ -1,9 +1,9 @@
import { useRecoilCallback } from 'recoil';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
+import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
import { isDefined } from 'twenty-shared';
@@ -22,11 +22,11 @@ export const useDeleteCombinedViewFilters = (viewBarComponentId?: string) => {
);
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
- currentViewIdComponentState,
+ contextStoreCurrentViewIdComponentState,
viewBarComponentId,
);
- const { getViewFromCache } = useGetViewFromCache();
+ const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const deleteCombinedViewFilter = useRecoilCallback(
({ snapshot, set }) =>
@@ -50,7 +50,7 @@ export const useDeleteCombinedViewFilters = (viewBarComponentId?: string) => {
return;
}
- const currentView = await getViewFromCache(currentViewId);
+ const currentView = await getViewFromPrefetchState(currentViewId);
if (!currentView) {
return;
@@ -89,7 +89,7 @@ export const useDeleteCombinedViewFilters = (viewBarComponentId?: string) => {
},
[
currentViewIdCallbackState,
- getViewFromCache,
+ getViewFromPrefetchState,
unsavedToDeleteViewFilterIdsCallbackState,
unsavedToUpsertViewFiltersCallbackState,
],
diff --git a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts
index 048b06dce0c1..ce7f2827ffb9 100644
--- a/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useDeleteCombinedViewSorts.ts
@@ -1,17 +1,16 @@
import { useRecoilCallback } from 'recoil';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
+import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
import { isDefined } from 'twenty-shared';
export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => {
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
- currentViewIdComponentState,
- viewBarComponentId,
+ contextStoreCurrentViewIdComponentState,
);
const unsavedToUpsertViewSortsCallbackState =
@@ -26,7 +25,7 @@ export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => {
viewBarComponentId,
);
- const { getViewFromCache } = useGetViewFromCache();
+ const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const deleteCombinedViewSort = useRecoilCallback(
({ snapshot, set }) =>
@@ -50,7 +49,7 @@ export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => {
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
);
- const currentView = await getViewFromCache(currentViewId);
+ const currentView = await getViewFromPrefetchState(currentViewId);
if (!currentView) {
return;
@@ -88,7 +87,7 @@ export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => {
},
[
currentViewIdCallbackState,
- getViewFromCache,
+ getViewFromPrefetchState,
unsavedToDeleteViewSortIdsCallbackState,
unsavedToUpsertViewSortsCallbackState,
],
diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilterGroups.ts b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilterGroups.ts
index c1300f2b8295..6de34305898a 100644
--- a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilterGroups.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilterGroups.ts
@@ -1,18 +1,14 @@
import { useRecoilCallback } from 'recoil';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState';
import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState';
-import { View } from '@/views/types/View';
import { getCombinedViewFilterGroups } from '@/views/utils/getCombinedViewFilterGroups';
import { isDefined } from 'twenty-shared';
export const useGetViewFilterGroupsCombined = (viewBarComponentId?: string) => {
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
-
const unsavedToUpsertViewFilterGroupsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewFilterGroupsComponentFamilyState,
@@ -28,7 +24,13 @@ export const useGetViewFilterGroupsCombined = (viewBarComponentId?: string) => {
const getViewFilterGroupsCombined = useRecoilCallback(
({ snapshot }) =>
(viewId: string) => {
- const view = views.find((view) => view.id === viewId);
+ const view = snapshot
+ .getLoadable(
+ prefetchViewFromViewIdFamilySelector({
+ viewId,
+ }),
+ )
+ .getValue();
if (!isDefined(view)) {
throw new Error(
@@ -55,7 +57,6 @@ export const useGetViewFilterGroupsCombined = (viewBarComponentId?: string) => {
return combinedViewFilterGroups;
},
[
- views,
unsavedToDeleteViewFilterGroupIdsCallbackState,
unsavedToUpsertViewFilterGroupsCallbackState,
],
diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilters.ts
index 1a72e3353900..8adf8304377b 100644
--- a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilters.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewFilters.ts
@@ -1,18 +1,14 @@
import { useRecoilCallback } from 'recoil';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
-import { View } from '@/views/types/View';
import { getCombinedViewFilters } from '@/views/utils/getCombinedViewFilters';
import { isDefined } from 'twenty-shared';
export const useGetViewFiltersCombined = (viewBarComponentId?: string) => {
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
-
const unsavedToUpsertViewFiltersCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewFiltersComponentFamilyState,
@@ -28,7 +24,13 @@ export const useGetViewFiltersCombined = (viewBarComponentId?: string) => {
const getViewFiltersCombined = useRecoilCallback(
({ snapshot }) =>
(viewId: string) => {
- const view = views.find((view) => view.id === viewId);
+ const view = snapshot
+ .getLoadable(
+ prefetchViewFromViewIdFamilySelector({
+ viewId,
+ }),
+ )
+ .getValue();
if (!isDefined(view)) {
throw new Error(
@@ -55,7 +57,6 @@ export const useGetViewFiltersCombined = (viewBarComponentId?: string) => {
return combinedViewFilters;
},
[
- views,
unsavedToDeleteViewFilterIdsCallbackState,
unsavedToUpsertViewFiltersCallbackState,
],
diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewSorts.ts
index 7b3131da6685..10fbc26d793a 100644
--- a/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewSorts.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useGetCombinedViewSorts.ts
@@ -1,19 +1,15 @@
import { useRecoilCallback } from 'recoil';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
-import { View } from '@/views/types/View';
import { getCombinedViewSorts } from '@/views/utils/getCombinedViewSorts';
import { isDefined } from 'twenty-shared';
// TODO: fix naming
export const useGetViewSortsCombined = (viewBarComponentId?: string) => {
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
-
const unsavedToUpsertViewSortsCallbackState =
useRecoilComponentCallbackStateV2(
unsavedToUpsertViewSortsComponentFamilyState,
@@ -29,7 +25,13 @@ export const useGetViewSortsCombined = (viewBarComponentId?: string) => {
const getViewSortsCombined = useRecoilCallback(
({ snapshot }) =>
(viewId: string) => {
- const view = views.find((view) => view.id === viewId);
+ const view = snapshot
+ .getLoadable(
+ prefetchViewFromViewIdFamilySelector({
+ viewId,
+ }),
+ )
+ .getValue();
if (!isDefined(view)) {
throw new Error(
@@ -56,7 +58,6 @@ export const useGetViewSortsCombined = (viewBarComponentId?: string) => {
return combinedViewSorts;
},
[
- views,
unsavedToDeleteViewSortIdsCallbackState,
unsavedToUpsertViewSortsCallbackState,
],
diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts
index 9c25b8722ec7..4d8a9d204594 100644
--- a/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useGetCurrentView.ts
@@ -1,13 +1,15 @@
import { useEffect } from 'react';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
+import { prefetchIndexViewIdFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector';
+import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
+import { prefetchViewsFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchViewsFromObjectMetadataItemFamilySelector';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { isCurrentViewKeyIndexComponentState } from '@/views/states/isCurrentViewIndexComponentState';
import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState';
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
@@ -15,12 +17,10 @@ import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/u
import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
-import { viewObjectMetadataIdComponentState } from '@/views/states/viewObjectMetadataIdComponentState';
-import { View } from '@/views/types/View';
import { getCombinedViewFilterGroups } from '@/views/utils/getCombinedViewFilterGroups';
import { getCombinedViewFilters } from '@/views/utils/getCombinedViewFilters';
import { getCombinedViewSorts } from '@/views/utils/getCombinedViewSorts';
-import { getObjectMetadataItemViews } from '@/views/utils/getObjectMetadataItemViews';
+import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
export const useGetCurrentView = (viewBarInstanceId?: string) => {
@@ -29,42 +29,46 @@ export const useGetCurrentView = (viewBarInstanceId?: string) => {
viewBarInstanceId,
);
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
+ const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const currentViewId = useRecoilComponentValueV2(
- currentViewIdComponentState,
- instanceId,
+ contextStoreCurrentViewIdComponentState,
);
- const viewObjectMetadataId = useRecoilComponentValueV2(
- viewObjectMetadataIdComponentState,
- instanceId,
+ const indexViewId = useRecoilValue(
+ prefetchIndexViewIdFromObjectMetadataItemFamilySelector({
+ objectMetadataItemId: objectMetadataItem.id,
+ }),
);
- const setIsCurrentViewKeyIndex = useSetRecoilComponentStateV2(
- isCurrentViewKeyIndexComponentState,
- instanceId,
+ const currentViewFromViewId = useRecoilValue(
+ prefetchViewFromViewIdFamilySelector({
+ viewId: currentViewId ?? '',
+ }),
);
- const currentViewFromCurrentViewId = views.find(
- (view) => view.id === currentViewId,
- );
- const indexView = views.find(
- (view) =>
- view.key === 'INDEX' && view.objectMetadataId === viewObjectMetadataId,
+ const indexView = useRecoilValue(
+ prefetchViewFromViewIdFamilySelector({
+ viewId: indexViewId ?? '',
+ }),
);
- const currentView = currentViewId ? currentViewFromCurrentViewId : indexView;
+ const setIsCurrentViewKeyIndex = useSetRecoilComponentStateV2(
+ isCurrentViewKeyIndexComponentState,
+ instanceId,
+ );
const viewId = currentViewId ?? indexView?.id;
+ const currentView = currentViewFromViewId ?? indexView;
useEffect(() => {
setIsCurrentViewKeyIndex(currentView?.key === 'INDEX');
}, [currentView, setIsCurrentViewKeyIndex]);
- const viewsOnCurrentObject = getObjectMetadataItemViews(
- viewObjectMetadataId ?? '',
- views,
+ const viewsOnCurrentObject = useRecoilValue(
+ prefetchViewsFromObjectMetadataItemFamilySelector({
+ objectMetadataItemId: objectMetadataItem.id,
+ }),
);
const unsavedToUpsertViewFilters = useRecoilComponentFamilyValueV2(
diff --git a/packages/twenty-front/src/modules/views/hooks/useGetCurrentViewOnly.ts b/packages/twenty-front/src/modules/views/hooks/useGetCurrentViewOnly.ts
index e6fb9bed9e87..9614c25d943b 100644
--- a/packages/twenty-front/src/modules/views/hooks/useGetCurrentViewOnly.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useGetCurrentViewOnly.ts
@@ -1,19 +1,18 @@
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
+import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
-import { View } from '@/views/types/View';
-import { useMemo } from 'react';
+import { useRecoilValue } from 'recoil';
export const useGetCurrentViewOnly = () => {
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
-
- const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState);
+ const currentViewId = useRecoilComponentValueV2(
+ contextStoreCurrentViewIdComponentState,
+ );
- const currentView = useMemo(
- () => views.find((view) => view.id === currentViewId),
- [views, currentViewId],
+ const currentView = useRecoilValue(
+ prefetchViewFromViewIdFamilySelector({
+ viewId: currentViewId ?? '',
+ }),
);
return {
diff --git a/packages/twenty-front/src/modules/views/hooks/useGetViewFromCache.ts b/packages/twenty-front/src/modules/views/hooks/useGetViewFromCache.ts
deleted file mode 100644
index cdc95e1e8fbd..000000000000
--- a/packages/twenty-front/src/modules/views/hooks/useGetViewFromCache.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { useCallback } from 'react';
-import { useApolloClient } from '@apollo/client';
-
-import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
-import { useGetRecordFromCache } from '@/object-record/cache/hooks/useGetRecordFromCache';
-import { View } from '@/views/types/View';
-
-export const useGetViewFromCache = () => {
- const client = useApolloClient();
- const cache = client.cache;
-
- const getRecordFromCache = useGetRecordFromCache({
- objectNameSingular: CoreObjectNameSingular.View,
- });
-
- const getViewFromCache = useCallback(
- async (viewId: string) => {
- return getRecordFromCache(viewId, cache);
- },
- [cache, getRecordFromCache],
- );
-
- return {
- getViewFromCache,
- };
-};
diff --git a/packages/twenty-front/src/modules/views/hooks/useGetViewFromPrefetchState.ts b/packages/twenty-front/src/modules/views/hooks/useGetViewFromPrefetchState.ts
new file mode 100644
index 000000000000..1dc1d35f3e06
--- /dev/null
+++ b/packages/twenty-front/src/modules/views/hooks/useGetViewFromPrefetchState.ts
@@ -0,0 +1,24 @@
+import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
+import { useRecoilCallback } from 'recoil';
+
+export const useGetViewFromPrefetchState = () => {
+ const getViewFromPrefetchState = useRecoilCallback(
+ ({ snapshot }) =>
+ (viewId: string) => {
+ const view = snapshot
+ .getLoadable(
+ prefetchViewFromViewIdFamilySelector({
+ viewId: viewId,
+ }),
+ )
+ .getValue();
+
+ return view;
+ },
+ [],
+ );
+
+ return {
+ getViewFromPrefetchState,
+ };
+};
diff --git a/packages/twenty-front/src/modules/views/hooks/useQueryVariablesFromActiveFieldsOfViewOrDefaultView.ts b/packages/twenty-front/src/modules/views/hooks/useQueryVariablesFromActiveFieldsOfViewOrDefaultView.ts
index 048334c6f416..527f6b6b7acd 100644
--- a/packages/twenty-front/src/modules/views/hooks/useQueryVariablesFromActiveFieldsOfViewOrDefaultView.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useQueryVariablesFromActiveFieldsOfViewOrDefaultView.ts
@@ -6,14 +6,11 @@ import { getQueryVariablesFromView } from '@/views/utils/getQueryVariablesFromVi
export const useQueryVariablesFromActiveFieldsOfViewOrDefaultView = ({
objectMetadataItem,
- viewId,
}: {
objectMetadataItem: ObjectMetadataItem;
- viewId: string | null | undefined;
}) => {
const { view } = useViewOrDefaultViewFromPrefetchedViews({
objectMetadataItemId: objectMetadataItem.id,
- viewId,
});
const { activeFieldMetadataItems } = useActiveFieldMetadataItems({
diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts
index 832999fb885e..5c14c5e90ed4 100644
--- a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFields.ts
@@ -1,29 +1,23 @@
import { useRecoilCallback } from 'recoil';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords';
-import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
-import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState';
+import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
+import { isPersistingViewFieldsState } from '@/views/states/isPersistingViewFieldsState';
import { ViewField } from '@/views/types/ViewField';
import { isDefined } from 'twenty-shared';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
-export const useSaveCurrentViewFields = (viewBarComponentId?: string) => {
+export const useSaveCurrentViewFields = () => {
const { createViewFieldRecords, updateViewFieldRecords } =
usePersistViewFieldRecords();
- const { getViewFromCache } = useGetViewFromCache();
+ const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
- currentViewIdComponentState,
- viewBarComponentId,
- );
-
- const isPersistingViewFieldsCallbackState = useRecoilComponentCallbackStateV2(
- isPersistingViewFieldsComponentState,
- viewBarComponentId,
+ contextStoreCurrentViewIdComponentState,
);
const saveViewFields = useRecoilCallback(
@@ -37,9 +31,9 @@ export const useSaveCurrentViewFields = (viewBarComponentId?: string) => {
return;
}
- set(isPersistingViewFieldsCallbackState, true);
+ set(isPersistingViewFieldsState, true);
- const view = await getViewFromCache(currentViewId);
+ const view = await getViewFromPrefetchState(currentViewId);
if (isUndefinedOrNull(view)) {
return;
@@ -94,13 +88,12 @@ export const useSaveCurrentViewFields = (viewBarComponentId?: string) => {
updateViewFieldRecords(viewFieldsToUpdate),
]);
- set(isPersistingViewFieldsCallbackState, false);
+ set(isPersistingViewFieldsState, false);
},
[
createViewFieldRecords,
currentViewIdCallbackState,
- getViewFromCache,
- isPersistingViewFieldsCallbackState,
+ getViewFromPrefetchState,
updateViewFieldRecords,
],
);
diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts
index d74d8528be9c..ef8d7b0e7ae2 100644
--- a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewFiltersAndSorts.ts
@@ -1,13 +1,13 @@
import { useRecoilCallback } from 'recoil';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { usePersistViewFilterGroupRecords } from '@/views/hooks/internal/usePersistViewFilterGroupRecords';
import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords';
-import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
+import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
import { useSaveRecordFiltersToViewFilters } from '@/views/hooks/useSaveRecordFiltersToViewFilters';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { unsavedToDeleteViewFilterGroupIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterGroupIdsComponentFamilyState';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewFilterGroupsComponentFamilyState } from '@/views/states/unsavedToUpsertViewFilterGroupsComponentFamilyState';
@@ -18,10 +18,10 @@ import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
export const useSaveCurrentViewFiltersAndSorts = (
viewBarComponentId?: string,
) => {
- const { getViewFromCache } = useGetViewFromCache();
+ const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
- currentViewIdComponentState,
+ contextStoreCurrentViewIdComponentState,
viewBarComponentId,
);
@@ -77,7 +77,7 @@ export const useSaveCurrentViewFiltersAndSorts = (
unsavedToUpsertViewSortsCallbackState({ viewId }),
);
- const view = await getViewFromCache(viewId);
+ const view = await getViewFromPrefetchState(viewId);
if (isUndefinedOrNull(view)) {
return;
@@ -103,7 +103,7 @@ export const useSaveCurrentViewFiltersAndSorts = (
[
createViewSortRecords,
deleteViewSortRecords,
- getViewFromCache,
+ getViewFromPrefetchState,
unsavedToDeleteViewSortIdsCallbackState,
unsavedToUpsertViewSortsCallbackState,
updateViewSortRecords,
@@ -123,7 +123,7 @@ export const useSaveCurrentViewFiltersAndSorts = (
unsavedToUpsertViewFilterGroupsCallbackState({ viewId }),
);
- const view = await getViewFromCache(viewId);
+ const view = await getViewFromPrefetchState(viewId);
if (isUndefinedOrNull(view)) {
return;
@@ -150,7 +150,7 @@ export const useSaveCurrentViewFiltersAndSorts = (
await deleteViewFilterGroupRecords(unsavedToDeleteViewFilterGroupIds);
},
[
- getViewFromCache,
+ getViewFromPrefetchState,
createViewFilterGroupRecords,
deleteViewFilterGroupRecords,
unsavedToDeleteViewFilterGroupIdsCallbackState,
diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts
index 83c92ebdfb76..2c98521cb071 100644
--- a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts
@@ -1,9 +1,9 @@
import { useRecoilCallback } from 'recoil';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
import { usePersistViewGroupRecords } from '@/views/hooks/internal/usePersistViewGroupRecords';
-import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
+import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { ViewGroup } from '@/views/types/ViewGroup';
import { isDefined } from 'twenty-shared';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
@@ -13,10 +13,10 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => {
const { createViewGroupRecords, updateViewGroupRecords } =
usePersistViewGroupRecords();
- const { getViewFromCache } = useGetViewFromCache();
+ const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
- currentViewIdComponentState,
+ contextStoreCurrentViewIdComponentState,
viewBarComponentId,
);
@@ -31,7 +31,7 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => {
return;
}
- const view = await getViewFromCache(currentViewId);
+ const view = await getViewFromPrefetchState(currentViewId);
if (isUndefinedOrNull(view)) {
return;
@@ -67,7 +67,11 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => {
{ ...viewGroupToSave, id: existingField.id },
]);
},
- [currentViewIdCallbackState, getViewFromCache, updateViewGroupRecords],
+ [
+ currentViewIdCallbackState,
+ getViewFromPrefetchState,
+ updateViewGroupRecords,
+ ],
);
const saveViewGroups = useRecoilCallback(
@@ -81,7 +85,7 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => {
return;
}
- const view = await getViewFromCache(currentViewId);
+ const view = await getViewFromPrefetchState(currentViewId);
if (isUndefinedOrNull(view)) {
return;
@@ -135,7 +139,7 @@ export const useSaveCurrentViewGroups = (viewBarComponentId?: string) => {
[
createViewGroupRecords,
currentViewIdCallbackState,
- getViewFromCache,
+ getViewFromPrefetchState,
updateViewGroupRecords,
],
);
diff --git a/packages/twenty-front/src/modules/views/hooks/useUpdateCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useUpdateCurrentView.ts
index 8f3e151302cb..4c626d5d809d 100644
--- a/packages/twenty-front/src/modules/views/hooks/useUpdateCurrentView.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useUpdateCurrentView.ts
@@ -1,16 +1,15 @@
import { useRecoilCallback } from 'recoil';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { GraphQLView } from '@/views/types/GraphQLView';
import { isDefined } from 'twenty-shared';
-export const useUpdateCurrentView = (viewBarComponentId?: string) => {
+export const useUpdateCurrentView = () => {
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
- currentViewIdComponentState,
- viewBarComponentId,
+ contextStoreCurrentViewIdComponentState,
);
const { updateOneRecord } = useUpdateOneRecord({
diff --git a/packages/twenty-front/src/modules/views/hooks/useUpdateViewAggregate.ts b/packages/twenty-front/src/modules/views/hooks/useUpdateViewAggregate.ts
index c9924120a260..e65cbbbfc3cb 100644
--- a/packages/twenty-front/src/modules/views/hooks/useUpdateViewAggregate.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useUpdateViewAggregate.ts
@@ -1,12 +1,14 @@
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { ExtendedAggregateOperations } from '@/object-record/record-table/types/ExtendedAggregateOperations';
import { convertExtendedAggregateOperationToAggregateOperation } from '@/object-record/utils/convertExtendedAggregateOperationToAggregateOperation';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useUpdateView } from '@/views/hooks/useUpdateView';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { useCallback } from 'react';
export const useUpdateViewAggregate = () => {
- const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState);
+ const currentViewId = useRecoilComponentValueV2(
+ contextStoreCurrentViewIdComponentState,
+ );
const { updateView } = useUpdateView();
const updateViewAggregate = useCallback(
({
diff --git a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts
index 0457919fd415..9df11a992ab0 100644
--- a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewFilters.ts
@@ -1,10 +1,10 @@
import { useRecoilCallback } from 'recoil';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
+import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
import { ViewFilter } from '@/views/types/ViewFilter';
@@ -25,11 +25,11 @@ export const useUpsertCombinedViewFilters = (viewBarComponentId?: string) => {
);
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
- currentViewIdComponentState,
+ contextStoreCurrentViewIdComponentState,
viewBarComponentId,
);
- const { getViewFromCache } = useGetViewFromCache();
+ const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const upsertCombinedViewFilter = useRecoilCallback(
({ snapshot, set }) =>
@@ -53,7 +53,7 @@ export const useUpsertCombinedViewFilters = (viewBarComponentId?: string) => {
return;
}
- const currentView = await getViewFromCache(currentViewId);
+ const currentView = await getViewFromPrefetchState(currentViewId);
if (!currentView) {
return;
@@ -120,7 +120,7 @@ export const useUpsertCombinedViewFilters = (viewBarComponentId?: string) => {
},
[
currentViewIdCallbackState,
- getViewFromCache,
+ getViewFromPrefetchState,
unsavedToDeleteViewFilterIdsCallbackState,
unsavedToUpsertViewFiltersCallbackState,
],
diff --git a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts
index 1983a1ea6bde..0d9f1f283da8 100644
--- a/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useUpsertCombinedViewSorts.ts
@@ -1,11 +1,11 @@
import { useRecoilCallback } from 'recoil';
import { v4 } from 'uuid';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
-import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
-import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
+import { useGetViewFromPrefetchState } from '@/views/hooks/useGetViewFromPrefetchState';
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
import { ViewSort } from '@/views/types/ViewSort';
@@ -13,8 +13,7 @@ import { isDefined } from 'twenty-shared';
export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => {
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
- currentViewIdComponentState,
- viewBarComponentId,
+ contextStoreCurrentViewIdComponentState,
);
const unsavedToUpsertViewSortsCallbackState =
@@ -29,7 +28,7 @@ export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => {
viewBarComponentId,
);
- const { getViewFromCache } = useGetViewFromCache();
+ const { getViewFromPrefetchState } = useGetViewFromPrefetchState();
const upsertCombinedViewSort = useRecoilCallback(
({ snapshot, set }) =>
@@ -53,7 +52,7 @@ export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => {
return;
}
- const currentView = await getViewFromCache(currentViewId);
+ const currentView = await getViewFromPrefetchState(currentViewId);
if (!currentView) {
return;
@@ -111,7 +110,7 @@ export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => {
},
[
currentViewIdCallbackState,
- getViewFromCache,
+ getViewFromPrefetchState,
unsavedToDeleteViewSortIdsCallbackState,
unsavedToUpsertViewSortsCallbackState,
],
diff --git a/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts b/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts
index 40bd3d7a7393..26ee0b327941 100644
--- a/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts
+++ b/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts
@@ -1,24 +1,23 @@
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
-import { View } from '@/views/types/View';
-import { useMemo } from 'react';
+import { prefetchIndexViewIdFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchIndexViewIdFromObjectMetadataItemFamilySelector';
+import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
+import { useRecoilValue } from 'recoil';
export const useViewOrDefaultViewFromPrefetchedViews = ({
objectMetadataItemId,
- viewId,
}: {
objectMetadataItemId: string;
- viewId: string | null | undefined;
}) => {
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
+ const indexViewId = useRecoilValue(
+ prefetchIndexViewIdFromObjectMetadataItemFamilySelector({
+ objectMetadataItemId,
+ }),
+ );
- const view = useMemo(() => {
- return views.find(
- (view: View) =>
- (view.key === 'INDEX' || view?.id === viewId) &&
- view?.objectMetadataId === objectMetadataItemId,
- );
- }, [viewId, views, objectMetadataItemId]);
+ const indexView = useRecoilValue(
+ prefetchViewFromViewIdFamilySelector({
+ viewId: indexViewId ?? '',
+ }),
+ );
- return { view };
+ return { view: indexView };
};
diff --git a/packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts b/packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts
deleted file mode 100644
index 40b7ecb61836..000000000000
--- a/packages/twenty-front/src/modules/views/states/currentViewIdComponentState.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
-import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
-
-export const currentViewIdComponentState = createComponentStateV2<
- string | undefined
->({
- key: 'currentViewIdComponentState',
- defaultValue: undefined,
- componentInstanceContext: ViewComponentInstanceContext,
-});
diff --git a/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts b/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts
deleted file mode 100644
index 7ddaa5e43d0c..000000000000
--- a/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsComponentState.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
-import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
-
-export const isPersistingViewFieldsComponentState =
- createComponentStateV2({
- key: 'isPersistingViewFieldsComponentState',
- defaultValue: false,
- componentInstanceContext: ViewComponentInstanceContext,
- });
diff --git a/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsState.ts b/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsState.ts
new file mode 100644
index 000000000000..40dc43ab1942
--- /dev/null
+++ b/packages/twenty-front/src/modules/views/states/isPersistingViewFieldsState.ts
@@ -0,0 +1,6 @@
+import { createState } from 'twenty-ui';
+
+export const isPersistingViewFieldsState = createState({
+ key: 'isPersistingViewFieldsState',
+ defaultValue: false,
+});
diff --git a/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts b/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts
index 3aa843660094..d6ee94537285 100644
--- a/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts
+++ b/packages/twenty-front/src/modules/views/utils/mapViewFiltersToFilters.ts
@@ -18,9 +18,8 @@ export const mapViewFiltersToFilters = (
);
if (!isDefined(availableFieldMetadataItem)) {
- throw new Error(
- `Field metadata item not found for view filter ${viewFilter.id} and field metadata id ${viewFilter.fieldMetadataId}`,
- );
+ // Todo: we we don't throw an error yet as we have race condition on view change
+ return undefined;
}
const filterType = getFilterTypeFromFieldType(
diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEffect.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEffect.tsx
index eaacac4173c2..34d4076e23eb 100644
--- a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEffect.tsx
+++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerContentEffect.tsx
@@ -1,9 +1,10 @@
import { useEffect } from 'react';
+import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
+import { prefetchViewsFromObjectMetadataItemFamilySelector } from '@/prefetch/states/selector/prefetchViewsFromObjectMetadataItemFamilySelector';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
-import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { ViewType } from '@/views/types/ViewType';
import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban';
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
@@ -14,6 +15,7 @@ import { viewPickerKanbanFieldMetadataIdComponentState } from '@/views/view-pick
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
import { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState';
import { viewPickerTypeComponentState } from '@/views/view-picker/states/viewPickerTypeComponentState';
+import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared';
export const ViewPickerContentEffect = () => {
@@ -44,7 +46,13 @@ export const ViewPickerContentEffect = () => {
viewPickerIsPersistingComponentState,
);
- const { viewsOnCurrentObject } = useGetCurrentView();
+ const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
+ const viewsOnCurrentObject = useRecoilValue(
+ prefetchViewsFromObjectMetadataItemFamilySelector({
+ objectMetadataItemId: objectMetadataItem.id,
+ }),
+ );
+
const referenceView = viewsOnCurrentObject.find(
(view) => view.id === viewPickerReferenceViewId,
);
diff --git a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerFavoriteFoldersDropdown.tsx b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerFavoriteFoldersDropdown.tsx
index 470337e77687..587b3008b0b3 100644
--- a/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerFavoriteFoldersDropdown.tsx
+++ b/packages/twenty-front/src/modules/views/view-picker/components/ViewPickerFavoriteFoldersDropdown.tsx
@@ -1,21 +1,23 @@
import { FavoriteFolderPicker } from '@/favorites/favorite-folder-picker/components/FavoriteFolderPicker';
import { FavoriteFolderPickerEffect } from '@/favorites/favorite-folder-picker/components/FavoriteFolderPickerEffect';
import { FavoriteFolderPickerComponentInstanceContext } from '@/favorites/favorite-folder-picker/scopes/FavoriteFolderPickerScope';
-import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
-import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
+import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
-import { View } from '@/views/types/View';
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
+import { useRecoilValue } from 'recoil';
export const ViewPickerFavoriteFoldersDropdown = () => {
- const { records: views } = usePrefetchedData(PrefetchKey.AllViews);
const [viewPickerReferenceViewId] = useRecoilComponentStateV2(
viewPickerReferenceViewIdComponentState,
);
- const view = views.find((view) => view.id === viewPickerReferenceViewId);
+ const view = useRecoilValue(
+ prefetchViewFromViewIdFamilySelector({
+ viewId: viewPickerReferenceViewId ?? '',
+ }),
+ );
return (
{
const { currentViewWithCombinedFiltersAndSorts, viewsOnCurrentObject } =
useGetCurrentView();
+
const setViewPickerReferenceViewId = useSetRecoilComponentStateV2(
viewPickerReferenceViewIdComponentState,
);
diff --git a/packages/twenty-front/src/modules/views/view-picker/hooks/useCloseAndResetViewPicker.ts b/packages/twenty-front/src/modules/views/view-picker/hooks/useCloseAndResetViewPicker.ts
index 46fde3f74a19..d6dbe903ae82 100644
--- a/packages/twenty-front/src/modules/views/view-picker/hooks/useCloseAndResetViewPicker.ts
+++ b/packages/twenty-front/src/modules/views/view-picker/hooks/useCloseAndResetViewPicker.ts
@@ -1,45 +1,31 @@
import { useCallback } from 'react';
-import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
+import { useDropdownV2 } from '@/ui/layout/dropdown/hooks/useDropdownV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
import { VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerKanbanFieldDropdownId';
import { VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerViewTypeDropdownId';
-import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState';
+import { viewPickerModeComponentState } from '@/views/view-picker/states/viewPickerModeComponentState';
export const useCloseAndResetViewPicker = () => {
- const { setViewPickerMode } = useViewPickerMode();
+ const setViewPickerMode = useSetRecoilComponentStateV2(
+ viewPickerModeComponentState,
+ );
const setViewPickerIsPersisting = useSetRecoilComponentStateV2(
viewPickerIsPersistingComponentState,
);
- const { closeDropdown: closeViewPickerDropdown } = useDropdown(
- VIEW_PICKER_DROPDOWN_ID,
- );
-
- const { closeDropdown: closeKanbanFieldDropdown } = useDropdown(
- VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID,
- );
-
- const { closeDropdown: closeTypeDropdown } = useDropdown(
- VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID,
- );
+ const { closeDropdown } = useDropdownV2();
const closeAndResetViewPicker = useCallback(() => {
setViewPickerIsPersisting(false);
setViewPickerMode('list');
- closeKanbanFieldDropdown();
- closeTypeDropdown();
- closeViewPickerDropdown();
- }, [
- closeKanbanFieldDropdown,
- closeTypeDropdown,
- closeViewPickerDropdown,
- setViewPickerIsPersisting,
- setViewPickerMode,
- ]);
+ closeDropdown(VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID);
+ closeDropdown(VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID);
+ closeDropdown(VIEW_PICKER_DROPDOWN_ID);
+ }, [closeDropdown, setViewPickerIsPersisting, setViewPickerMode]);
return { closeAndResetViewPicker };
};
diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionFormCreateRecord.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionFormCreateRecord.tsx
index 768f6f8b9e94..b91ffebd8884 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionFormCreateRecord.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/components/WorkflowEditActionFormCreateRecord.tsx
@@ -83,7 +83,6 @@ export const WorkflowEditActionFormCreateRecord = ({
const { view: indexView } = useViewOrDefaultViewFromPrefetchedViews({
objectMetadataItemId: objectMetadataItem.id ?? '',
- viewId: undefined,
});
const viewFields = indexView?.viewFields ?? [];
diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx
index f151507dc6f1..46719d9ea49b 100644
--- a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx
+++ b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx
@@ -1,74 +1,26 @@
-import styled from '@emotion/styled';
-import { useParams } from 'react-router-dom';
-
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
-import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId';
-import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
-import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
-import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId';
-import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext';
-import { RecordIndexContainer } from '@/object-record/record-index/components/RecordIndexContainer';
-import { RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect } from '@/object-record/record-index/components/RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect';
-import { RecordIndexContainerContextStoreObjectMetadataEffect } from '@/object-record/record-index/components/RecordIndexContainerContextStoreObjectMetadataEffect';
-import { RecordIndexPageHeader } from '@/object-record/record-index/components/RecordIndexPageHeader';
-import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext';
-import { useHandleIndexIdentifierClick } from '@/object-record/record-index/hooks/useHandleIndexIdentifierClick';
-import { PageBody } from '@/ui/layout/page/components/PageBody';
+import { RecordIndexContainerGater } from '@/object-record/record-index/components/RecordIndexContainerGater';
import { PageContainer } from '@/ui/layout/page/components/PageContainer';
-import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
-import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
-import { isUndefined } from '@sniptt/guards';
-import { useRecoilCallback, useRecoilValue } from 'recoil';
-import { capitalize } from 'twenty-shared';
-
-const StyledIndexContainer = styled.div`
- display: flex;
- height: 100%;
- width: 100%;
-`;
+import { isNonEmptyString, isUndefined } from '@sniptt/guards';
export const RecordIndexPage = () => {
- const objectNamePlural = useParams().objectNamePlural ?? '';
-
- const mainContextStoreComponentInstanceId = useRecoilValue(
- mainContextStoreComponentInstanceIdState,
- );
-
const contextStoreCurrentViewId = useRecoilComponentValueV2(
contextStoreCurrentViewIdComponentState,
- mainContextStoreComponentInstanceId,
+ 'main-context-store',
);
- // Todo: if we want the recordIndexId to contain the viewId, we need to remove the Effects otherwise we will have race condition on view change
- const recordIndexId = `${objectNamePlural}`;
-
- const { objectNameSingular } = useObjectNameSingularFromPlural({
- objectNamePlural,
- });
-
- const { objectMetadataItem } = useObjectMetadataItem({
- objectNameSingular,
- });
-
- const { indexIdentifierUrl } = useHandleIndexIdentifierClick({
- objectMetadataItem,
- recordIndexId,
- });
-
- const handleIndexRecordsLoaded = useRecoilCallback(
- ({ set }) =>
- () => {
- // TODO: find a better way to reset this state ?
- set(lastShowPageRecordIdState, null);
- },
- [],
+ const objectMetadataItem = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
+ 'main-context-store',
);
- if (isUndefined(contextStoreCurrentViewId)) {
+ if (
+ isUndefined(objectMetadataItem) ||
+ !isNonEmptyString(contextStoreCurrentViewId)
+ ) {
return null;
}
@@ -76,43 +28,10 @@ export const RecordIndexPage = () => {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
);
diff --git a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx
index e0f62e4bb8c4..c4626d4e3b93 100644
--- a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx
+++ b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx
@@ -51,7 +51,7 @@ export const RecordShowPage = () => {
value={{ instanceId: `record-show-${objectRecordId}` }}
>
{
+ const { contextStore } = context.parameters;
+
+ let componentInstanceId = contextStore?.componentInstanceId;
+
+ if (isUndefined(componentInstanceId)) {
+ componentInstanceId = 'main-context-store';
+ }
+
+ const setCurrentObjectMetadataItem = useSetRecoilComponentStateV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
+ componentInstanceId,
+ );
+
+ const [isLoaded, setIsLoaded] = useState(false);
+
+ const objectMetadataItem = getCompanyObjectMetadataItem();
+
+ useEffect(() => {
+ setCurrentObjectMetadataItem(objectMetadataItem);
+ setIsLoaded(true);
+ }, [setCurrentObjectMetadataItem, objectMetadataItem]);
+
+ return (
+
+ {isLoaded && }
+
+ );
+};
diff --git a/packages/twenty-front/src/testing/decorators/PrefetchLoadedDecorator.tsx b/packages/twenty-front/src/testing/decorators/PrefetchLoadedDecorator.tsx
index f9e35c56b258..9e856f7ea3a1 100644
--- a/packages/twenty-front/src/testing/decorators/PrefetchLoadedDecorator.tsx
+++ b/packages/twenty-front/src/testing/decorators/PrefetchLoadedDecorator.tsx
@@ -5,9 +5,6 @@ import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedF
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
export const PrefetchLoadedDecorator: Decorator = (Story) => {
- const setAreViewsPrefetched = useSetRecoilState(
- prefetchIsLoadedFamilyState(PrefetchKey.AllViews),
- );
const setAreFavoritesPrefetched = useSetRecoilState(
prefetchIsLoadedFamilyState(PrefetchKey.AllFavorites),
);
@@ -15,7 +12,6 @@ export const PrefetchLoadedDecorator: Decorator = (Story) => {
prefetchIsLoadedFamilyState(PrefetchKey.AllFavoritesFolders),
);
- setAreViewsPrefetched(true);
setAreFavoritesPrefetched(true);
setAreFavoritesFoldersPrefetched(true);
diff --git a/packages/twenty-front/src/testing/decorators/PrefetchLoadingDecorator.tsx b/packages/twenty-front/src/testing/decorators/PrefetchLoadingDecorator.tsx
index 12290c724b0e..76f87a69102b 100644
--- a/packages/twenty-front/src/testing/decorators/PrefetchLoadingDecorator.tsx
+++ b/packages/twenty-front/src/testing/decorators/PrefetchLoadingDecorator.tsx
@@ -5,14 +5,10 @@ import { prefetchIsLoadedFamilyState } from '@/prefetch/states/prefetchIsLoadedF
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
export const PrefetchLoadingDecorator: Decorator = (Story) => {
- const setAreViewsPrefetched = useSetRecoilState(
- prefetchIsLoadedFamilyState(PrefetchKey.AllViews),
- );
const setAreFavoritesPrefetched = useSetRecoilState(
- prefetchIsLoadedFamilyState(PrefetchKey.AllFavorites),
+ prefetchIsLoadedFamilyState(PrefetchKey.AllFavoritesFolders),
);
- setAreViewsPrefetched(false);
setAreFavoritesPrefetched(false);
return ;
diff --git a/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx b/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx
index b54dedf390be..f51a3557f539 100644
--- a/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx
+++ b/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx
@@ -1,6 +1,6 @@
import { PropsWithChildren, useEffect, useState } from 'react';
-import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
+import { contextStoreCurrentObjectMetadataItemComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemComponentState';
import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState';
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
import {
@@ -34,8 +34,8 @@ export const JestContextStoreSetter = ({
contextStoreTargetedRecordsRuleComponentState,
);
- const setContextStoreCurrentObjectMetadataId = useSetRecoilComponentStateV2(
- contextStoreCurrentObjectMetadataIdComponentState,
+ const setContextStoreCurrentObjectMetadataItem = useSetRecoilComponentStateV2(
+ contextStoreCurrentObjectMetadataItemComponentState,
);
const setContextStoreNumberOfSelectedRecords = useSetRecoilComponentStateV2(
@@ -55,20 +55,21 @@ export const JestContextStoreSetter = ({
const [isLoaded, setIsLoaded] = useState(false);
useEffect(() => {
setContextStoreTargetedRecordsRule(contextStoreTargetedRecordsRule);
- setContextStoreCurrentObjectMetadataId(contextStoreCurrentObjectMetadataId);
+ setContextStoreCurrentObjectMetadataItem(objectMetadataItem);
setContextStoreNumberOfSelectedRecords(contextStoreNumberOfSelectedRecords);
setcontextStoreFiltersComponentState(contextStoreFilters);
setIsLoaded(true);
}, [
setContextStoreTargetedRecordsRule,
- setContextStoreCurrentObjectMetadataId,
+ setContextStoreCurrentObjectMetadataItem,
contextStoreTargetedRecordsRule,
contextStoreCurrentObjectMetadataId,
setContextStoreNumberOfSelectedRecords,
contextStoreNumberOfSelectedRecords,
setcontextStoreFiltersComponentState,
contextStoreFilters,
+ objectMetadataItem,
]);
return isLoaded ? <>{children}> : null;