Differentiate edit mode behavior for record pages vs dashboards (#17550)

Temporary disable tabs edition for record page layouts


https://github.com/user-attachments/assets/c1f5d7fd-f125-4fb0-bf9c-96fadec14cd2

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Devessier <29370468+Devessier@users.noreply.github.com>
Co-authored-by: Baptiste Devessier <baptiste@devessier.fr>
This commit is contained in:
Copilot
2026-02-02 13:28:51 +00:00
committed by GitHub
parent 86c15551ce
commit 28763428f6
6 changed files with 99 additions and 18 deletions
@@ -14,6 +14,7 @@ import { getScrollWrapperInstanceIdFromPageLayoutId } from '@/page-layout/utils/
import { getTabListInstanceIdFromPageLayoutId } from '@/page-layout/utils/getTabListInstanceIdFromPageLayoutId';
import { getTabsByDisplayMode } from '@/page-layout/utils/getTabsByDisplayMode';
import { getTabsWithVisibleWidgets } from '@/page-layout/utils/getTabsWithVisibleWidgets';
import { shouldEnableTabEditingFeatures } from '@/page-layout/utils/shouldEnableTabEditingFeatures';
import { sortTabsByPosition } from '@/page-layout/utils/sortTabsByPosition';
import { useLayoutRenderingContext } from '@/ui/layout/contexts/LayoutRenderingContext';
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
@@ -66,23 +67,29 @@ export const PageLayoutRendererContent = () => {
);
const { navigatePageLayoutCommandMenu } = useNavigatePageLayoutCommandMenu();
const handleAddTab = isPageLayoutInEditMode
? () => {
const newTabId = createPageLayoutTab(t`Untitled`);
setTabSettingsOpenTabId(newTabId);
navigatePageLayoutCommandMenu({
commandMenuPage: CommandMenuPages.PageLayoutTabSettings,
focusTitleInput: true,
});
}
: undefined;
const isMobile = useIsMobile();
if (!isDefined(currentPageLayout)) {
return null;
}
const handleAddTab =
isPageLayoutInEditMode &&
shouldEnableTabEditingFeatures(currentPageLayout.type)
? () => {
const newTabId = createPageLayoutTab(t`Untitled`);
setTabSettingsOpenTabId(newTabId);
navigatePageLayoutCommandMenu({
commandMenuPage: CommandMenuPages.PageLayoutTabSettings,
focusTitleInput: true,
});
}
: undefined;
const canEnableTabEditing =
isPageLayoutInEditMode &&
shouldEnableTabEditingFeatures(currentPageLayout.type);
const tabsWithVisibleWidgets = getTabsWithVisibleWidgets({
tabs: currentPageLayout.tabs,
isMobile,
@@ -123,8 +130,9 @@ export const PageLayoutRendererContent = () => {
behaveAsLinks={!isInRightDrawer && !isPageLayoutInEditMode}
componentInstanceId={tabListInstanceId}
onAddTab={handleAddTab}
isReorderEnabled={isPageLayoutInEditMode}
onReorder={isPageLayoutInEditMode ? reorderTabs : undefined}
isReorderEnabled={canEnableTabEditing}
onReorder={canEnableTabEditing ? reorderTabs : undefined}
pageLayoutType={currentPageLayout.type}
/>
)}
@@ -37,11 +37,13 @@ import { isPageLayoutInEditModeComponentState } from '@/page-layout/states/isPag
import { pageLayoutTabListCurrentDragDroppableIdComponentState } from '@/page-layout/states/pageLayoutTabListCurrentDragDroppableIdComponentState';
import { pageLayoutTabSettingsOpenTabIdComponentState } from '@/page-layout/states/pageLayoutTabSettingsOpenTabIdComponentState';
import { type PageLayoutTab } from '@/page-layout/types/PageLayoutTab';
import { shouldEnableTabEditingFeatures } from '@/page-layout/utils/shouldEnableTabEditingFeatures';
import { TabListFromUrlOptionalEffect } from '@/ui/layout/tab-list/components/TabListFromUrlOptionalEffect';
import { type SingleTabProps } from '@/ui/layout/tab-list/types/SingleTabProps';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { isDefined } from 'twenty-shared/utils';
import { type PageLayoutType } from '~/generated/graphql';
const StyledContainer = styled.div`
box-sizing: border-box;
@@ -75,6 +77,7 @@ type PageLayoutTabListProps = Omit<TabListProps, 'tabs'> & {
onAddTab?: () => void;
onReorder?: (result: DropResult, provided: ResponderProvided) => boolean;
behaveAsLinks: boolean;
pageLayoutType: PageLayoutType;
};
export const PageLayoutTabList = ({
@@ -88,6 +91,7 @@ export const PageLayoutTabList = ({
onAddTab,
isReorderEnabled,
onReorder,
pageLayoutType,
}: PageLayoutTabListProps) => {
const { getIcon } = useIcons();
@@ -229,17 +233,24 @@ export const PageLayoutTabList = ({
const handleSelectTab = useCallback(
(tabId: string) => {
if (isPageLayoutInEditMode && activeTabId === tabId) {
const shouldOpenSettings =
isPageLayoutInEditMode &&
shouldEnableTabEditingFeatures(pageLayoutType);
if (shouldOpenSettings && activeTabId === tabId) {
openTabSettings(tabId);
return;
}
if (isPageLayoutInEditMode && isTabSettingsOpen) {
if (shouldOpenSettings && isTabSettingsOpen) {
openTabSettings(tabId);
}
selectTab(tabId);
},
[
isPageLayoutInEditMode,
pageLayoutType,
activeTabId,
isTabSettingsOpen,
openTabSettings,
@@ -249,18 +260,25 @@ export const PageLayoutTabList = ({
const handleSelectTabFromDropdown = useCallback(
(tabId: string) => {
if (isPageLayoutInEditMode && activeTabId === tabId) {
const shouldOpenSettings =
isPageLayoutInEditMode &&
shouldEnableTabEditingFeatures(pageLayoutType);
if (shouldOpenSettings && activeTabId === tabId) {
openTabSettings(tabId);
closeOverflowDropdown();
return;
}
if (isPageLayoutInEditMode && isTabSettingsOpen) {
if (shouldOpenSettings && isTabSettingsOpen) {
openTabSettings(tabId);
}
selectTabFromDropdown(tabId);
},
[
isPageLayoutInEditMode,
pageLayoutType,
activeTabId,
isTabSettingsOpen,
openTabSettings,
@@ -336,6 +354,7 @@ export const PageLayoutTabList = ({
onSelect={handleSelectTabFromDropdown}
visibleTabCount={visibleTabCount}
onClose={closeOverflowDropdown}
pageLayoutType={pageLayoutType}
/>
)}
@@ -18,6 +18,7 @@ import { PageLayoutComponentInstanceContext } from '@/page-layout/states/context
import { isPageLayoutInEditModeComponentState } from '@/page-layout/states/isPageLayoutInEditModeComponentState';
import { isPageLayoutTabDraggingComponentState } from '@/page-layout/states/isPageLayoutTabDraggingComponentState';
import { pageLayoutTabSettingsOpenTabIdComponentState } from '@/page-layout/states/pageLayoutTabSettingsOpenTabIdComponentState';
import { shouldEnableTabEditingFeatures } from '@/page-layout/utils/shouldEnableTabEditingFeatures';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
@@ -28,6 +29,7 @@ import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/com
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useContext } from 'react';
import { type PageLayoutType } from '~/generated/graphql';
const StyledOverflowDropdownListDraggableWrapper = styled.div`
display: flex;
@@ -48,6 +50,7 @@ type PageLayoutTabListReorderableOverflowDropdownProps = {
onSelect: (tabId: string) => void;
visibleTabCount: number;
onClose: () => void;
pageLayoutType: PageLayoutType;
};
export const PageLayoutTabListReorderableOverflowDropdown = ({
@@ -60,6 +63,7 @@ export const PageLayoutTabListReorderableOverflowDropdown = ({
onSelect,
visibleTabCount,
onClose,
pageLayoutType,
}: PageLayoutTabListReorderableOverflowDropdownProps) => {
const theme = useTheme();
const context = useContext(TabListComponentInstanceContext);
@@ -74,6 +78,9 @@ export const PageLayoutTabListReorderableOverflowDropdown = ({
pageLayoutId,
);
const shouldShowEditButton =
isPageLayoutInEditMode && shouldEnableTabEditingFeatures(pageLayoutType);
const isTabDragging = useRecoilComponentValue(
isPageLayoutTabDraggingComponentState,
instanceId,
@@ -201,7 +208,7 @@ export const PageLayoutTabListReorderableOverflowDropdown = ({
: () => handleTabSelect(tab.id)
}
disabled={disabled}
showEditButton={isPageLayoutInEditMode}
showEditButton={shouldShowEditButton}
onEditClick={handleEditClick}
/>
</div>
@@ -11,6 +11,7 @@ import { PageLayoutTabListEffect } from '@/page-layout/components/PageLayoutTabL
import { PageLayoutComponentInstanceContext } from '@/page-layout/states/contexts/PageLayoutComponentInstanceContext';
import { type PageLayoutTab } from '@/page-layout/types/PageLayoutTab';
import { calculateNewPosition } from '@/ui/layout/draggable-list/utils/calculateNewPosition';
import { PageLayoutType } from '~/generated/graphql';
const StyledContainer = styled.div`
border: 1px solid ${({ theme }) => theme.border.color.strong};
@@ -163,6 +164,7 @@ const PageLayoutTabListPlayground = ({
onAddTab={isReorderEnabled ? handleAddTab : undefined}
isReorderEnabled={isReorderEnabled}
onReorder={isReorderEnabled ? handleReorder : undefined}
pageLayoutType={PageLayoutType.DASHBOARD}
/>
</StyledContainer>
);
@@ -0,0 +1,38 @@
import { shouldEnableTabEditingFeatures } from '@/page-layout/utils/shouldEnableTabEditingFeatures';
import { PageLayoutType } from '~/generated/graphql';
describe('shouldEnableTabEditingFeatures', () => {
it('should return true for DASHBOARD layout type', () => {
const result = shouldEnableTabEditingFeatures(PageLayoutType.DASHBOARD);
expect(result).toBe(true);
});
it('should return false for RECORD_PAGE layout type', () => {
const result = shouldEnableTabEditingFeatures(PageLayoutType.RECORD_PAGE);
expect(result).toBe(false);
});
it('should return false for RECORD_INDEX layout type', () => {
const result = shouldEnableTabEditingFeatures(PageLayoutType.RECORD_INDEX);
expect(result).toBe(false);
});
describe('behavior validation', () => {
it('should enable tab editing features only for dashboards', () => {
// Dashboards should allow adding tabs and opening settings on click
expect(shouldEnableTabEditingFeatures(PageLayoutType.DASHBOARD)).toBe(
true,
);
// Record pages should NOT allow adding tabs or opening settings on click
expect(shouldEnableTabEditingFeatures(PageLayoutType.RECORD_PAGE)).toBe(
false,
);
// Record index pages should NOT allow adding tabs or opening settings on click
expect(shouldEnableTabEditingFeatures(PageLayoutType.RECORD_INDEX)).toBe(
false,
);
});
});
});
@@ -0,0 +1,7 @@
import { PageLayoutType } from '~/generated/graphql';
export const shouldEnableTabEditingFeatures = (
pageLayoutType: PageLayoutType,
): boolean => {
return pageLayoutType === PageLayoutType.DASHBOARD;
};