From 6843a642b595573a5dfc118a0e907bbcddc8ae9e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Bosi?=
<71827178+bosiraphael@users.noreply.github.com>
Date: Tue, 22 Oct 2024 18:35:45 +0200
Subject: [PATCH] 7499 refactor right drawer to have contextual actions (#7954)
Closes #7499
- Modifies context store states to be component states
- Introduces the concept of `mainContextStore` which will dictate the
available actions inside the command K
- Adds contextual actions inside the right drawer
- Creates a new type of modal variant
---
.../components/DeleteRecordsActionEffect.tsx | 33 +++--
.../ManageFavoritesActionEffect.tsx | 7 +-
...MultipleRecordsActionMenuEntriesSetter.tsx | 4 +
.../RecordActionMenuEntriesSetter.tsx | 23 +--
.../SingleRecordActionMenuEntriesSetter.tsx | 4 +
.../action-menu/components/ActionMenu.tsx | 30 ----
.../components/RecordIndexActionMenu.tsx | 35 +++++
...nuBar.tsx => RecordIndexActionMenuBar.tsx} | 13 +-
....tsx => RecordIndexActionMenuBarEntry.tsx} | 6 +-
....tsx => RecordIndexActionMenuDropdown.tsx} | 6 +-
...ct.tsx => RecordIndexActionMenuEffect.tsx} | 9 +-
.../components/RecordShowActionMenu.tsx | 31 +++++
.../components/RecordShowActionMenuBar.tsx | 16 +++
.../RecordShowActionMenuBarEntry.tsx | 53 +++++++
.../__stories__/ActionMenuBar.stories.tsx | 116 ----------------
.../RecordIndexActionMenuBar.stories.tsx | 131 ++++++++++++++++++
...RecordIndexActionMenuBarEntry.stories.tsx} | 10 +-
...RecordIndexActionMenuDropdown.stories.tsx} | 14 +-
.../RecordShowActionMenuBar.stories.tsx | 131 ++++++++++++++++++
...tionMenuDropdownPositionComponentState.ts} | 4 +-
.../action-menu/types/ActionMenuType.ts | 1 +
...nContextStoreComponentInstanceIdEffect.tsx | 22 +++
...reCurrentObjectMetadataIdComponentState.ts | 9 ++
...ontextStoreCurrentObjectMetadataIdState.ts | 8 --
...contextStoreCurrentViewIdComponentState.ts | 10 ++
.../states/contextStoreCurrentViewIdState.ts | 6 -
...reNumberOfSelectedRecordsComponentState.ts | 9 ++
...ontextStoreNumberOfSelectedRecordsState.ts | 6 -
...StoreTargetedRecordsRuleComponentState.ts} | 10 +-
.../ContextStoreComponentInstanceContext.tsx | 4 +
.../mainContextStoreComponentInstanceId.ts | 8 ++
.../computeContextStoreFilters.test.ts | 2 +-
.../utils/computeContextStoreFilters.ts | 2 +-
.../components/RecordBoardCard.tsx | 4 +-
.../RecordIndexBoardDataLoaderEffect.tsx | 7 +-
.../components/RecordIndexContainer.tsx | 11 +-
...textStoreNumberOfSelectedRecordsEffect.tsx | 15 +-
...tainerContextStoreObjectMetadataEffect.tsx | 8 +-
.../RecordIndexTableContainerEffect.tsx | 9 +-
.../hooks/__tests__/useRecordData.test.tsx | 3 +-
.../options/hooks/useRecordData.ts | 7 +-
.../components/RecordShowContainer.tsx | 18 ++-
.../RecordShowContainerContextStoreEffect.tsx | 56 ++++++++
.../hooks/useTriggerActionMenuDropdown.ts | 4 +-
.../modal/components/ConfirmationModal.tsx | 5 +-
.../ui/layout/modal/components/Modal.tsx | 6 +-
.../page/components/RightDrawerContainer.tsx | 52 -------
.../components/ShowPageSubContainer.tsx | 24 +---
.../components/QueryParamsViewIdEffect.tsx | 8 +-
.../pages/object-record/RecordIndexPage.tsx | 15 +-
.../pages/object-record/RecordShowPage.tsx | 2 -
.../RecordShowPageContextStoreEffect.tsx | 57 --------
.../testing/jest/JestContextStoreSetter.tsx | 17 +--
...taAndApolloMocksAndContextStoreWrapper.tsx | 25 ++--
.../src/theme/constants/BackgroundDark.ts | 5 +-
.../src/theme/constants/BackgroundLight.ts | 5 +-
56 files changed, 718 insertions(+), 418 deletions(-)
delete mode 100644 packages/twenty-front/src/modules/action-menu/components/ActionMenu.tsx
create mode 100644 packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx
rename packages/twenty-front/src/modules/action-menu/components/{ActionMenuBar.tsx => RecordIndexActionMenuBar.tsx} (76%)
rename packages/twenty-front/src/modules/action-menu/components/{ActionMenuBarEntry.tsx => RecordIndexActionMenuBarEntry.tsx} (89%)
rename packages/twenty-front/src/modules/action-menu/components/{ActionMenuDropdown.tsx => RecordIndexActionMenuDropdown.tsx} (91%)
rename packages/twenty-front/src/modules/action-menu/components/{ActionMenuEffect.tsx => RecordIndexActionMenuEffect.tsx} (77%)
create mode 100644 packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenu.tsx
create mode 100644 packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenuBar.tsx
create mode 100644 packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenuBarEntry.tsx
delete mode 100644 packages/twenty-front/src/modules/action-menu/components/__stories__/ActionMenuBar.stories.tsx
create mode 100644 packages/twenty-front/src/modules/action-menu/components/__stories__/RecordIndexActionMenuBar.stories.tsx
rename packages/twenty-front/src/modules/action-menu/components/__stories__/{ActionMenuBarEntry.stories.tsx => RecordIndexActionMenuBarEntry.stories.tsx} (78%)
rename packages/twenty-front/src/modules/action-menu/components/__stories__/{ActionMenuDropdown.stories.tsx => RecordIndexActionMenuDropdown.stories.tsx} (85%)
create mode 100644 packages/twenty-front/src/modules/action-menu/components/__stories__/RecordShowActionMenuBar.stories.tsx
rename packages/twenty-front/src/modules/action-menu/states/{actionMenuDropdownPositionComponentState.ts => recordIndexActionMenuDropdownPositionComponentState.ts} (67%)
create mode 100644 packages/twenty-front/src/modules/action-menu/types/ActionMenuType.ts
create mode 100644 packages/twenty-front/src/modules/context-store/components/SetMainContextStoreComponentInstanceIdEffect.tsx
create mode 100644 packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdComponentState.ts
delete mode 100644 packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdState.ts
create mode 100644 packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdComponentState.ts
delete mode 100644 packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdState.ts
create mode 100644 packages/twenty-front/src/modules/context-store/states/contextStoreNumberOfSelectedRecordsComponentState.ts
delete mode 100644 packages/twenty-front/src/modules/context-store/states/contextStoreNumberOfSelectedRecordsState.ts
rename packages/twenty-front/src/modules/context-store/states/{contextStoreTargetedRecordsRuleState.ts => contextStoreTargetedRecordsRuleComponentState.ts} (53%)
create mode 100644 packages/twenty-front/src/modules/context-store/states/contexts/ContextStoreComponentInstanceContext.tsx
create mode 100644 packages/twenty-front/src/modules/context-store/states/mainContextStoreComponentInstanceId.ts
create mode 100644 packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerContextStoreEffect.tsx
delete mode 100644 packages/twenty-front/src/modules/ui/layout/page/components/RightDrawerContainer.tsx
delete mode 100644 packages/twenty-front/src/pages/object-record/RecordShowPageContextStoreEffect.tsx
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/DeleteRecordsActionEffect.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/DeleteRecordsActionEffect.tsx
index dfa609fc05..a1f1f34f1d 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/DeleteRecordsActionEffect.tsx
+++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/DeleteRecordsActionEffect.tsx
@@ -1,6 +1,7 @@
import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries';
-import { contextStoreNumberOfSelectedRecordsState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsState';
-import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
+import { ActionMenuType } from '@/action-menu/types/ActionMenuType';
+import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
+import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
@@ -9,16 +10,19 @@ import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords
import { useFetchAllRecordIds } from '@/object-record/hooks/useFetchAllRecordIds';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
+import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useCallback, useEffect, useState } from 'react';
-import { useRecoilValue } from 'recoil';
import { IconTrash, isDefined } from 'twenty-ui';
export const DeleteRecordsActionEffect = ({
position,
objectMetadataItem,
+ actionMenuType,
}: {
position: number;
objectMetadataItem: ObjectMetadataItem;
+ actionMenuType: ActionMenuType;
}) => {
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
@@ -35,12 +39,12 @@ export const DeleteRecordsActionEffect = ({
const { favorites, deleteFavorite } = useFavorites();
- const contextStoreNumberOfSelectedRecords = useRecoilValue(
- contextStoreNumberOfSelectedRecordsState,
+ const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
+ contextStoreNumberOfSelectedRecordsComponentState,
);
- const contextStoreTargetedRecordsRule = useRecoilValue(
- contextStoreTargetedRecordsRuleState,
+ const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
+ contextStoreTargetedRecordsRuleComponentState,
);
const graphqlFilter = computeContextStoreFilters(
@@ -53,6 +57,8 @@ export const DeleteRecordsActionEffect = ({
filter: graphqlFilter,
});
+ const { closeRightDrawer } = useRightDrawer();
+
const handleDeleteClick = useCallback(async () => {
const recordIdsToDelete = await fetchAllRecordIds();
@@ -112,10 +118,19 @@ export const DeleteRecordsActionEffect = ({
}? ${
contextStoreNumberOfSelectedRecords === 1 ? 'It' : 'They'
} can be recovered from the Options menu.`}
- onConfirmClick={() => handleDeleteClick()}
+ onConfirmClick={() => {
+ handleDeleteClick();
+
+ if (actionMenuType === 'recordShow') {
+ closeRightDrawer();
+ }
+ }}
deleteButtonText={`Delete ${
contextStoreNumberOfSelectedRecords > 1 ? 'Records' : 'Record'
}`}
+ modalVariant={
+ actionMenuType === 'recordShow' ? 'tertiary' : 'primary'
+ }
/>
),
});
@@ -127,8 +142,10 @@ export const DeleteRecordsActionEffect = ({
removeActionMenuEntry('delete');
};
}, [
+ actionMenuType,
addActionMenuEntry,
canDelete,
+ closeRightDrawer,
contextStoreNumberOfSelectedRecords,
handleDeleteClick,
isDeleteRecordsModalOpen,
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/ManageFavoritesActionEffect.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/ManageFavoritesActionEffect.tsx
index 572bc23939..face480344 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/ManageFavoritesActionEffect.tsx
+++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/ManageFavoritesActionEffect.tsx
@@ -1,8 +1,9 @@
import { useActionMenuEntries } from '@/action-menu/hooks/useActionMenuEntries';
-import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
+import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { useEffect } from 'react';
import { useRecoilValue } from 'recoil';
import { IconHeart, IconHeartOff, isDefined } from 'twenty-ui';
@@ -16,8 +17,8 @@ export const ManageFavoritesActionEffect = ({
}) => {
const { addActionMenuEntry, removeActionMenuEntry } = useActionMenuEntries();
- const contextStoreTargetedRecordsRule = useRecoilValue(
- contextStoreTargetedRecordsRuleState,
+ const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
+ contextStoreTargetedRecordsRuleComponentState,
);
const { favorites, createFavorite, deleteFavorite } = useFavorites();
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/MultipleRecordsActionMenuEntriesSetter.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/MultipleRecordsActionMenuEntriesSetter.tsx
index ad47a1ee17..f1fcd52c9b 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/MultipleRecordsActionMenuEntriesSetter.tsx
+++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/MultipleRecordsActionMenuEntriesSetter.tsx
@@ -1,13 +1,16 @@
import { DeleteRecordsActionEffect } from '@/action-menu/actions/record-actions/components/DeleteRecordsActionEffect';
import { ExportRecordsActionEffect } from '@/action-menu/actions/record-actions/components/ExportRecordsActionEffect';
+import { ActionMenuType } from '@/action-menu/types/ActionMenuType';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
const actionEffects = [ExportRecordsActionEffect, DeleteRecordsActionEffect];
export const MultipleRecordsActionMenuEntriesSetter = ({
objectMetadataItem,
+ actionMenuType,
}: {
objectMetadataItem: ObjectMetadataItem;
+ actionMenuType: ActionMenuType;
}) => {
return (
<>
@@ -16,6 +19,7 @@ export const MultipleRecordsActionMenuEntriesSetter = ({
key={index}
position={index}
objectMetadataItem={objectMetadataItem}
+ actionMenuType={actionMenuType}
/>
))}
>
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 acf4a9bed7..5ed405684b 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
@@ -1,17 +1,22 @@
import { MultipleRecordsActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/MultipleRecordsActionMenuEntriesSetter';
import { SingleRecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/SingleRecordActionMenuEntriesSetter';
-import { contextStoreCurrentObjectMetadataIdState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdState';
-import { contextStoreNumberOfSelectedRecordsState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsState';
+import { ActionMenuType } from '@/action-menu/types/ActionMenuType';
+import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
+import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
import { useObjectMetadataItemById } from '@/object-metadata/hooks/useObjectMetadataItemById';
-import { useRecoilValue } from 'recoil';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
-export const RecordActionMenuEntriesSetter = () => {
- const contextStoreNumberOfSelectedRecords = useRecoilValue(
- contextStoreNumberOfSelectedRecordsState,
+export const RecordActionMenuEntriesSetter = ({
+ actionMenuType,
+}: {
+ actionMenuType: ActionMenuType;
+}) => {
+ const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
+ contextStoreNumberOfSelectedRecordsComponentState,
);
- const contextStoreCurrentObjectMetadataId = useRecoilValue(
- contextStoreCurrentObjectMetadataIdState,
+ const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataIdComponentState,
);
const { objectMetadataItem } = useObjectMetadataItemById({
@@ -32,6 +37,7 @@ export const RecordActionMenuEntriesSetter = () => {
return (
);
}
@@ -39,6 +45,7 @@ export const RecordActionMenuEntriesSetter = () => {
return (
);
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/SingleRecordActionMenuEntriesSetter.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/SingleRecordActionMenuEntriesSetter.tsx
index 9c4b1d528f..7bf10746fb 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/SingleRecordActionMenuEntriesSetter.tsx
+++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/components/SingleRecordActionMenuEntriesSetter.tsx
@@ -1,12 +1,15 @@
import { DeleteRecordsActionEffect } from '@/action-menu/actions/record-actions/components/DeleteRecordsActionEffect';
import { ExportRecordsActionEffect } from '@/action-menu/actions/record-actions/components/ExportRecordsActionEffect';
import { ManageFavoritesActionEffect } from '@/action-menu/actions/record-actions/components/ManageFavoritesActionEffect';
+import { ActionMenuType } from '@/action-menu/types/ActionMenuType';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
export const SingleRecordActionMenuEntriesSetter = ({
objectMetadataItem,
+ actionMenuType,
}: {
objectMetadataItem: ObjectMetadataItem;
+ actionMenuType: ActionMenuType;
}) => {
const actionEffects = [
ManageFavoritesActionEffect,
@@ -20,6 +23,7 @@ export const SingleRecordActionMenuEntriesSetter = ({
key={index}
position={index}
objectMetadataItem={objectMetadataItem}
+ actionMenuType={actionMenuType}
/>
))}
>
diff --git a/packages/twenty-front/src/modules/action-menu/components/ActionMenu.tsx b/packages/twenty-front/src/modules/action-menu/components/ActionMenu.tsx
deleted file mode 100644
index 92cda27cc9..0000000000
--- a/packages/twenty-front/src/modules/action-menu/components/ActionMenu.tsx
+++ /dev/null
@@ -1,30 +0,0 @@
-import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter';
-import { ActionMenuBar } from '@/action-menu/components/ActionMenuBar';
-import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
-import { ActionMenuDropdown } from '@/action-menu/components/ActionMenuDropdown';
-import { ActionMenuEffect } from '@/action-menu/components/ActionMenuEffect';
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { contextStoreCurrentObjectMetadataIdState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdState';
-import { useRecoilValue } from 'recoil';
-
-export const ActionMenu = ({ actionMenuId }: { actionMenuId: string }) => {
- const contextStoreCurrentObjectMetadataId = useRecoilValue(
- contextStoreCurrentObjectMetadataIdState,
- );
-
- return (
- <>
- {contextStoreCurrentObjectMetadataId && (
-
-
-
-
-
-
-
- )}
- >
- );
-};
diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx
new file mode 100644
index 0000000000..866303d3f5
--- /dev/null
+++ b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx
@@ -0,0 +1,35 @@
+import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter';
+import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
+import { RecordIndexActionMenuBar } from '@/action-menu/components/RecordIndexActionMenuBar';
+import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown';
+import { RecordIndexActionMenuEffect } from '@/action-menu/components/RecordIndexActionMenuEffect';
+
+import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
+import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
+
+export const RecordIndexActionMenu = ({
+ actionMenuId,
+}: {
+ actionMenuId: string;
+}) => {
+ const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataIdComponentState,
+ );
+
+ return (
+ <>
+ {contextStoreCurrentObjectMetadataId && (
+
+
+
+
+
+
+
+ )}
+ >
+ );
+};
diff --git a/packages/twenty-front/src/modules/action-menu/components/ActionMenuBar.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuBar.tsx
similarity index 76%
rename from packages/twenty-front/src/modules/action-menu/components/ActionMenuBar.tsx
rename to packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuBar.tsx
index 2fd2937408..ea0383727e 100644
--- a/packages/twenty-front/src/modules/action-menu/components/ActionMenuBar.tsx
+++ b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuBar.tsx
@@ -1,14 +1,13 @@
import styled from '@emotion/styled';
-import { ActionMenuBarEntry } from '@/action-menu/components/ActionMenuBarEntry';
+import { RecordIndexActionMenuBarEntry } from '@/action-menu/components/RecordIndexActionMenuBarEntry';
import { actionMenuEntriesComponentSelector } from '@/action-menu/states/actionMenuEntriesComponentSelector';
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
import { ActionBarHotkeyScope } from '@/action-menu/types/ActionBarHotKeyScope';
-import { contextStoreNumberOfSelectedRecordsState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsState';
+import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
import { BottomBar } from '@/ui/layout/bottom-bar/components/BottomBar';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
-import { useRecoilValue } from 'recoil';
const StyledLabel = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
@@ -18,9 +17,9 @@ const StyledLabel = styled.div`
padding-right: ${({ theme }) => theme.spacing(2)};
`;
-export const ActionMenuBar = () => {
- const contextStoreNumberOfSelectedRecords = useRecoilValue(
- contextStoreNumberOfSelectedRecordsState,
+export const RecordIndexActionMenuBar = () => {
+ const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
+ contextStoreNumberOfSelectedRecordsComponentState,
);
const actionMenuId = useAvailableComponentInstanceIdOrThrow(
@@ -44,7 +43,7 @@ export const ActionMenuBar = () => {
>
{contextStoreNumberOfSelectedRecords} selected:
{actionMenuEntries.map((entry, index) => (
-
+
))}
);
diff --git a/packages/twenty-front/src/modules/action-menu/components/ActionMenuBarEntry.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuBarEntry.tsx
similarity index 89%
rename from packages/twenty-front/src/modules/action-menu/components/ActionMenuBarEntry.tsx
rename to packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuBarEntry.tsx
index 02802ec4a6..8be4747983 100644
--- a/packages/twenty-front/src/modules/action-menu/components/ActionMenuBarEntry.tsx
+++ b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuBarEntry.tsx
@@ -4,7 +4,7 @@ import styled from '@emotion/styled';
import { ActionMenuEntry } from '@/action-menu/types/ActionMenuEntry';
import { MenuItemAccent } from '@/ui/navigation/menu-item/types/MenuItemAccent';
-type ActionMenuBarEntryProps = {
+type RecordIndexActionMenuBarEntryProps = {
entry: ActionMenuEntry;
};
@@ -35,7 +35,9 @@ const StyledButtonLabel = styled.div`
margin-left: ${({ theme }) => theme.spacing(1)};
`;
-export const ActionMenuBarEntry = ({ entry }: ActionMenuBarEntryProps) => {
+export const RecordIndexActionMenuBarEntry = ({
+ entry,
+}: RecordIndexActionMenuBarEntryProps) => {
const theme = useTheme();
return (
`
width: auto;
`;
-export const ActionMenuDropdown = () => {
+export const RecordIndexActionMenuDropdown = () => {
const actionMenuEntries = useRecoilComponentValueV2(
actionMenuEntriesComponentSelector,
);
@@ -45,7 +45,7 @@ export const ActionMenuDropdown = () => {
const actionMenuDropdownPosition = useRecoilValue(
extractComponentState(
- actionMenuDropdownPositionComponentState,
+ recordIndexActionMenuDropdownPositionComponentState,
`action-menu-dropdown-${actionMenuId}`,
),
);
diff --git a/packages/twenty-front/src/modules/action-menu/components/ActionMenuEffect.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuEffect.tsx
similarity index 77%
rename from packages/twenty-front/src/modules/action-menu/components/ActionMenuEffect.tsx
rename to packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuEffect.tsx
index 89ba0f003e..97c785af7f 100644
--- a/packages/twenty-front/src/modules/action-menu/components/ActionMenuEffect.tsx
+++ b/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuEffect.tsx
@@ -1,15 +1,16 @@
import { useActionMenu } from '@/action-menu/hooks/useActionMenu';
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { contextStoreNumberOfSelectedRecordsState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsState';
+import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
import { useEffect } from 'react';
import { useRecoilValue } from 'recoil';
-export const ActionMenuEffect = () => {
- const contextStoreNumberOfSelectedRecords = useRecoilValue(
- contextStoreNumberOfSelectedRecordsState,
+export const RecordIndexActionMenuEffect = () => {
+ const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2(
+ contextStoreNumberOfSelectedRecordsComponentState,
);
const actionMenuId = useAvailableComponentInstanceIdOrThrow(
diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenu.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenu.tsx
new file mode 100644
index 0000000000..80bbfe4e14
--- /dev/null
+++ b/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenu.tsx
@@ -0,0 +1,31 @@
+import { RecordActionMenuEntriesSetter } from '@/action-menu/actions/record-actions/components/RecordActionMenuEntriesSetter';
+import { ActionMenuConfirmationModals } from '@/action-menu/components/ActionMenuConfirmationModals';
+import { RecordShowActionMenuBar } from '@/action-menu/components/RecordShowActionMenuBar';
+
+import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
+import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
+
+export const RecordShowActionMenu = ({
+ actionMenuId,
+}: {
+ actionMenuId: string;
+}) => {
+ const contextStoreCurrentObjectMetadataId = useRecoilComponentValueV2(
+ contextStoreCurrentObjectMetadataIdComponentState,
+ );
+
+ return (
+ <>
+ {contextStoreCurrentObjectMetadataId && (
+
+
+
+
+
+ )}
+ >
+ );
+};
diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenuBar.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenuBar.tsx
new file mode 100644
index 0000000000..c4fefcef4a
--- /dev/null
+++ b/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenuBar.tsx
@@ -0,0 +1,16 @@
+import { RecordShowActionMenuBarEntry } from '@/action-menu/components/RecordShowActionMenuBarEntry';
+import { actionMenuEntriesComponentSelector } from '@/action-menu/states/actionMenuEntriesComponentSelector';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
+
+export const RecordShowActionMenuBar = () => {
+ const actionMenuEntries = useRecoilComponentValueV2(
+ actionMenuEntriesComponentSelector,
+ );
+ return (
+ <>
+ {actionMenuEntries.map((actionMenuEntry) => (
+
+ ))}
+ >
+ );
+};
diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenuBarEntry.tsx b/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenuBarEntry.tsx
new file mode 100644
index 0000000000..debc175b7c
--- /dev/null
+++ b/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenuBarEntry.tsx
@@ -0,0 +1,53 @@
+import { useTheme } from '@emotion/react';
+import styled from '@emotion/styled';
+
+import { ActionMenuEntry } from '@/action-menu/types/ActionMenuEntry';
+import { MenuItemAccent } from '@/ui/navigation/menu-item/types/MenuItemAccent';
+
+type RecordShowActionMenuBarEntryProps = {
+ entry: ActionMenuEntry;
+};
+
+const StyledButton = styled.div<{ accent: MenuItemAccent }>`
+ border-radius: ${({ theme }) => theme.border.radius.sm};
+ color: ${(props) =>
+ props.accent === 'danger'
+ ? props.theme.color.red
+ : props.theme.font.color.secondary};
+ cursor: pointer;
+ display: flex;
+ justify-content: center;
+
+ padding: ${({ theme }) => theme.spacing(2)};
+ transition: background 0.1s ease;
+ user-select: none;
+
+ &:hover {
+ background: ${({ theme, accent }) =>
+ accent === 'danger'
+ ? theme.background.danger
+ : theme.background.tertiary};
+ }
+`;
+
+const StyledButtonLabel = styled.div`
+ font-weight: ${({ theme }) => theme.font.weight.medium};
+ margin-left: ${({ theme }) => theme.spacing(1)};
+`;
+
+// For now, this component is the same as RecordIndexActionMenuBarEntry but they
+// will probably diverge in the future
+export const RecordShowActionMenuBarEntry = ({
+ entry,
+}: RecordShowActionMenuBarEntryProps) => {
+ const theme = useTheme();
+ return (
+ entry.onClick?.()}
+ >
+ {entry.Icon && }
+ {entry.label}
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/action-menu/components/__stories__/ActionMenuBar.stories.tsx b/packages/twenty-front/src/modules/action-menu/components/__stories__/ActionMenuBar.stories.tsx
deleted file mode 100644
index b34462d8fb..0000000000
--- a/packages/twenty-front/src/modules/action-menu/components/__stories__/ActionMenuBar.stories.tsx
+++ /dev/null
@@ -1,116 +0,0 @@
-import { expect, jest } from '@storybook/jest';
-import { Meta, StoryObj } from '@storybook/react';
-import { RecoilRoot } from 'recoil';
-
-import { ActionMenuBar } from '@/action-menu/components/ActionMenuBar';
-import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { contextStoreNumberOfSelectedRecordsState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsState';
-import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
-import { isBottomBarOpenedComponentState } from '@/ui/layout/bottom-bar/states/isBottomBarOpenedComponentState';
-import { userEvent, waitFor, within } from '@storybook/test';
-import { IconCheckbox, IconTrash } from 'twenty-ui';
-
-const deleteMock = jest.fn();
-const markAsDoneMock = jest.fn();
-
-const meta: Meta = {
- title: 'Modules/ActionMenu/ActionMenuBar',
- component: ActionMenuBar,
- decorators: [
- (Story) => (
- {
- set(contextStoreTargetedRecordsRuleState, {
- mode: 'selection',
- selectedRecordIds: ['1', '2', '3'],
- });
- set(contextStoreNumberOfSelectedRecordsState, 3);
- set(
- actionMenuEntriesComponentState.atomFamily({
- instanceId: 'story-action-menu',
- }),
- new Map([
- [
- 'delete',
- {
- key: 'delete',
- label: 'Delete',
- position: 0,
- Icon: IconTrash,
- onClick: deleteMock,
- },
- ],
- [
- 'markAsDone',
- {
- key: 'markAsDone',
- label: 'Mark as done',
- position: 1,
- Icon: IconCheckbox,
- onClick: markAsDoneMock,
- },
- ],
- ]),
- );
- set(
- isBottomBarOpenedComponentState.atomFamily({
- instanceId: 'action-bar-story-action-menu',
- }),
- true,
- );
- }}
- >
-
-
-
-
- ),
- ],
- args: {
- actionMenuId: 'story-action-menu',
- },
-};
-
-export default meta;
-
-type Story = StoryObj;
-
-export const Default: Story = {
- args: {
- actionMenuId: 'story-action-menu',
- },
-};
-
-export const WithCustomSelection: Story = {
- args: {
- actionMenuId: 'story-action-menu',
- },
- play: async ({ canvasElement }) => {
- const canvas = within(canvasElement);
- const selectionText = await canvas.findByText('3 selected:');
- expect(selectionText).toBeInTheDocument();
- },
-};
-
-export const WithButtonClicks: Story = {
- args: {
- actionMenuId: 'story-action-menu',
- },
- play: async ({ canvasElement }) => {
- const canvas = within(canvasElement);
-
- const deleteButton = await canvas.findByText('Delete');
- await userEvent.click(deleteButton);
-
- const markAsDoneButton = await canvas.findByText('Mark as done');
- await userEvent.click(markAsDoneButton);
-
- await waitFor(() => {
- expect(deleteMock).toHaveBeenCalled();
- expect(markAsDoneMock).toHaveBeenCalled();
- });
- },
-};
diff --git a/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordIndexActionMenuBar.stories.tsx b/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordIndexActionMenuBar.stories.tsx
new file mode 100644
index 0000000000..f3a3eab2fd
--- /dev/null
+++ b/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordIndexActionMenuBar.stories.tsx
@@ -0,0 +1,131 @@
+import { expect, jest } from '@storybook/jest';
+import { Meta, StoryObj } from '@storybook/react';
+import { RecoilRoot } from 'recoil';
+
+import { RecordIndexActionMenuBar } from '@/action-menu/components/RecordIndexActionMenuBar';
+import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
+import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
+import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
+import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
+import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
+import { isBottomBarOpenedComponentState } from '@/ui/layout/bottom-bar/states/isBottomBarOpenedComponentState';
+import { userEvent, waitFor, within } from '@storybook/test';
+import { IconCheckbox, IconTrash } from 'twenty-ui';
+
+const deleteMock = jest.fn();
+const markAsDoneMock = jest.fn();
+
+const meta: Meta = {
+ title: 'Modules/ActionMenu/RecordIndexActionMenuBar',
+ component: RecordIndexActionMenuBar,
+ decorators: [
+ (Story) => (
+
+ {
+ set(
+ contextStoreTargetedRecordsRuleComponentState.atomFamily({
+ instanceId: 'story-action-menu',
+ }),
+ {
+ mode: 'selection',
+ selectedRecordIds: ['1', '2', '3'],
+ },
+ );
+ set(
+ contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
+ instanceId: 'story-action-menu',
+ }),
+ 3,
+ );
+ set(
+ actionMenuEntriesComponentState.atomFamily({
+ instanceId: 'story-action-menu',
+ }),
+ new Map([
+ [
+ 'delete',
+ {
+ key: 'delete',
+ label: 'Delete',
+ position: 0,
+ Icon: IconTrash,
+ onClick: deleteMock,
+ },
+ ],
+ [
+ 'markAsDone',
+ {
+ key: 'markAsDone',
+ label: 'Mark as done',
+ position: 1,
+ Icon: IconCheckbox,
+ onClick: markAsDoneMock,
+ },
+ ],
+ ]),
+ );
+ set(
+ isBottomBarOpenedComponentState.atomFamily({
+ instanceId: 'action-bar-story-action-menu',
+ }),
+ true,
+ );
+ }}
+ >
+
+
+
+
+
+ ),
+ ],
+ args: {
+ actionMenuId: 'story-action-menu',
+ },
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ actionMenuId: 'story-action-menu',
+ },
+};
+
+export const WithCustomSelection: Story = {
+ args: {
+ actionMenuId: 'story-action-menu',
+ },
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const selectionText = await canvas.findByText('3 selected:');
+ expect(selectionText).toBeInTheDocument();
+ },
+};
+
+export const WithButtonClicks: Story = {
+ args: {
+ actionMenuId: 'story-action-menu',
+ },
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+
+ const deleteButton = await canvas.findByText('Delete');
+ await userEvent.click(deleteButton);
+
+ const markAsDoneButton = await canvas.findByText('Mark as done');
+ await userEvent.click(markAsDoneButton);
+
+ await waitFor(() => {
+ expect(deleteMock).toHaveBeenCalled();
+ expect(markAsDoneMock).toHaveBeenCalled();
+ });
+ },
+};
diff --git a/packages/twenty-front/src/modules/action-menu/components/__stories__/ActionMenuBarEntry.stories.tsx b/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordIndexActionMenuBarEntry.stories.tsx
similarity index 78%
rename from packages/twenty-front/src/modules/action-menu/components/__stories__/ActionMenuBarEntry.stories.tsx
rename to packages/twenty-front/src/modules/action-menu/components/__stories__/RecordIndexActionMenuBarEntry.stories.tsx
index a9c7b26b84..96267fed3e 100644
--- a/packages/twenty-front/src/modules/action-menu/components/__stories__/ActionMenuBarEntry.stories.tsx
+++ b/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordIndexActionMenuBarEntry.stories.tsx
@@ -1,19 +1,19 @@
+import { RecordIndexActionMenuBarEntry } from '@/action-menu/components/RecordIndexActionMenuBarEntry';
import { expect, jest } from '@storybook/jest';
import { Meta, StoryObj } from '@storybook/react';
import { userEvent, within } from '@storybook/testing-library';
import { ComponentDecorator, IconCheckbox, IconTrash } from 'twenty-ui';
-import { ActionMenuBarEntry } from '../ActionMenuBarEntry';
-const meta: Meta = {
- title: 'Modules/ActionMenu/ActionMenuBarEntry',
- component: ActionMenuBarEntry,
+const meta: Meta = {
+ title: 'Modules/ActionMenu/RecordIndexActionMenuBarEntry',
+ component: RecordIndexActionMenuBarEntry,
decorators: [ComponentDecorator],
};
export default meta;
-type Story = StoryObj;
+type Story = StoryObj;
const deleteMock = jest.fn();
const markAsDoneMock = jest.fn();
diff --git a/packages/twenty-front/src/modules/action-menu/components/__stories__/ActionMenuDropdown.stories.tsx b/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordIndexActionMenuDropdown.stories.tsx
similarity index 85%
rename from packages/twenty-front/src/modules/action-menu/components/__stories__/ActionMenuDropdown.stories.tsx
rename to packages/twenty-front/src/modules/action-menu/components/__stories__/RecordIndexActionMenuDropdown.stories.tsx
index 53a0714cee..bb9260755a 100644
--- a/packages/twenty-front/src/modules/action-menu/components/__stories__/ActionMenuDropdown.stories.tsx
+++ b/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordIndexActionMenuDropdown.stories.tsx
@@ -3,10 +3,10 @@ import { Meta, StoryObj } from '@storybook/react';
import { userEvent, within } from '@storybook/testing-library';
import { RecoilRoot } from 'recoil';
-import { ActionMenuDropdown } from '@/action-menu/components/ActionMenuDropdown';
-import { actionMenuDropdownPositionComponentState } from '@/action-menu/states/actionMenuDropdownPositionComponentState';
+import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown';
import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
+import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
import { IconCheckbox, IconHeart, IconTrash } from 'twenty-ui';
@@ -15,16 +15,16 @@ const deleteMock = jest.fn();
const markAsDoneMock = jest.fn();
const addToFavoritesMock = jest.fn();
-const meta: Meta = {
- title: 'Modules/ActionMenu/ActionMenuDropdown',
- component: ActionMenuDropdown,
+const meta: Meta = {
+ title: 'Modules/ActionMenu/RecordIndexActionMenuDropdown',
+ component: RecordIndexActionMenuDropdown,
decorators: [
(Story) => (
{
set(
extractComponentState(
- actionMenuDropdownPositionComponentState,
+ recordIndexActionMenuDropdownPositionComponentState,
'action-menu-dropdown-story',
),
{ x: 10, y: 10 },
@@ -87,7 +87,7 @@ const meta: Meta = {
export default meta;
-type Story = StoryObj;
+type Story = StoryObj;
export const Default: Story = {
args: {
diff --git a/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordShowActionMenuBar.stories.tsx b/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordShowActionMenuBar.stories.tsx
new file mode 100644
index 0000000000..22f1bab670
--- /dev/null
+++ b/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordShowActionMenuBar.stories.tsx
@@ -0,0 +1,131 @@
+import { expect, jest } from '@storybook/jest';
+import { Meta, StoryObj } from '@storybook/react';
+import { RecoilRoot } from 'recoil';
+
+import { RecordShowActionMenuBar } from '@/action-menu/components/RecordShowActionMenuBar';
+import { actionMenuEntriesComponentState } from '@/action-menu/states/actionMenuEntriesComponentState';
+import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
+import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
+import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
+import { MenuItemAccent } from '@/ui/navigation/menu-item/types/MenuItemAccent';
+import { userEvent, waitFor, within } from '@storybook/test';
+import {
+ ComponentDecorator,
+ IconFileExport,
+ IconHeart,
+ IconTrash,
+} from 'twenty-ui';
+
+const deleteMock = jest.fn();
+const addToFavoritesMock = jest.fn();
+const exportMock = jest.fn();
+
+const meta: Meta = {
+ title: 'Modules/ActionMenu/RecordShowActionMenuBar',
+ component: RecordShowActionMenuBar,
+ decorators: [
+ (Story) => (
+ {
+ set(
+ contextStoreTargetedRecordsRuleComponentState.atomFamily({
+ instanceId: 'story-action-menu',
+ }),
+ {
+ mode: 'selection',
+ selectedRecordIds: ['1'],
+ },
+ );
+ set(
+ contextStoreNumberOfSelectedRecordsComponentState.atomFamily({
+ instanceId: 'story-action-menu',
+ }),
+ 1,
+ );
+ set(
+ actionMenuEntriesComponentState.atomFamily({
+ instanceId: 'story-action-menu',
+ }),
+ new Map([
+ [
+ 'addToFavorites',
+ {
+ key: 'addToFavorites',
+ label: 'Add to favorites',
+ position: 0,
+ Icon: IconHeart,
+ onClick: addToFavoritesMock,
+ },
+ ],
+ [
+ 'export',
+ {
+ key: 'export',
+ label: 'Export',
+ position: 1,
+ Icon: IconFileExport,
+ onClick: exportMock,
+ },
+ ],
+ [
+ 'delete',
+ {
+ key: 'delete',
+ label: 'Delete',
+ position: 2,
+ Icon: IconTrash,
+ onClick: deleteMock,
+ accent: 'danger' as MenuItemAccent,
+ },
+ ],
+ ]),
+ );
+ }}
+ >
+
+
+
+
+ ),
+ ComponentDecorator,
+ ],
+ args: {
+ actionMenuId: 'story-action-menu',
+ },
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ args: {
+ actionMenuId: 'story-action-menu',
+ },
+};
+
+export const WithButtonClicks: Story = {
+ args: {
+ actionMenuId: 'story-action-menu',
+ },
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+
+ const deleteButton = await canvas.findByText('Delete');
+ await userEvent.click(deleteButton);
+
+ const addToFavoritesButton = await canvas.findByText('Add to favorites');
+ await userEvent.click(addToFavoritesButton);
+
+ const exportButton = await canvas.findByText('Export');
+ await userEvent.click(exportButton);
+
+ await waitFor(() => {
+ expect(deleteMock).toHaveBeenCalled();
+ expect(addToFavoritesMock).toHaveBeenCalled();
+ expect(exportMock).toHaveBeenCalled();
+ });
+ },
+};
diff --git a/packages/twenty-front/src/modules/action-menu/states/actionMenuDropdownPositionComponentState.ts b/packages/twenty-front/src/modules/action-menu/states/recordIndexActionMenuDropdownPositionComponentState.ts
similarity index 67%
rename from packages/twenty-front/src/modules/action-menu/states/actionMenuDropdownPositionComponentState.ts
rename to packages/twenty-front/src/modules/action-menu/states/recordIndexActionMenuDropdownPositionComponentState.ts
index f2f8f06b13..4be2f83c5b 100644
--- a/packages/twenty-front/src/modules/action-menu/states/actionMenuDropdownPositionComponentState.ts
+++ b/packages/twenty-front/src/modules/action-menu/states/recordIndexActionMenuDropdownPositionComponentState.ts
@@ -1,9 +1,9 @@
import { PositionType } from '@/action-menu/types/PositionType';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
-export const actionMenuDropdownPositionComponentState =
+export const recordIndexActionMenuDropdownPositionComponentState =
createComponentState({
- key: 'actionMenuDropdownPositionComponentState',
+ key: 'recordIndexActionMenuDropdownPositionComponentState',
defaultValue: {
x: null,
y: null,
diff --git a/packages/twenty-front/src/modules/action-menu/types/ActionMenuType.ts b/packages/twenty-front/src/modules/action-menu/types/ActionMenuType.ts
new file mode 100644
index 0000000000..a0e7d0e4b5
--- /dev/null
+++ b/packages/twenty-front/src/modules/action-menu/types/ActionMenuType.ts
@@ -0,0 +1 @@
+export type ActionMenuType = 'recordIndex' | 'recordShow';
diff --git a/packages/twenty-front/src/modules/context-store/components/SetMainContextStoreComponentInstanceIdEffect.tsx b/packages/twenty-front/src/modules/context-store/components/SetMainContextStoreComponentInstanceIdEffect.tsx
new file mode 100644
index 0000000000..b1acc25d84
--- /dev/null
+++ b/packages/twenty-front/src/modules/context-store/components/SetMainContextStoreComponentInstanceIdEffect.tsx
@@ -0,0 +1,22 @@
+import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
+import { mainContextStoreComponentInstanceIdState } from '@/context-store/states/mainContextStoreComponentInstanceId';
+import { useContext, useEffect } from 'react';
+import { useSetRecoilState } from 'recoil';
+
+export const SetMainContextStoreComponentInstanceIdEffect = () => {
+ const setMainContextStoreComponentInstanceId = useSetRecoilState(
+ mainContextStoreComponentInstanceIdState,
+ );
+
+ const context = useContext(ContextStoreComponentInstanceContext);
+
+ useEffect(() => {
+ setMainContextStoreComponentInstanceId(context?.instanceId ?? null);
+
+ return () => {
+ setMainContextStoreComponentInstanceId(null);
+ };
+ }, [context, setMainContextStoreComponentInstanceId]);
+
+ return null;
+};
diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdComponentState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdComponentState.ts
new file mode 100644
index 0000000000..9898e6c6f5
--- /dev/null
+++ b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdComponentState.ts
@@ -0,0 +1,9 @@
+import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
+import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
+
+export const contextStoreCurrentObjectMetadataIdComponentState =
+ createComponentStateV2({
+ key: 'contextStoreCurrentObjectMetadataIdComponentState',
+ defaultValue: null,
+ componentInstanceContext: ContextStoreComponentInstanceContext,
+ });
diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdState.ts
deleted file mode 100644
index 3227e53807..0000000000
--- a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentObjectMetadataIdState.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { createState } from 'twenty-ui';
-
-export const contextStoreCurrentObjectMetadataIdState = createState<
- string | null
->({
- key: 'contextStoreCurrentObjectMetadataIdState',
- defaultValue: null,
-});
diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdComponentState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdComponentState.ts
new file mode 100644
index 0000000000..10136c28d0
--- /dev/null
+++ b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdComponentState.ts
@@ -0,0 +1,10 @@
+import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
+import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
+
+export const contextStoreCurrentViewIdComponentState = createComponentStateV2<
+ string | null
+>({
+ key: 'contextStoreCurrentViewIdComponentState',
+ defaultValue: null,
+ componentInstanceContext: ContextStoreComponentInstanceContext,
+});
diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdState.ts
deleted file mode 100644
index 41af1cc135..0000000000
--- a/packages/twenty-front/src/modules/context-store/states/contextStoreCurrentViewIdState.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { createState } from 'twenty-ui';
-
-export const contextStoreCurrentViewIdState = createState({
- key: 'contextStoreCurrentViewIdState',
- defaultValue: null,
-});
diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreNumberOfSelectedRecordsComponentState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreNumberOfSelectedRecordsComponentState.ts
new file mode 100644
index 0000000000..54a6cb1adb
--- /dev/null
+++ b/packages/twenty-front/src/modules/context-store/states/contextStoreNumberOfSelectedRecordsComponentState.ts
@@ -0,0 +1,9 @@
+import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
+import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
+
+export const contextStoreNumberOfSelectedRecordsComponentState =
+ createComponentStateV2({
+ key: 'contextStoreNumberOfSelectedRecordsComponentState',
+ defaultValue: 0,
+ componentInstanceContext: ContextStoreComponentInstanceContext,
+ });
diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreNumberOfSelectedRecordsState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreNumberOfSelectedRecordsState.ts
deleted file mode 100644
index fb1b3544d3..0000000000
--- a/packages/twenty-front/src/modules/context-store/states/contextStoreNumberOfSelectedRecordsState.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { createState } from 'twenty-ui';
-
-export const contextStoreNumberOfSelectedRecordsState = createState({
- key: 'contextStoreNumberOfSelectedRecordsState',
- defaultValue: 0,
-});
diff --git a/packages/twenty-front/src/modules/context-store/states/contextStoreTargetedRecordsRuleState.ts b/packages/twenty-front/src/modules/context-store/states/contextStoreTargetedRecordsRuleComponentState.ts
similarity index 53%
rename from packages/twenty-front/src/modules/context-store/states/contextStoreTargetedRecordsRuleState.ts
rename to packages/twenty-front/src/modules/context-store/states/contextStoreTargetedRecordsRuleComponentState.ts
index 7f71377c31..1540c05f3f 100644
--- a/packages/twenty-front/src/modules/context-store/states/contextStoreTargetedRecordsRuleState.ts
+++ b/packages/twenty-front/src/modules/context-store/states/contextStoreTargetedRecordsRuleComponentState.ts
@@ -1,5 +1,6 @@
+import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
-import { createState } from 'twenty-ui';
+import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
type ContextStoreTargetedRecordsRuleSelectionMode = {
mode: 'selection';
@@ -16,11 +17,12 @@ export type ContextStoreTargetedRecordsRule =
| ContextStoreTargetedRecordsRuleSelectionMode
| ContextStoreTargetedRecordsRuleExclusionMode;
-export const contextStoreTargetedRecordsRuleState =
- createState({
- key: 'contextStoreTargetedRecordsRuleState',
+export const contextStoreTargetedRecordsRuleComponentState =
+ createComponentStateV2({
+ key: 'contextStoreTargetedRecordsRuleComponentState',
defaultValue: {
mode: 'selection',
selectedRecordIds: [],
},
+ componentInstanceContext: ContextStoreComponentInstanceContext,
});
diff --git a/packages/twenty-front/src/modules/context-store/states/contexts/ContextStoreComponentInstanceContext.tsx b/packages/twenty-front/src/modules/context-store/states/contexts/ContextStoreComponentInstanceContext.tsx
new file mode 100644
index 0000000000..f82a5d53b1
--- /dev/null
+++ b/packages/twenty-front/src/modules/context-store/states/contexts/ContextStoreComponentInstanceContext.tsx
@@ -0,0 +1,4 @@
+import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext';
+
+export const ContextStoreComponentInstanceContext =
+ createComponentInstanceContext();
diff --git a/packages/twenty-front/src/modules/context-store/states/mainContextStoreComponentInstanceId.ts b/packages/twenty-front/src/modules/context-store/states/mainContextStoreComponentInstanceId.ts
new file mode 100644
index 0000000000..2e73436727
--- /dev/null
+++ b/packages/twenty-front/src/modules/context-store/states/mainContextStoreComponentInstanceId.ts
@@ -0,0 +1,8 @@
+import { createState } from 'twenty-ui';
+
+export const mainContextStoreComponentInstanceIdState = createState<
+ string | null
+>({
+ key: 'mainContextStoreComponentInstanceIdState',
+ defaultValue: null,
+});
diff --git a/packages/twenty-front/src/modules/context-store/utils/__tests__/computeContextStoreFilters.test.ts b/packages/twenty-front/src/modules/context-store/utils/__tests__/computeContextStoreFilters.test.ts
index 689d7287d4..1c65848ede 100644
--- a/packages/twenty-front/src/modules/context-store/utils/__tests__/computeContextStoreFilters.test.ts
+++ b/packages/twenty-front/src/modules/context-store/utils/__tests__/computeContextStoreFilters.test.ts
@@ -1,4 +1,4 @@
-import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
+import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
import { ViewFilterOperand } from '@/views/types/ViewFilterOperand';
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
diff --git a/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts b/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts
index 26727fbc26..edc4e17336 100644
--- a/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts
+++ b/packages/twenty-front/src/modules/context-store/utils/computeContextStoreFilters.ts
@@ -1,4 +1,4 @@
-import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
+import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter';
import { turnFiltersIntoQueryFilter } from '@/object-record/record-filter/utils/turnFiltersIntoQueryFilter';
diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx
index 2fdffd2598..8e3c002055 100644
--- a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx
@@ -1,5 +1,5 @@
import { useActionMenu } from '@/action-menu/hooks/useActionMenu';
-import { actionMenuDropdownPositionComponentState } from '@/action-menu/states/actionMenuDropdownPositionComponentState';
+import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
import { useRecordBoardStates } from '@/object-record/record-board/hooks/internal/useRecordBoardStates';
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
@@ -188,7 +188,7 @@ export const RecordBoardCard = ({
const setActionMenuDropdownPosition = useSetRecoilState(
extractComponentState(
- actionMenuDropdownPositionComponentState,
+ recordIndexActionMenuDropdownPositionComponentState,
`action-menu-dropdown-${recordBoardId}`,
),
);
diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardDataLoaderEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardDataLoaderEffect.tsx
index 9e8358f9e0..e034730304 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardDataLoaderEffect.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexBoardDataLoaderEffect.tsx
@@ -2,7 +2,7 @@ import { useCallback, useEffect } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { useRecoilValue, useSetRecoilState } from 'recoil';
-import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
+import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug';
import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoard';
@@ -11,6 +11,7 @@ import { recordIndexIsCompactModeActiveState } from '@/object-record/record-inde
import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState';
import { computeRecordBoardColumnDefinitionsFromObjectMetadata } from '@/object-record/utils/computeRecordBoardColumnDefinitionsFromObjectMetadata';
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
+import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined';
@@ -120,8 +121,8 @@ export const RecordIndexBoardDataLoaderEffect = ({
const selectedRecordIds = useRecoilValue(selectedRecordIdsSelector());
- const setContextStoreTargetedRecords = useSetRecoilState(
- contextStoreTargetedRecordsRuleState,
+ const setContextStoreTargetedRecords = useSetRecoilComponentStateV2(
+ contextStoreTargetedRecordsRuleComponentState,
);
useEffect(() => {
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 a28d2f26ac..1bd29294bb 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
@@ -22,8 +22,9 @@ import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
-import { ActionMenu } from '@/action-menu/components/ActionMenu';
-import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
+import { RecordIndexActionMenu } from '@/action-menu/components/RecordIndexActionMenu';
+import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
+import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { ViewBar } from '@/views/components/ViewBar';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
import { ViewField } from '@/views/types/ViewField';
@@ -102,8 +103,8 @@ export const RecordIndexContainer = () => {
[columnDefinitions, setTableColumns],
);
- const setContextStoreTargetedRecordsRule = useSetRecoilState(
- contextStoreTargetedRecordsRuleState,
+ const setContextStoreTargetedRecordsRule = useSetRecoilComponentStateV2(
+ contextStoreTargetedRecordsRuleComponentState,
);
return (
@@ -186,7 +187,7 @@ export const RecordIndexContainer = () => {
/>
)}
-
+
diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect.tsx
index 2a538c542a..602ed22723 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect.tsx
@@ -1,22 +1,23 @@
-import { contextStoreNumberOfSelectedRecordsState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsState';
-import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
+import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
+import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext';
import { useFindManyParams } from '@/object-record/record-index/hooks/useLoadRecordIndexTable';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
+import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { useContext, useEffect } from 'react';
-import { useRecoilValue, useSetRecoilState } from 'recoil';
export const RecordIndexContainerContextStoreNumberOfSelectedRecordsEffect =
() => {
- const setContextStoreNumberOfSelectedRecords = useSetRecoilState(
- contextStoreNumberOfSelectedRecordsState,
+ const setContextStoreNumberOfSelectedRecords = useSetRecoilComponentStateV2(
+ contextStoreNumberOfSelectedRecordsComponentState,
);
- const contextStoreTargetedRecordsRule = useRecoilValue(
- contextStoreTargetedRecordsRuleState,
+ const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
+ contextStoreTargetedRecordsRuleComponentState,
);
const { objectNamePlural } = useContext(RecordIndexRootPropsContext);
diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerContextStoreObjectMetadataEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerContextStoreObjectMetadataEffect.tsx
index c94611836a..03a02ee36f 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerContextStoreObjectMetadataEffect.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerContextStoreObjectMetadataEffect.tsx
@@ -1,13 +1,13 @@
-import { contextStoreCurrentObjectMetadataIdState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdState';
+import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext';
+import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { useContext, useEffect } from 'react';
-import { useSetRecoilState } from 'recoil';
export const RecordIndexContainerContextStoreObjectMetadataEffect = () => {
- const setContextStoreCurrentObjectMetadataItem = useSetRecoilState(
- contextStoreCurrentObjectMetadataIdState,
+ const setContextStoreCurrentObjectMetadataItem = useSetRecoilComponentStateV2(
+ contextStoreCurrentObjectMetadataIdComponentState,
);
const { objectNamePlural } = useContext(RecordIndexRootPropsContext);
diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx
index ba541ca1a6..a30c797f22 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexTableContainerEffect.tsx
@@ -1,13 +1,14 @@
import { useContext, useEffect } from 'react';
-import { useRecoilValue, useSetRecoilState } from 'recoil';
+import { useRecoilValue } from 'recoil';
-import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
+import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { RecordIndexRootPropsContext } from '@/object-record/record-index/contexts/RecordIndexRootPropsContext';
import { useHandleToggleColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleColumnFilter';
import { useHandleToggleColumnSort } from '@/object-record/record-index/hooks/useHandleToggleColumnSort';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
+import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { useSetRecordCountInCurrentView } from '@/views/hooks/useSetRecordCountInCurrentView';
export const RecordIndexTableContainerEffect = () => {
@@ -73,8 +74,8 @@ export const RecordIndexTableContainerEffect = () => {
);
}, [setRecordCountInCurrentView, setOnEntityCountChange]);
- const setContextStoreTargetedRecords = useSetRecoilState(
- contextStoreTargetedRecordsRuleState,
+ const setContextStoreTargetedRecords = useSetRecoilComponentStateV2(
+ contextStoreTargetedRecordsRuleComponentState,
);
const hasUserSelectedAllRows = useRecoilValue(hasUserSelectedAllRowsState);
const selectedRowIds = useRecoilValue(selectedRowIdsSelector());
diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useRecordData.test.tsx b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useRecordData.test.tsx
index 9747c2c4e9..d7dc9df12c 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useRecordData.test.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/__tests__/useRecordData.test.tsx
@@ -130,6 +130,7 @@ const mocks: MockedResponse[] = [
const WrapperWithResponse = getJestMetadataAndApolloMocksAndContextStoreWrapper(
{
apolloMocks: mocks,
+ componentInstanceId: 'recordIndexId',
contextStoreTargetedRecordsRule: {
mode: 'selection',
selectedRecordIds: [],
@@ -155,6 +156,7 @@ const graphqlEmptyResponse = [
const WrapperWithEmptyResponse =
getJestMetadataAndApolloMocksAndContextStoreWrapper({
apolloMocks: graphqlEmptyResponse,
+ componentInstanceId: 'recordIndexId',
contextStoreTargetedRecordsRule: {
mode: 'selection',
selectedRecordIds: [],
@@ -207,7 +209,6 @@ describe('useRecordData', () => {
objectMetadataItem,
callback,
pageSize: 30,
-
delayMs: 0,
}),
{ wrapper: WrapperWithResponse },
diff --git a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordData.ts b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordData.ts
index 7c65a53105..fe08785490 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordData.ts
+++ b/packages/twenty-front/src/modules/object-record/record-index/options/hooks/useRecordData.ts
@@ -7,7 +7,7 @@ import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefin
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
import { isDefined } from '~/utils/isDefined';
-import { contextStoreTargetedRecordsRuleState } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
+import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useLazyFindManyRecords } from '@/object-record/hooks/useLazyFindManyRecords';
@@ -15,6 +15,7 @@ import { useRecordBoardStates } from '@/object-record/record-board/hooks/interna
import { useFindManyParams } from '@/object-record/record-index/hooks/useLoadRecordIndexTable';
import { EXPORT_TABLE_DATA_DEFAULT_PAGE_SIZE } from '@/object-record/record-index/options/constants/ExportTableDataDefaultPageSize';
import { useRecordIndexOptionsForBoard } from '@/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard';
+import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
import { ViewType } from '@/views/types/ViewType';
export const sleep = (ms: number) =>
@@ -75,8 +76,8 @@ export const useRecordData = ({
);
const columns = useRecoilValue(visibleTableColumnsSelector());
- const contextStoreTargetedRecordsRule = useRecoilValue(
- contextStoreTargetedRecordsRuleState,
+ const contextStoreTargetedRecordsRule = useRecoilComponentValueV2(
+ contextStoreTargetedRecordsRuleComponentState,
);
const queryFilter = computeContextStoreFilters(
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 01e5f42d65..075b83cd35 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
@@ -1,7 +1,10 @@
-import { InformationBannerDeletedRecord } from '@/information-banner/components/deleted-record/InformationBannerDeletedRecord';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { ShowPageContainer } from '@/ui/layout/page/components/ShowPageContainer';
+import { SetMainContextStoreComponentInstanceIdEffect } from '@/context-store/components/SetMainContextStoreComponentInstanceIdEffect';
+import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
+import { InformationBannerDeletedRecord } from '@/information-banner/components/deleted-record/InformationBannerDeletedRecord';
+import { RecordShowContainerContextStoreEffect } from '@/object-record/record-show/components/RecordShowContainerContextStoreEffect';
import { useRecordShowContainerData } from '@/object-record/record-show/hooks/useRecordShowContainerData';
import { useRecordShowContainerTabs } from '@/object-record/record-show/hooks/useRecordShowContainerTabs';
import { ShowPageSubContainer } from '@/ui/layout/show-page/components/ShowPageSubContainer';
@@ -38,7 +41,16 @@ export const RecordShowContainer = ({
);
return (
- <>
+
+
+ {!isInRightDrawer && }
{recordFromStore && recordFromStore.deletedAt && (
- >
+
);
};
diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerContextStoreEffect.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerContextStoreEffect.tsx
new file mode 100644
index 0000000000..fe1c65796b
--- /dev/null
+++ b/packages/twenty-front/src/modules/object-record/record-show/components/RecordShowContainerContextStoreEffect.tsx
@@ -0,0 +1,56 @@
+import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
+import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
+import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
+import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
+import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
+import { useEffect } from 'react';
+
+export const RecordShowContainerContextStoreEffect = ({
+ recordId,
+ objectNameSingular,
+}: {
+ recordId: string;
+ objectNameSingular: string;
+}) => {
+ const setContextStoreTargetedRecordsRule = useSetRecoilComponentStateV2(
+ contextStoreTargetedRecordsRuleComponentState,
+ );
+
+ const setContextStoreCurrentObjectMetadataId = useSetRecoilComponentStateV2(
+ contextStoreCurrentObjectMetadataIdComponentState,
+ );
+
+ const { objectMetadataItem } = useObjectMetadataItem({
+ objectNameSingular: objectNameSingular,
+ });
+
+ const setContextStoreNumberOfSelectedRecords = useSetRecoilComponentStateV2(
+ contextStoreNumberOfSelectedRecordsComponentState,
+ );
+
+ useEffect(() => {
+ setContextStoreTargetedRecordsRule({
+ mode: 'selection',
+ selectedRecordIds: [recordId],
+ });
+ setContextStoreCurrentObjectMetadataId(objectMetadataItem?.id);
+ setContextStoreNumberOfSelectedRecords(1);
+
+ return () => {
+ setContextStoreTargetedRecordsRule({
+ mode: 'selection',
+ selectedRecordIds: [],
+ });
+ setContextStoreCurrentObjectMetadataId(null);
+ setContextStoreNumberOfSelectedRecords(0);
+ };
+ }, [
+ recordId,
+ setContextStoreTargetedRecordsRule,
+ setContextStoreCurrentObjectMetadataId,
+ objectMetadataItem?.id,
+ setContextStoreNumberOfSelectedRecords,
+ ]);
+
+ return null;
+};
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useTriggerActionMenuDropdown.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useTriggerActionMenuDropdown.ts
index 0870b7bb4d..a651c22cf4 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useTriggerActionMenuDropdown.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useTriggerActionMenuDropdown.ts
@@ -1,6 +1,6 @@
import { useRecoilCallback } from 'recoil';
-import { actionMenuDropdownPositionComponentState } from '@/action-menu/states/actionMenuDropdownPositionComponentState';
+import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
import { isBottomBarOpenedComponentState } from '@/ui/layout/bottom-bar/states/isBottomBarOpenedComponentState';
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
@@ -23,7 +23,7 @@ export const useTriggerActionMenuDropdown = ({
set(
extractComponentState(
- actionMenuDropdownPositionComponentState,
+ recordIndexActionMenuDropdownPositionComponentState,
`action-menu-dropdown-${recordTableId}`,
),
{
diff --git a/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx b/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx
index 7b75faec18..3165ebce78 100644
--- a/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/modal/components/ConfirmationModal.tsx
@@ -7,7 +7,7 @@ import { useDebouncedCallback } from 'use-debounce';
import { Button, ButtonAccent } from '@/ui/input/button/components/Button';
import { TextInput } from '@/ui/input/components/TextInput';
-import { Modal } from '@/ui/layout/modal/components/Modal';
+import { Modal, ModalVariants } from '@/ui/layout/modal/components/Modal';
import {
Section,
SectionAlignment,
@@ -26,6 +26,7 @@ export type ConfirmationModalProps = {
confirmationValue?: string;
confirmButtonAccent?: ButtonAccent;
AdditionalButtons?: React.ReactNode;
+ modalVariant?: ModalVariants;
};
const StyledConfirmationModal = styled(Modal)`
@@ -71,6 +72,7 @@ export const ConfirmationModal = ({
confirmationPlaceholder,
confirmButtonAccent = 'danger',
AdditionalButtons,
+ modalVariant = 'primary',
}: ConfirmationModalProps) => {
const [inputConfirmationValue, setInputConfirmationValue] =
useState('');
@@ -113,6 +115,7 @@ export const ConfirmationModal = ({
onEnter={handleEnter}
isClosable={true}
padding="large"
+ modalVariant={modalVariant}
>
diff --git a/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx b/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx
index fe7983082e..5916849250 100644
--- a/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/modal/components/Modal.tsx
@@ -94,7 +94,9 @@ const StyledBackDrop = styled(motion.div)<{
background: ${({ theme, modalVariant }) =>
modalVariant === 'primary'
? theme.background.overlayPrimary
- : theme.background.overlaySecondary};
+ : modalVariant === 'secondary'
+ ? theme.background.overlaySecondary
+ : theme.background.overlayTertiary};
display: flex;
height: 100%;
justify-content: center;
@@ -132,7 +134,7 @@ const ModalFooter = ({ children, className }: ModalFooterProps) => (
export type ModalSize = 'small' | 'medium' | 'large';
export type ModalPadding = 'none' | 'small' | 'medium' | 'large';
-export type ModalVariants = 'primary' | 'secondary';
+export type ModalVariants = 'primary' | 'secondary' | 'tertiary';
export type ModalProps = React.PropsWithChildren & {
size?: ModalSize;
diff --git a/packages/twenty-front/src/modules/ui/layout/page/components/RightDrawerContainer.tsx b/packages/twenty-front/src/modules/ui/layout/page/components/RightDrawerContainer.tsx
deleted file mode 100644
index 5d4c0efb7e..0000000000
--- a/packages/twenty-front/src/modules/ui/layout/page/components/RightDrawerContainer.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import { ReactNode } from 'react';
-import styled from '@emotion/styled';
-import { MOBILE_VIEWPORT } from 'twenty-ui';
-
-import { RightDrawer } from '@/ui/layout/right-drawer/components/RightDrawer';
-
-import { PagePanel } from './PagePanel';
-
-type RightDrawerContainerProps = {
- children: ReactNode;
-};
-
-const StyledMainContainer = styled.div`
- background: ${({ theme }) => theme.background.noisy};
- box-sizing: border-box;
- display: flex;
- flex: 1 1 auto;
- flex-direction: row;
- gap: ${({ theme }) => theme.spacing(2)};
- min-height: 0;
- padding-bottom: ${({ theme }) => theme.spacing(3)};
- padding-right: ${({ theme }) => theme.spacing(3)};
- padding-left: 0;
- width: 100%;
-
- @media (max-width: ${MOBILE_VIEWPORT}px) {
- padding-left: ${({ theme }) => theme.spacing(3)};
- padding-bottom: 0;
- }
-`;
-
-type LeftContainerProps = {
- isRightDrawerOpen?: boolean;
-};
-
-const StyledLeftContainer = styled.div`
- display: flex;
- flex-direction: column;
- position: relative;
- width: 100%;
-`;
-
-export const RightDrawerContainer = ({
- children,
-}: RightDrawerContainerProps) => (
-
-
- {children}
-
-
-
-);
diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageSubContainer.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageSubContainer.tsx
index 29a53033ed..1c6777148f 100644
--- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageSubContainer.tsx
+++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageSubContainer.tsx
@@ -1,3 +1,4 @@
+import { RecordShowActionMenu } from '@/action-menu/components/RecordShowActionMenu';
import { Calendar } from '@/activities/calendar/components/Calendar';
import { EmailThreads } from '@/activities/emails/components/EmailThreads';
import { Attachments } from '@/activities/files/components/Attachments';
@@ -6,13 +7,11 @@ import { ObjectTasks } from '@/activities/tasks/components/ObjectTasks';
import { TimelineActivities } from '@/activities/timeline-activities/components/TimelineActivities';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
-import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
import { isNewViewableRecordLoadingState } from '@/object-record/record-right-drawer/states/isNewViewableRecordLoading';
import { FieldsCard } from '@/object-record/record-show/components/FieldsCard';
import { SummaryCard } from '@/object-record/record-show/components/SummaryCard';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { ObjectRecord } from '@/object-record/types/ObjectRecord';
-import { Button } from '@/ui/input/button/components/Button';
import { ShowPageActivityContainer } from '@/ui/layout/show-page/components/ShowPageActivityContainer';
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
import { SingleTabProps, TabList } from '@/ui/layout/tab/components/TabList';
@@ -25,9 +24,7 @@ import { WorkflowVersionVisualizerEffect } from '@/workflow/components/WorkflowV
import { WorkflowVisualizer } from '@/workflow/components/WorkflowVisualizer';
import { WorkflowVisualizerEffect } from '@/workflow/components/WorkflowVisualizerEffect';
import styled from '@emotion/styled';
-import { useState } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil';
-import { IconTrash } from 'twenty-ui';
const StyledShowPageRightContainer = styled.div<{ isMobile: boolean }>`
display: flex;
@@ -198,18 +195,6 @@ export const ShowPageSubContainer = ({
}
};
- const [isDeleting, setIsDeleting] = useState(false);
-
- const { deleteOneRecord } = useDeleteOneRecord({
- objectNameSingular: targetableObject.targetObjectNameSingular,
- });
-
- const handleDelete = async () => {
- setIsDeleting(true);
- await deleteOneRecord(targetableObject.id);
- setIsDeleting(false);
- };
-
const [recordFromStore] = useRecoilState(
recordStoreFamilyState(targetableObject.id),
);
@@ -236,12 +221,7 @@ export const ShowPageSubContainer = ({
{isInRightDrawer && recordFromStore && !recordFromStore.deletedAt && (
-
+
)}
diff --git a/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx b/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx
index f306f29bd7..ced095e33a 100644
--- a/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx
+++ b/packages/twenty-front/src/modules/views/components/QueryParamsViewIdEffect.tsx
@@ -1,14 +1,14 @@
-import { contextStoreCurrentViewIdState } from '@/context-store/states/contextStoreCurrentViewIdState';
+import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useLastVisitedObjectMetadataItem } from '@/navigation/hooks/useLastVisitedObjectMetadataItem';
import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
+import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
import { isUndefined } from '@sniptt/guards';
import { useEffect } from 'react';
-import { useSetRecoilState } from 'recoil';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { isDefined } from '~/utils/isDefined';
@@ -39,8 +39,8 @@ export const QueryParamsViewIdEffect = () => {
objectMetadataItemId?.id,
lastVisitedObjectMetadataItemId,
);
- const setContextStoreCurrentViewId = useSetRecoilState(
- contextStoreCurrentViewIdState,
+ const setContextStoreCurrentViewId = useSetRecoilComponentStateV2(
+ contextStoreCurrentViewIdComponentState,
);
// // TODO: scope view bar per view id if possible
diff --git a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx
index 854f89e060..c9352d52f0 100644
--- a/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx
+++ b/packages/twenty-front/src/pages/object-record/RecordIndexPage.tsx
@@ -1,6 +1,8 @@
import styled from '@emotion/styled';
import { useParams } from 'react-router-dom';
+import { SetMainContextStoreComponentInstanceIdEffect } from '@/context-store/components/SetMainContextStoreComponentInstanceIdEffect';
+import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId';
@@ -73,9 +75,16 @@ 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 6c83840037..8f2d489bf7 100644
--- a/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx
+++ b/packages/twenty-front/src/pages/object-record/RecordShowPage.tsx
@@ -12,7 +12,6 @@ import { PageTitle } from '@/ui/utilities/page-title/components/PageTitle';
import { RecordShowPageWorkflowHeader } from '@/workflow/components/RecordShowPageWorkflowHeader';
import { RecordShowPageWorkflowVersionHeader } from '@/workflow/components/RecordShowPageWorkflowVersionHeader';
import { RecordShowPageBaseHeader } from '~/pages/object-record/RecordShowPageBaseHeader';
-import { RecordShowPageContextStoreEffect } from '~/pages/object-record/RecordShowPageContextStoreEffect';
import { RecordShowPageHeader } from '~/pages/object-record/RecordShowPageHeader';
export const RecordShowPage = () => {
@@ -40,7 +39,6 @@ export const RecordShowPage = () => {
return (
-
{
- const setContextStoreTargetedRecordsRule = useSetRecoilState(
- contextStoreTargetedRecordsRuleState,
- );
-
- const setContextStoreCurrentObjectMetadataId = useSetRecoilState(
- contextStoreCurrentObjectMetadataIdState,
- );
-
- const { objectNameSingular } = useParams();
-
- const { objectMetadataItem } = useObjectMetadataItem({
- objectNameSingular: objectNameSingular ?? '',
- });
-
- const setContextStoreNumberOfSelectedRecords = useSetRecoilState(
- contextStoreNumberOfSelectedRecordsState,
- );
-
- useEffect(() => {
- setContextStoreTargetedRecordsRule({
- mode: 'selection',
- selectedRecordIds: [recordId],
- });
- setContextStoreCurrentObjectMetadataId(objectMetadataItem?.id);
- setContextStoreNumberOfSelectedRecords(1);
-
- return () => {
- setContextStoreTargetedRecordsRule({
- mode: 'selection',
- selectedRecordIds: [],
- });
- setContextStoreCurrentObjectMetadataId(null);
- setContextStoreNumberOfSelectedRecords(0);
- };
- }, [
- recordId,
- setContextStoreTargetedRecordsRule,
- setContextStoreCurrentObjectMetadataId,
- objectMetadataItem?.id,
- setContextStoreNumberOfSelectedRecords,
- ]);
-
- return null;
-};
diff --git a/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx b/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx
index 866ebe143e..47ac02bcc8 100644
--- a/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx
+++ b/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx
@@ -1,12 +1,12 @@
import { ReactNode, useEffect, useState } from 'react';
-import { useSetRecoilState } from 'recoil';
-import { contextStoreCurrentObjectMetadataIdState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdState';
+import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState';
import {
ContextStoreTargetedRecordsRule,
- contextStoreTargetedRecordsRuleState,
-} from '@/context-store/states/contextStoreTargetedRecordsRuleState';
+ contextStoreTargetedRecordsRuleComponentState,
+} from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
+import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
export const JestContextStoreSetter = ({
contextStoreTargetedRecordsRule = {
@@ -20,11 +20,12 @@ export const JestContextStoreSetter = ({
contextStoreCurrentObjectMetadataNameSingular?: string;
children: ReactNode;
}) => {
- const setContextStoreTargetedRecordsRule = useSetRecoilState(
- contextStoreTargetedRecordsRuleState,
+ const setContextStoreTargetedRecordsRule = useSetRecoilComponentStateV2(
+ contextStoreTargetedRecordsRuleComponentState,
);
- const setContextStoreCurrentObjectMetadataId = useSetRecoilState(
- contextStoreCurrentObjectMetadataIdState,
+
+ const setContextStoreCurrentObjectMetadataId = useSetRecoilComponentStateV2(
+ contextStoreCurrentObjectMetadataIdComponentState,
);
const { objectMetadataItem } = useObjectMetadataItem({
diff --git a/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndContextStoreWrapper.tsx b/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndContextStoreWrapper.tsx
index e674d42821..fba19c23ba 100644
--- a/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndContextStoreWrapper.tsx
+++ b/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndContextStoreWrapper.tsx
@@ -1,4 +1,5 @@
-import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleState';
+import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
+import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { MockedResponse } from '@apollo/client/testing';
import { ReactNode } from 'react';
import { MutableSnapshot } from 'recoil';
@@ -10,6 +11,7 @@ export const getJestMetadataAndApolloMocksAndContextStoreWrapper = ({
onInitializeRecoilSnapshot,
contextStoreTargetedRecordsRule,
contextStoreCurrentObjectMetadataNameSingular,
+ componentInstanceId,
}: {
apolloMocks:
| readonly MockedResponse, Record>[]
@@ -17,6 +19,7 @@ export const getJestMetadataAndApolloMocksAndContextStoreWrapper = ({
onInitializeRecoilSnapshot?: (snapshot: MutableSnapshot) => void;
contextStoreTargetedRecordsRule?: ContextStoreTargetedRecordsRule;
contextStoreCurrentObjectMetadataNameSingular?: string;
+ componentInstanceId: string;
}) => {
const Wrapper = getJestMetadataAndApolloMocksWrapper({
apolloMocks,
@@ -24,14 +27,20 @@ export const getJestMetadataAndApolloMocksAndContextStoreWrapper = ({
});
return ({ children }: { children: ReactNode }) => (
-
- {children}
-
+
+ {children}
+
+
);
};
diff --git a/packages/twenty-ui/src/theme/constants/BackgroundDark.ts b/packages/twenty-ui/src/theme/constants/BackgroundDark.ts
index b594cb842b..446a6d2aa4 100644
--- a/packages/twenty-ui/src/theme/constants/BackgroundDark.ts
+++ b/packages/twenty-ui/src/theme/constants/BackgroundDark.ts
@@ -23,8 +23,9 @@ export const BACKGROUND_DARK = {
lighter: RGBA(GRAY_SCALE.gray0, 0.03),
danger: RGBA(COLOR.red, 0.08),
},
- overlayPrimary: RGBA(GRAY_SCALE.gray80, 0.8),
- overlaySecondary: RGBA(GRAY_SCALE.gray80, 0.4),
+ overlayPrimary: RGBA(GRAY_SCALE.gray90, 0.8),
+ overlaySecondary: RGBA(GRAY_SCALE.gray90, 0.4),
+ overlayTertiary: RGBA(GRAY_SCALE.gray90, 0.4),
radialGradient: `radial-gradient(50% 62.62% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`,
radialGradientHover: `radial-gradient(76.32% 95.59% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`,
primaryInverted: GRAY_SCALE.gray20,
diff --git a/packages/twenty-ui/src/theme/constants/BackgroundLight.ts b/packages/twenty-ui/src/theme/constants/BackgroundLight.ts
index 187ecf7de8..dfd68500ae 100644
--- a/packages/twenty-ui/src/theme/constants/BackgroundLight.ts
+++ b/packages/twenty-ui/src/theme/constants/BackgroundLight.ts
@@ -23,8 +23,9 @@ export const BACKGROUND_LIGHT = {
lighter: RGBA(GRAY_SCALE.gray100, 0.02),
danger: RGBA(COLOR.red, 0.08),
},
- overlayPrimary: RGBA(GRAY_SCALE.gray80, 0.8),
- overlaySecondary: RGBA(GRAY_SCALE.gray80, 0.4),
+ overlayPrimary: RGBA(GRAY_SCALE.gray90, 0.8),
+ overlaySecondary: RGBA(GRAY_SCALE.gray90, 0.4),
+ overlayTertiary: RGBA(GRAY_SCALE.gray90, 0.08),
radialGradient: `radial-gradient(50% 62.62% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`,
radialGradientHover: `radial-gradient(76.32% 95.59% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`,
primaryInverted: GRAY_SCALE.gray60,