Skip to content

Commit 097432d

Browse files
authored
[Command Menu] Refactor layout customization conditional availability [Warning] (#19974)
closes https://discord.com/channels/1130383047699738754/1494312529286004837
1 parent 3deb467 commit 097432d

20 files changed

Lines changed: 374 additions & 61 deletions

File tree

packages/twenty-front/src/modules/app/hooks/useExecuteTasksOnAnyLocationChange.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
2-
import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
31
import { isLayoutCustomizationModeEnabledState } from '@/layout-customization/states/isLayoutCustomizationModeEnabledState';
42
import { currentPageLayoutIdState } from '@/page-layout/states/currentPageLayoutIdState';
53
import { fieldsWidgetEditorModeDraftComponentState } from '@/page-layout/states/fieldsWidgetEditorModeDraftComponentState';
@@ -130,13 +128,6 @@ export const useExecuteTasksOnAnyLocationChange = () => {
130128

131129
store.set(currentPageLayoutIdState.atom, null);
132130
}
133-
134-
store.set(
135-
contextStoreIsPageInEditModeComponentState.atomFamily({
136-
instanceId: MAIN_CONTEXT_STORE_INSTANCE_ID,
137-
}),
138-
false,
139-
);
140131
}, [store]);
141132

142133
/**

packages/twenty-front/src/modules/command-menu-item/components/StandalonePageCommandMenu.tsx

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { CommandMenuItemEditButton } from '@/command-menu-item/edit/components/C
66
import { commandMenuItemsSelector } from '@/command-menu-item/states/commandMenuItemsSelector';
77
import { doesCommandMenuItemMatchObjectMetadataId } from '@/command-menu-item/utils/doesCommandMenuItemMatchObjectMetadataId';
88
import { doesCommandMenuItemMatchPageLayoutId } from '@/command-menu-item/utils/doesCommandMenuItemMatchPageLayoutId';
9+
import { isLayoutCustomizationModeEnabledState } from '@/layout-customization/states/isLayoutCustomizationModeEnabledState';
910
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
1011
import { currentPageLayoutIdState } from '@/page-layout/states/currentPageLayoutIdState';
1112
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
@@ -25,6 +26,9 @@ export const StandalonePageCommandMenu = () => {
2526
const commandMenuItems = useAtomStateValue(commandMenuItemsSelector);
2627
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
2728
const currentPageLayoutId = useAtomStateValue(currentPageLayoutIdState);
29+
const isLayoutCustomizationModeEnabled = useAtomStateValue(
30+
isLayoutCustomizationModeEnabledState,
31+
);
2832
const { objectMetadataItems } = useObjectMetadataItems();
2933

3034
const commandMenuContextApi = useMemo<CommandMenuContextApi>(() => {
@@ -52,7 +56,8 @@ export const StandalonePageCommandMenu = () => {
5256
return {
5357
pageType: ContextStorePageType.Standalone,
5458
isInSidePanel: false,
55-
isPageInEditMode: false,
59+
isDashboardPageLayoutInEditMode: false,
60+
isLayoutCustomizationModeEnabled,
5661
favoriteRecordIds: [],
5762
isSelectAll: false,
5863
hasAnySoftDeleteFilterOnView: false,
@@ -74,7 +79,12 @@ export const StandalonePageCommandMenu = () => {
7479
objectMetadataItem: {},
7580
objectMetadataLabel: '',
7681
};
77-
}, [currentWorkspace?.featureFlags, objectMetadataItems, store]);
82+
}, [
83+
currentWorkspace?.featureFlags,
84+
isLayoutCustomizationModeEnabled,
85+
objectMetadataItems,
86+
store,
87+
]);
7888

7989
const filteredCommandMenuItems = useMemo(() => {
8090
return commandMenuItems

packages/twenty-front/src/modules/command-menu-item/constants/EmptyCommandMenuContextApi.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import {
66
export const EMPTY_COMMAND_MENU_CONTEXT_API: CommandMenuContextApi = {
77
pageType: ContextStorePageType.Index,
88
isInSidePanel: false,
9-
isPageInEditMode: false,
9+
isDashboardPageLayoutInEditMode: false,
10+
isLayoutCustomizationModeEnabled: false,
1011
favoriteRecordIds: [],
1112
isSelectAll: false,
1213
hasAnySoftDeleteFilterOnView: false,

packages/twenty-front/src/modules/command-menu-item/hooks/__tests__/useCloseCommandMenu.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ const getWrapper =
4646
commandMenuContextApi: {
4747
pageType: ContextStorePageType.Index,
4848
isInSidePanel,
49-
isPageInEditMode: false,
49+
isDashboardPageLayoutInEditMode: false,
50+
isLayoutCustomizationModeEnabled: false,
5051
favoriteRecordIds: [],
5152
isSelectAll: false,
5253
hasAnySoftDeleteFilterOnView: false,

packages/twenty-front/src/modules/command-menu-item/hooks/useCommandMenuContextApi.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,25 @@ import { ContextStoreComponentInstanceContext } from '@/context-store/states/con
44
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
55
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
66
import { contextStoreCurrentPageTypeComponentState } from '@/context-store/states/contextStoreCurrentPageTypeComponentState';
7-
import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
87
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
98
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
109
import { useNavigationMenuItemsData } from '@/navigation-menu-item/display/hooks/useNavigationMenuItemsData';
1110
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
1211
import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPermissionsForObject';
12+
import { isLayoutCustomizationModeEnabledState } from '@/layout-customization/states/isLayoutCustomizationModeEnabledState';
1313
import { hasAnySoftDeleteFilterOnViewComponentSelector } from '@/object-record/record-filter/states/hasAnySoftDeleteFilterOnView';
1414
import { recordStoreRecordsSelector } from '@/object-record/record-store/states/selectors/recordStoreRecordsSelector';
1515
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
16+
import { currentPageLayoutIdState } from '@/page-layout/states/currentPageLayoutIdState';
17+
import { isDashboardInEditModeComponentState } from '@/page-layout/states/isDashboardInEditModeComponentState';
1618
import { SIDE_PANEL_COMPONENT_INSTANCE_ID } from '@/side-panel/constants/SidePanelComponentInstanceId';
1719
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
1820
import { useAtomComponentSelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorValue';
1921
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
2022
import { useAtomFamilySelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilySelectorValue';
2123
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
2224
import { isNonEmptyArray } from '@sniptt/guards';
23-
import { useStore } from 'jotai';
25+
import { useAtomValue, useStore } from 'jotai';
2426
import {
2527
ContextStorePageType,
2628
type CommandMenuContextApi,
@@ -77,6 +79,11 @@ export const useCommandMenuContextApi = (): CommandMenuContextApi => {
7779
{ recordIds: recordIds ?? [] },
7880
);
7981

82+
const currentPageLayoutId = useAtomStateValue(currentPageLayoutIdState);
83+
84+
const dashboardPageLayoutIdForCommandMenu =
85+
selectedRecords[0]?.pageLayoutId ?? currentPageLayoutId ?? '';
86+
8087
const objectPermissionsFromHook = useObjectPermissionsForObject(
8188
objectMetadataItem?.id ?? '',
8289
);
@@ -111,8 +118,14 @@ export const useCommandMenuContextApi = (): CommandMenuContextApi => {
111118
contextStoreCurrentPageTypeComponentState,
112119
);
113120

114-
const contextStoreIsPageInEditMode = useAtomComponentStateValue(
115-
contextStoreIsPageInEditModeComponentState,
121+
const isDashboardInEditMode = useAtomValue(
122+
isDashboardInEditModeComponentState.atomFamily({
123+
instanceId: dashboardPageLayoutIdForCommandMenu,
124+
}),
125+
);
126+
127+
const isLayoutCustomizationModeEnabled = useAtomStateValue(
128+
isLayoutCustomizationModeEnabledState,
116129
);
117130

118131
const pageType = isDefined(contextStoreCurrentPageType)
@@ -154,7 +167,8 @@ export const useCommandMenuContextApi = (): CommandMenuContextApi => {
154167
return {
155168
pageType,
156169
isInSidePanel,
157-
isPageInEditMode: contextStoreIsPageInEditMode,
170+
isDashboardPageLayoutInEditMode: isDashboardInEditMode,
171+
isLayoutCustomizationModeEnabled,
158172
favoriteRecordIds,
159173
isSelectAll,
160174
hasAnySoftDeleteFilterOnView,

packages/twenty-front/src/modules/context-store/states/contextStoreIsPageInEditModeComponentState.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

packages/twenty-front/src/modules/layout-customization/hooks/useEnterLayoutCustomizationMode.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { t } from '@lingui/core/macro';
22
import { useStore } from 'jotai';
33
import { useCallback } from 'react';
44
import { SidePanelPages } from 'twenty-shared/types';
5+
import { isDefined } from 'twenty-shared/utils';
56
import { IconPencil } from 'twenty-ui/display';
67

78
import { commandMenuItemsDraftState } from '@/command-menu-item/edit/states/commandMenuItemsDraftState';
@@ -11,13 +12,17 @@ import { isLayoutCustomizationModeEnabledState } from '@/layout-customization/st
1112
import { navigationMenuItemsDraftState } from '@/navigation-menu-item/common/states/navigationMenuItemsDraftState';
1213
import { navigationMenuItemsSelector } from '@/navigation-menu-item/common/states/navigationMenuItemsSelector';
1314
import { filterWorkspaceNavigationMenuItems } from '@/navigation-menu-item/common/utils/filterWorkspaceNavigationMenuItems';
15+
import { currentPageLayoutIdState } from '@/page-layout/states/currentPageLayoutIdState';
16+
import { isDashboardInEditModeComponentState } from '@/page-layout/states/isDashboardInEditModeComponentState';
1417
import { useNavigateSidePanel } from '@/side-panel/hooks/useNavigateSidePanel';
1518
import { isSidePanelOpenedState } from '@/side-panel/states/isSidePanelOpenedState';
1619
import { sidePanelPageState } from '@/side-panel/states/sidePanelPageState';
20+
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
1721

1822
export const useEnterLayoutCustomizationMode = () => {
1923
const store = useStore();
2024
const { navigateSidePanel } = useNavigateSidePanel();
25+
const { enqueueWarningSnackBar } = useSnackBar();
2126

2227
const enterLayoutCustomizationMode = useCallback(() => {
2328
const isLayoutCustomizationModeAlreadyEnabled = store.get(
@@ -28,6 +33,26 @@ export const useEnterLayoutCustomizationMode = () => {
2833
return;
2934
}
3035

36+
const dashboardPageLayoutIdInEditMode = store.get(
37+
currentPageLayoutIdState.atom,
38+
);
39+
40+
if (isDefined(dashboardPageLayoutIdInEditMode)) {
41+
const isDashboardInEditMode = store.get(
42+
isDashboardInEditModeComponentState.atomFamily({
43+
instanceId: dashboardPageLayoutIdInEditMode,
44+
}),
45+
);
46+
47+
if (isDashboardInEditMode) {
48+
enqueueWarningSnackBar({
49+
message: t`Save or cancel dashboard changes before editing the layout.`,
50+
});
51+
52+
return;
53+
}
54+
}
55+
3156
const prefetchNavigationMenuItems = store.get(
3257
navigationMenuItemsSelector.atom,
3358
);
@@ -57,7 +82,7 @@ export const useEnterLayoutCustomizationMode = () => {
5782
resetNavigationStack: true,
5883
});
5984
}
60-
}, [navigateSidePanel, store]);
85+
}, [enqueueWarningSnackBar, navigateSidePanel, store]);
6186

6287
return { enterLayoutCustomizationMode };
6388
};

packages/twenty-front/src/modules/page-layout/hooks/useSetIsPageLayoutInEditMode.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
2-
import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
31
import { isLayoutCustomizationModeEnabledState } from '@/layout-customization/states/isLayoutCustomizationModeEnabledState';
42
import { PageLayoutComponentInstanceContext } from '@/page-layout/states/contexts/PageLayoutComponentInstanceContext';
53
import { currentPageLayoutIdState } from '@/page-layout/states/currentPageLayoutIdState';
@@ -27,12 +25,6 @@ export const useSetIsPageLayoutInEditMode = (pageLayoutIdFromProps: string) => {
2725
pageLayoutId,
2826
);
2927

30-
const contextStoreIsFullTabWidgetInEditModeState =
31-
useAtomComponentStateCallbackState(
32-
contextStoreIsPageInEditModeComponentState,
33-
MAIN_CONTEXT_STORE_INSTANCE_ID,
34-
);
35-
3628
const fieldsWidgetGroupsDraftState = useAtomComponentStateCallbackState(
3729
fieldsWidgetGroupsDraftComponentState,
3830
pageLayoutId,
@@ -93,15 +85,12 @@ export const useSetIsPageLayoutInEditMode = (pageLayoutIdFromProps: string) => {
9385

9486
store.set(isDashboardInEditModeState, value);
9587

96-
store.set(contextStoreIsFullTabWidgetInEditModeState, value);
97-
9888
if (value) {
9989
store.set(currentPageLayoutIdState.atom, pageLayoutId);
10090
}
10191
},
10292
[
10393
isDashboardInEditModeState,
104-
contextStoreIsFullTabWidgetInEditModeState,
10594
fieldsWidgetGroupsDraftState,
10695
fieldsWidgetUngroupedFieldsDraftState,
10796
fieldsWidgetEditorModeDraftState,

packages/twenty-front/src/modules/side-panel/hooks/useOpenRecordInSidePanel.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainCo
77
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
88
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
99
import { contextStoreCurrentPageTypeComponentState } from '@/context-store/states/contextStoreCurrentPageTypeComponentState';
10-
import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
1110
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
1211
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
1312
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
@@ -137,17 +136,6 @@ export const useOpenRecordInSidePanel = () => {
137136
),
138137
);
139138

140-
store.set(
141-
contextStoreIsPageInEditModeComponentState.atomFamily({
142-
instanceId: pageComponentInstanceId,
143-
}),
144-
store.get(
145-
contextStoreIsPageInEditModeComponentState.atomFamily({
146-
instanceId: MAIN_CONTEXT_STORE_INSTANCE_ID,
147-
}),
148-
),
149-
);
150-
151139
const currentMorphItems = store.get(
152140
sidePanelNavigationMorphItemsByPageState.atom,
153141
);

packages/twenty-sdk/src/cli/utilities/build/common/conditional-availability/__tests__/transform-conditional-availability-expressions.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ const buildMockCommandMenuContextApi = (
1818
): CommandMenuContextApi => ({
1919
pageType: ContextStorePageType.Index,
2020
isInSidePanel: false,
21-
isPageInEditMode: false,
21+
isDashboardPageLayoutInEditMode: false,
22+
isLayoutCustomizationModeEnabled: false,
2223
favoriteRecordIds: [],
2324
isSelectAll: false,
2425
hasAnySoftDeleteFilterOnView: false,

0 commit comments

Comments
 (0)