Support side panel in record page layout (#15216)
## Demo https://github.com/user-attachments/assets/078b67d3-52d7-4ddf-a65a-fb002f82cfdd Closes https://github.com/twentyhq/core-team-issues/issues/1731 --------- Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
co-authored by
Félix Malfait
parent
ea09987e80
commit
e58668003d
-2
@@ -5,7 +5,6 @@ import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataI
|
||||
import { useObjectPermissions } from '@/object-record/hooks/useObjectPermissions';
|
||||
import { BASE_RECORD_LAYOUT } from '@/object-record/record-show/layouts/base-record-layout';
|
||||
import { COMPANY_RECORD_LAYOUT } from '@/object-record/record-show/layouts/company-record-layout';
|
||||
import { DASHBOARD_RECORD_LAYOUT } from '@/object-record/record-show/layouts/dashboard-record-layout';
|
||||
import { NOTE_RECORD_LAYOUT } from '@/object-record/record-show/layouts/note-record-layout';
|
||||
import { OPPORTUNITY_RECORD_LAYOUT } from '@/object-record/record-show/layouts/opportunity-record-layout';
|
||||
import { PERSON_RECORD_LAYOUT } from '@/object-record/record-show/layouts/person-record-layout';
|
||||
@@ -34,7 +33,6 @@ const OBJECT_SPECIFIC_LAYOUTS: Partial<
|
||||
[CoreObjectNameSingular.Workflow]: WORKFLOW_RECORD_LAYOUT,
|
||||
[CoreObjectNameSingular.WorkflowVersion]: WORKFLOW_VERSION_RECORD_LAYOUT,
|
||||
[CoreObjectNameSingular.WorkflowRun]: WORKFLOW_RUN_RECORD_LAYOUT,
|
||||
[CoreObjectNameSingular.Dashboard]: DASHBOARD_RECORD_LAYOUT,
|
||||
};
|
||||
|
||||
export const useRecordShowContainerTabs = (
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
import { CardType } from '@/object-record/record-show/types/CardType';
|
||||
import { type RecordLayout } from '@/object-record/record-show/types/RecordLayout';
|
||||
|
||||
export const DASHBOARD_RECORD_LAYOUT: RecordLayout = {
|
||||
hideSummaryAndFields: true,
|
||||
hideFieldsInSidePanel: true,
|
||||
tabs: {
|
||||
dashboard: {
|
||||
title: 'Dashboard',
|
||||
position: 101,
|
||||
icon: 'IconLayoutDashboard',
|
||||
cards: [{ type: CardType.DashboardCard }],
|
||||
hide: {
|
||||
ifMobile: false,
|
||||
ifDesktop: false,
|
||||
ifInRightDrawer: false,
|
||||
ifFeaturesDisabled: [],
|
||||
ifRequiredObjectsInactive: [],
|
||||
ifRelationsMissing: [],
|
||||
},
|
||||
},
|
||||
timeline: null,
|
||||
tasks: null,
|
||||
notes: null,
|
||||
files: null,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
import { SummaryCard } from '@/object-record/record-show/components/SummaryCard';
|
||||
import { PageLayoutGridLayout } from '@/page-layout/components/PageLayoutGridLayout';
|
||||
import { useCurrentPageLayout } from '@/page-layout/hooks/useCurrentPageLayout';
|
||||
import { useLayoutRenderingContext } from '@/ui/layout/contexts/LayoutRenderingContext';
|
||||
import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord';
|
||||
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
|
||||
import { PageLayoutType } from '~/generated/graphql';
|
||||
|
||||
type PageLayoutLeftPanelProps = {
|
||||
pinnedLeftTabId: string;
|
||||
};
|
||||
|
||||
export const PageLayoutLeftPanel = ({
|
||||
pinnedLeftTabId,
|
||||
}: PageLayoutLeftPanelProps) => {
|
||||
const { currentPageLayout } = useCurrentPageLayout();
|
||||
const targetRecordIdentifier = useTargetRecord();
|
||||
const { isInRightDrawer } = useLayoutRenderingContext();
|
||||
|
||||
if (currentPageLayout?.type !== PageLayoutType.RECORD_PAGE) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ShowPageLeftContainer>
|
||||
<SummaryCard
|
||||
objectNameSingular={targetRecordIdentifier.targetObjectNameSingular}
|
||||
objectRecordId={targetRecordIdentifier.id}
|
||||
isInRightDrawer={isInRightDrawer}
|
||||
/>
|
||||
|
||||
<PageLayoutGridLayout tabId={pinnedLeftTabId} />
|
||||
</ShowPageLeftContainer>
|
||||
);
|
||||
};
|
||||
+15
-19
@@ -1,15 +1,16 @@
|
||||
import { SummaryCard } from '@/object-record/record-show/components/SummaryCard';
|
||||
import { PageLayoutGridLayout } from '@/page-layout/components/PageLayoutGridLayout';
|
||||
import { PageLayoutLeftPanel } from '@/page-layout/components/PageLayoutLeftPanel';
|
||||
import { PageLayoutTabHeader } from '@/page-layout/components/PageLayoutTabHeader';
|
||||
import { useCreatePageLayoutTab } from '@/page-layout/hooks/useCreatePageLayoutTab';
|
||||
import { useCurrentPageLayout } from '@/page-layout/hooks/useCurrentPageLayout';
|
||||
import { isPageLayoutInEditModeComponentState } from '@/page-layout/states/isPageLayoutInEditModeComponentState';
|
||||
import { getTabListInstanceIdFromPageLayoutId } from '@/page-layout/utils/getTabListInstanceIdFromPageLayoutId';
|
||||
import { getTabsByDisplayMode } from '@/page-layout/utils/getTabsByDisplayMode';
|
||||
import { useLayoutRenderingContext } from '@/ui/layout/contexts/LayoutRenderingContext';
|
||||
import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord';
|
||||
import { ShowPageContainer } from '@/ui/layout/page/components/ShowPageContainer';
|
||||
import { ShowPageLeftContainer } from '@/ui/layout/show-page/components/ShowPageLeftContainer';
|
||||
import { TabList } from '@/ui/layout/tab-list/components/TabList';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import styled from '@emotion/styled';
|
||||
@@ -44,7 +45,6 @@ const StyledScrollWrapper = styled(ScrollWrapper)`
|
||||
export const PageLayoutRendererContent = () => {
|
||||
const { currentPageLayout } = useCurrentPageLayout();
|
||||
|
||||
const targetRecordIdentifier = useTargetRecord();
|
||||
const { isInRightDrawer } = useLayoutRenderingContext();
|
||||
|
||||
const isPageLayoutInEditMode = useRecoilComponentValue(
|
||||
@@ -57,29 +57,22 @@ export const PageLayoutRendererContent = () => {
|
||||
|
||||
const handleAddTab = isPageLayoutInEditMode ? createPageLayoutTab : undefined;
|
||||
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
if (!isDefined(currentPageLayout)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const tabsToRenderInTabList = currentPageLayout.tabs.filter(
|
||||
(tab) => tab.selfDisplayMode !== 'pinned-left',
|
||||
);
|
||||
const pinnedLeftTab = currentPageLayout.tabs.find(
|
||||
(tab) => tab.selfDisplayMode === 'pinned-left',
|
||||
);
|
||||
const { tabsToRenderInTabList, pinnedLeftTab } = getTabsByDisplayMode({
|
||||
pageLayout: currentPageLayout,
|
||||
isMobile,
|
||||
isInRightDrawer,
|
||||
});
|
||||
|
||||
return (
|
||||
<ShowPageContainer>
|
||||
{isDefined(pinnedLeftTab) && (
|
||||
<ShowPageLeftContainer forceMobile={false}>
|
||||
<SummaryCard
|
||||
objectNameSingular={targetRecordIdentifier.targetObjectNameSingular}
|
||||
objectRecordId={targetRecordIdentifier.id}
|
||||
isInRightDrawer={isInRightDrawer}
|
||||
/>
|
||||
|
||||
<PageLayoutGridLayout tabId={pinnedLeftTab.id} />
|
||||
</ShowPageLeftContainer>
|
||||
<PageLayoutLeftPanel pinnedLeftTabId={pinnedLeftTab.id} />
|
||||
)}
|
||||
|
||||
<StyledShowPageRightContainer>
|
||||
@@ -92,6 +85,9 @@ export const PageLayoutRendererContent = () => {
|
||||
)}
|
||||
onAddTab={handleAddTab}
|
||||
/>
|
||||
|
||||
<PageLayoutTabHeader />
|
||||
|
||||
<StyledScrollWrapper
|
||||
componentInstanceId={`scroll-wrapper-page-layout-${currentPageLayout.id}`}
|
||||
defaultEnableXScroll={false}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { SummaryCard } from '@/object-record/record-show/components/SummaryCard';
|
||||
import { useCurrentPageLayout } from '@/page-layout/hooks/useCurrentPageLayout';
|
||||
import { useLayoutRenderingContext } from '@/ui/layout/contexts/LayoutRenderingContext';
|
||||
import { useTargetRecord } from '@/ui/layout/contexts/useTargetRecord';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { PageLayoutType } from '~/generated/graphql';
|
||||
|
||||
export const PageLayoutTabHeader = () => {
|
||||
const { currentPageLayout } = useCurrentPageLayout();
|
||||
const targetRecordIdentifier = useTargetRecord();
|
||||
const { isInRightDrawer } = useLayoutRenderingContext();
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
if (
|
||||
currentPageLayout?.type !== PageLayoutType.RECORD_PAGE ||
|
||||
!(isMobile || isInRightDrawer)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<SummaryCard
|
||||
objectNameSingular={targetRecordIdentifier.targetObjectNameSingular}
|
||||
objectRecordId={targetRecordIdentifier.id}
|
||||
isInRightDrawer={isInRightDrawer}
|
||||
/>
|
||||
);
|
||||
};
|
||||
+444
@@ -0,0 +1,444 @@
|
||||
import { type DraftPageLayout } from '@/page-layout/types/draft-page-layout';
|
||||
import { type PageLayoutTab } from '@/page-layout/types/PageLayoutTab';
|
||||
import { PageLayoutType } from '~/generated/graphql';
|
||||
import { getTabsByDisplayMode } from '../getTabsByDisplayMode';
|
||||
|
||||
describe('getTabsByDisplayMode', () => {
|
||||
const createMockTab = (
|
||||
id: string,
|
||||
selfDisplayMode?: 'pinned-left',
|
||||
): PageLayoutTab => ({
|
||||
id,
|
||||
pageLayoutId: 'page-layout-1',
|
||||
title: `Tab ${id}`,
|
||||
position: 0,
|
||||
widgets: [],
|
||||
createdAt: '2024-01-01T00:00:00.000Z',
|
||||
updatedAt: '2024-01-01T00:00:00.000Z',
|
||||
selfDisplayMode,
|
||||
});
|
||||
|
||||
const createMockPageLayout = (tabs: PageLayoutTab[]): DraftPageLayout => ({
|
||||
id: 'page-layout-1',
|
||||
name: 'Test Layout',
|
||||
type: PageLayoutType.RECORD_PAGE,
|
||||
objectMetadataId: null,
|
||||
tabs,
|
||||
});
|
||||
|
||||
describe('when isMobile is true', () => {
|
||||
it('should return all tabs in tabsToRenderInTabList', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1'),
|
||||
createMockTab('tab-2'),
|
||||
createMockTab('tab-3', 'pinned-left'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: true,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(result.tabsToRenderInTabList).toEqual(tabs);
|
||||
expect(result.tabsToRenderInTabList).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('should return undefined for pinnedLeftTab', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1'),
|
||||
createMockTab('tab-2', 'pinned-left'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: true,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(result.pinnedLeftTab).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should handle empty tabs array', () => {
|
||||
const pageLayout = createMockPageLayout([]);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: true,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(result.tabsToRenderInTabList).toEqual([]);
|
||||
expect(result.pinnedLeftTab).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return all tabs even when all are pinned-left', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1', 'pinned-left'),
|
||||
createMockTab('tab-2', 'pinned-left'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: true,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(result.tabsToRenderInTabList).toEqual(tabs);
|
||||
expect(result.tabsToRenderInTabList).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when isInRightDrawer is true', () => {
|
||||
it('should return all tabs in tabsToRenderInTabList', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1'),
|
||||
createMockTab('tab-2'),
|
||||
createMockTab('tab-3', 'pinned-left'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: true,
|
||||
});
|
||||
|
||||
expect(result.tabsToRenderInTabList).toEqual(tabs);
|
||||
expect(result.tabsToRenderInTabList).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('should return undefined for pinnedLeftTab', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1'),
|
||||
createMockTab('tab-2', 'pinned-left'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: true,
|
||||
});
|
||||
|
||||
expect(result.pinnedLeftTab).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should handle empty tabs array', () => {
|
||||
const pageLayout = createMockPageLayout([]);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: true,
|
||||
});
|
||||
|
||||
expect(result.tabsToRenderInTabList).toEqual([]);
|
||||
expect(result.pinnedLeftTab).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return all tabs even when all are pinned-left', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1', 'pinned-left'),
|
||||
createMockTab('tab-2', 'pinned-left'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: true,
|
||||
});
|
||||
|
||||
expect(result.tabsToRenderInTabList).toEqual(tabs);
|
||||
expect(result.tabsToRenderInTabList).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when isMobile is false and isInRightDrawer is false', () => {
|
||||
it('should filter out pinned-left tabs from tabsToRenderInTabList', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1'),
|
||||
createMockTab('tab-2', 'pinned-left'),
|
||||
createMockTab('tab-3'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(result.tabsToRenderInTabList).toHaveLength(2);
|
||||
expect(result.tabsToRenderInTabList).toEqual([tabs[0], tabs[2]]);
|
||||
expect(
|
||||
result.tabsToRenderInTabList.every(
|
||||
(tab) => tab.selfDisplayMode !== 'pinned-left',
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return the pinned-left tab in pinnedLeftTab', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1'),
|
||||
createMockTab('tab-2', 'pinned-left'),
|
||||
createMockTab('tab-3'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(result.pinnedLeftTab).toBeDefined();
|
||||
expect(result.pinnedLeftTab?.id).toBe('tab-2');
|
||||
expect(result.pinnedLeftTab?.selfDisplayMode).toBe('pinned-left');
|
||||
});
|
||||
|
||||
it('should return undefined for pinnedLeftTab when no pinned tab exists', () => {
|
||||
const tabs = [createMockTab('tab-1'), createMockTab('tab-2')];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(result.pinnedLeftTab).toBeUndefined();
|
||||
expect(result.tabsToRenderInTabList).toEqual(tabs);
|
||||
});
|
||||
|
||||
it('should return all tabs in tabsToRenderInTabList when no pinned tabs exist', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1'),
|
||||
createMockTab('tab-2'),
|
||||
createMockTab('tab-3'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(result.tabsToRenderInTabList).toEqual(tabs);
|
||||
expect(result.tabsToRenderInTabList).toHaveLength(3);
|
||||
});
|
||||
|
||||
it('should handle empty tabs array', () => {
|
||||
const pageLayout = createMockPageLayout([]);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(result.tabsToRenderInTabList).toEqual([]);
|
||||
expect(result.pinnedLeftTab).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return first pinned-left tab when multiple exist', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1'),
|
||||
createMockTab('tab-2', 'pinned-left'),
|
||||
createMockTab('tab-3', 'pinned-left'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(result.pinnedLeftTab?.id).toBe('tab-2');
|
||||
expect(result.tabsToRenderInTabList).toHaveLength(1);
|
||||
expect(result.tabsToRenderInTabList[0].id).toBe('tab-1');
|
||||
});
|
||||
|
||||
it('should return empty array when all tabs are pinned-left', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1', 'pinned-left'),
|
||||
createMockTab('tab-2', 'pinned-left'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(result.tabsToRenderInTabList).toEqual([]);
|
||||
expect(result.pinnedLeftTab?.id).toBe('tab-1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('edge cases', () => {
|
||||
it('should handle single tab without pinned-left display mode', () => {
|
||||
const tabs = [createMockTab('tab-1')];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const resultMobile = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: true,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
const resultDesktop = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(resultMobile.tabsToRenderInTabList).toEqual(tabs);
|
||||
expect(resultMobile.pinnedLeftTab).toBeUndefined();
|
||||
|
||||
expect(resultDesktop.tabsToRenderInTabList).toEqual(tabs);
|
||||
expect(resultDesktop.pinnedLeftTab).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should handle single tab with pinned-left display mode', () => {
|
||||
const tabs = [createMockTab('tab-1', 'pinned-left')];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const resultMobile = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: true,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
const resultDesktop = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(resultMobile.tabsToRenderInTabList).toEqual(tabs);
|
||||
expect(resultMobile.pinnedLeftTab).toBeUndefined();
|
||||
|
||||
expect(resultDesktop.tabsToRenderInTabList).toEqual([]);
|
||||
expect(resultDesktop.pinnedLeftTab).toEqual(tabs[0]);
|
||||
});
|
||||
|
||||
it('should not mutate the original page layout', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1'),
|
||||
createMockTab('tab-2', 'pinned-left'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
const originalTabsLength = pageLayout.tabs.length;
|
||||
|
||||
getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(pageLayout.tabs).toHaveLength(originalTabsLength);
|
||||
expect(pageLayout.tabs).toEqual(tabs);
|
||||
});
|
||||
|
||||
it('should handle tabs with additional properties', () => {
|
||||
const tabWithExtraProps: PageLayoutTab = {
|
||||
...createMockTab('tab-1'),
|
||||
layoutMode: 'grid' as const,
|
||||
};
|
||||
const pageLayout = createMockPageLayout([tabWithExtraProps]);
|
||||
|
||||
const result = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(result.tabsToRenderInTabList[0].layoutMode).toBe('grid');
|
||||
});
|
||||
});
|
||||
|
||||
describe('consistency between mobile and desktop', () => {
|
||||
it('should return consistent results for the same input', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1'),
|
||||
createMockTab('tab-2', 'pinned-left'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const result1 = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
const result2 = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(result1).toEqual(result2);
|
||||
});
|
||||
|
||||
it('should show different results for mobile vs desktop', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1'),
|
||||
createMockTab('tab-2', 'pinned-left'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const mobileResult = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: true,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
const desktopResult = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
|
||||
expect(mobileResult.tabsToRenderInTabList.length).toBe(2);
|
||||
expect(desktopResult.tabsToRenderInTabList.length).toBe(1);
|
||||
|
||||
expect(mobileResult.pinnedLeftTab).toBeUndefined();
|
||||
expect(desktopResult.pinnedLeftTab).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when both isMobile and isInRightDrawer are true', () => {
|
||||
it('should behave the same as when only one is true', () => {
|
||||
const tabs = [
|
||||
createMockTab('tab-1'),
|
||||
createMockTab('tab-2', 'pinned-left'),
|
||||
];
|
||||
const pageLayout = createMockPageLayout(tabs);
|
||||
|
||||
const resultBothTrue = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: true,
|
||||
isInRightDrawer: true,
|
||||
});
|
||||
const resultOnlyMobile = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: true,
|
||||
isInRightDrawer: false,
|
||||
});
|
||||
const resultOnlyRightDrawer = getTabsByDisplayMode({
|
||||
pageLayout,
|
||||
isMobile: false,
|
||||
isInRightDrawer: true,
|
||||
});
|
||||
|
||||
expect(resultBothTrue).toEqual(resultOnlyMobile);
|
||||
expect(resultBothTrue).toEqual(resultOnlyRightDrawer);
|
||||
expect(resultBothTrue.tabsToRenderInTabList).toEqual(tabs);
|
||||
expect(resultBothTrue.pinnedLeftTab).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import { type DraftPageLayout } from '@/page-layout/types/draft-page-layout';
|
||||
import { type PageLayout } from '@/page-layout/types/PageLayout';
|
||||
import { PageLayoutType } from '~/generated/graphql';
|
||||
|
||||
type GetTabsByDisplayModeParams = {
|
||||
pageLayout: PageLayout | DraftPageLayout;
|
||||
isMobile: boolean;
|
||||
isInRightDrawer: boolean;
|
||||
};
|
||||
|
||||
export const getTabsByDisplayMode = ({
|
||||
pageLayout,
|
||||
isMobile,
|
||||
isInRightDrawer,
|
||||
}: GetTabsByDisplayModeParams) => {
|
||||
if (
|
||||
isMobile ||
|
||||
isInRightDrawer ||
|
||||
pageLayout.type !== PageLayoutType.RECORD_PAGE
|
||||
) {
|
||||
return {
|
||||
tabsToRenderInTabList: pageLayout.tabs,
|
||||
pinnedLeftTab: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
const tabsToRenderInTabList = pageLayout.tabs.filter(
|
||||
(tab) => tab.selfDisplayMode !== 'pinned-left',
|
||||
);
|
||||
const pinnedLeftTab = pageLayout.tabs.find(
|
||||
(tab) => tab.selfDisplayMode === 'pinned-left',
|
||||
);
|
||||
|
||||
return {
|
||||
tabsToRenderInTabList,
|
||||
pinnedLeftTab,
|
||||
};
|
||||
};
|
||||
+2
-3
@@ -30,15 +30,14 @@ const StyledIntermediateContainer = styled.div`
|
||||
`;
|
||||
|
||||
export type ShowPageLeftContainerProps = {
|
||||
forceMobile: boolean;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
export const ShowPageLeftContainer = ({
|
||||
forceMobile = false,
|
||||
children,
|
||||
}: ShowPageLeftContainerProps) => {
|
||||
const isMobile = useIsMobile() || forceMobile;
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
return (
|
||||
<StyledOuterContainer isMobile={isMobile}>
|
||||
{isMobile ? (
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ export const ShowPageSubContainer = ({
|
||||
value={{ instanceId: tabListComponentId }}
|
||||
>
|
||||
{displaySummaryAndFields && (
|
||||
<ShowPageLeftContainer forceMobile={isMobile}>
|
||||
<ShowPageLeftContainer>
|
||||
{summaryCard}
|
||||
{fieldsCard}
|
||||
</ShowPageLeftContainer>
|
||||
|
||||
Reference in New Issue
Block a user