Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/twenty-front/src/generated-metadata/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4477,9 +4477,15 @@ export type Webhook = {
export type WidgetConfiguration = BarChartConfiguration | GaugeChartConfiguration | IframeConfiguration | LineChartConfiguration | NumberChartConfiguration | PieChartConfiguration;

export enum WidgetType {
CALENDAR = 'CALENDAR',
EMAILS = 'EMAILS',
FIELDS = 'FIELDS',
FILES = 'FILES',
GRAPH = 'GRAPH',
IFRAME = 'IFRAME',
NOTES = 'NOTES',
TASKS = 'TASKS',
TIMELINE = 'TIMELINE',
VIEW = 'VIEW'
}

Expand Down
6 changes: 6 additions & 0 deletions packages/twenty-front/src/generated/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4305,9 +4305,15 @@ export type Webhook = {
export type WidgetConfiguration = BarChartConfiguration | GaugeChartConfiguration | IframeConfiguration | LineChartConfiguration | NumberChartConfiguration | PieChartConfiguration;

export enum WidgetType {
CALENDAR = 'CALENDAR',
EMAILS = 'EMAILS',
FIELDS = 'FIELDS',
FILES = 'FILES',
GRAPH = 'GRAPH',
IFRAME = 'IFRAME',
NOTES = 'NOTES',
TASKS = 'TASKS',
TIMELINE = 'TIMELINE',
VIEW = 'VIEW'
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { pageLayoutCurrentBreakpointComponentState } from '@/page-layout/states/
import { pageLayoutCurrentLayoutsComponentState } from '@/page-layout/states/pageLayoutCurrentLayoutsComponentState';
import { WidgetPlaceholder } from '@/page-layout/widgets/components/WidgetPlaceholder';
import { WidgetRenderer } from '@/page-layout/widgets/components/WidgetRenderer';
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
Expand Down Expand Up @@ -63,7 +62,11 @@ const StyledVerticalListContainer = styled.div`
gap: ${({ theme }) => theme.spacing(2)};
`;

export const PageLayoutGridLayout = () => {
type PageLayoutGridLayoutProps = {
tabId: string;
};

export const PageLayoutGridLayout = ({ tabId }: PageLayoutGridLayoutProps) => {
const isRecordPageEnabled = useIsFeatureEnabled(
FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_ENABLED,
);
Expand All @@ -84,19 +87,11 @@ export const PageLayoutGridLayout = () => {
pageLayoutCurrentLayoutsComponentState,
);

const activeTabId = useRecoilComponentValue(activeTabIdComponentState);

const { currentPageLayout } = useCurrentPageLayout();

const activeTab = currentPageLayout?.tabs.find(
(tab) => tab.id === activeTabId,
);
const activeTab = currentPageLayout?.tabs.find((tab) => tab.id === tabId);

if (
!isDefined(activeTabId) ||
!isDefined(currentPageLayout) ||
!isDefined(activeTab)
) {
if (!isDefined(currentPageLayout) || !isDefined(activeTab)) {
return null;
}

Expand All @@ -107,7 +102,7 @@ export const PageLayoutGridLayout = () => {

const layouts = isLayoutEmpty
? EMPTY_LAYOUT
: (pageLayoutCurrentLayouts[activeTabId] ?? EMPTY_LAYOUT);
: (pageLayoutCurrentLayouts[tabId] ?? EMPTY_LAYOUT);

const Widgets = isLayoutEmpty ? (
<div key="empty-placeholder" data-select-disable="true">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import { SummaryCard } from '@/object-record/record-show/components/SummaryCard';
import { PageLayoutGridLayout } from '@/page-layout/components/PageLayoutGridLayout';
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 { 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 { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import styled from '@emotion/styled';
import { isDefined } from 'twenty-shared/utils';

const StyledContainer = styled.div`
const StyledTabsAndDashboardContainer = styled.div`
display: flex;
flex-direction: column;
height: 100%;
Expand All @@ -18,6 +24,16 @@ const StyledContainer = styled.div`
background: ${({ theme }) => theme.background.primary};
`;

const StyledShowPageRightContainer = styled.div`
display: flex;
flex-direction: column;
height: 100%;
justify-content: start;
width: 100%;
height: 100%;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

syntax: Duplicate height declaration - remove one of the height: 100% lines

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/twenty-front/src/modules/page-layout/components/PageLayoutRendererContent.tsx
Line: 33:33

Comment:
**syntax:** Duplicate height declaration - remove one of the `height: 100%` lines

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

overflow: auto;
`;

const StyledTabList = styled(TabList)`
padding-left: ${({ theme }) => theme.spacing(2)};
`;
Expand All @@ -29,10 +45,15 @@ const StyledScrollWrapper = styled(ScrollWrapper)`
export const PageLayoutRendererContent = () => {
const { currentPageLayout } = useCurrentPageLayout();

const targetRecordIdentifier = useTargetRecord();
const { isInRightDrawer } = useLayoutRenderingContext();

const isPageLayoutInEditMode = useRecoilComponentValue(
isPageLayoutInEditModeComponentState,
);

const activeTabId = useRecoilComponentValue(activeTabIdComponentState);

const { createPageLayoutTab } = useCreatePageLayoutTab(currentPageLayout?.id);

const handleAddTab = isPageLayoutInEditMode ? createPageLayoutTab : undefined;
Expand All @@ -41,22 +62,47 @@ export const PageLayoutRendererContent = () => {
return null;
}

const tabsToRenderInTabList = currentPageLayout.tabs.filter(
(tab) => tab.selfDisplayMode !== 'pinned-left',
);
const pinnedLeftTab = currentPageLayout.tabs.find(
(tab) => tab.selfDisplayMode === 'pinned-left',
);
Comment on lines +65 to +70
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

selfDisplayMode: 'pinned-left' on tabs


return (
<StyledContainer>
<StyledTabList
tabs={currentPageLayout.tabs}
behaveAsLinks={false}
componentInstanceId={getTabListInstanceIdFromPageLayoutId(
currentPageLayout.id,
)}
onAddTab={handleAddTab}
/>
<StyledScrollWrapper
componentInstanceId={`scroll-wrapper-page-layout-${currentPageLayout.id}`}
defaultEnableXScroll={false}
>
<PageLayoutGridLayout />
</StyledScrollWrapper>
</StyledContainer>
<ShowPageContainer>
{isDefined(pinnedLeftTab) && (
<ShowPageLeftContainer forceMobile={false}>
<SummaryCard
objectNameSingular={targetRecordIdentifier.targetObjectNameSingular}
objectRecordId={targetRecordIdentifier.id}
isInRightDrawer={isInRightDrawer}
/>

<PageLayoutGridLayout tabId={pinnedLeftTab.id} />
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logic: Potential issue: PageLayoutGridLayout is rendered twice with different tabIds. Verify this doesn't cause conflicts or duplicate rendering.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/twenty-front/src/modules/page-layout/components/PageLayoutRendererContent.tsx
Line: 82:82

Comment:
**logic:** Potential issue: PageLayoutGridLayout is rendered twice with different tabIds. Verify this doesn't cause conflicts or duplicate rendering.

How can I resolve this? If you propose a fix, please make it concise.

</ShowPageLeftContainer>
)}
Comment on lines +74 to +84
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard-coded left panel; not fan of it.


<StyledShowPageRightContainer>
<StyledTabsAndDashboardContainer>
<StyledTabList
tabs={tabsToRenderInTabList}
behaveAsLinks={false}
componentInstanceId={getTabListInstanceIdFromPageLayoutId(
currentPageLayout.id,
)}
onAddTab={handleAddTab}
/>
<StyledScrollWrapper
componentInstanceId={`scroll-wrapper-page-layout-${currentPageLayout.id}`}
defaultEnableXScroll={false}
>
{isDefined(activeTabId) && (
<PageLayoutGridLayout tabId={activeTabId} />
)}
</StyledScrollWrapper>
</StyledTabsAndDashboardContainer>
</StyledShowPageRightContainer>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Grid Layout Sync Issue

The PageLayoutGridLayout in the right container relies on activeTabId to render content. However, activeTabId isn't consistently synchronized with the non-pinned tabs, which can lead to an empty right container or duplicate rendering if it points to a pinned-left tab.

Fix in Cursor Fix in Web

</ShowPageContainer>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = {
title: 'Fields',
position: 100,
layoutMode: 'vertical-list',
selfDisplayMode: 'pinned-left',
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why "selfDisplayMode" and not just displayMode? I didn't get the nuance

pageLayoutId: DEFAULT_PAGE_LAYOUT_ID,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
Expand Down Expand Up @@ -67,7 +68,7 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = {
id: 'default-widget-timeline',
pageLayoutTabId: 'default-tab-timeline',
title: 'Timeline',
type: WidgetType.VIEW,
type: WidgetType.TIMELINE,
objectMetadataId: null,
gridPosition: {
__typename: 'GridPosition',
Expand Down Expand Up @@ -100,7 +101,7 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = {
id: 'default-widget-tasks',
pageLayoutTabId: 'default-tab-tasks',
title: 'Tasks',
type: WidgetType.VIEW,
type: WidgetType.TASKS,
objectMetadataId: null,
gridPosition: {
__typename: 'GridPosition',
Expand Down Expand Up @@ -133,7 +134,7 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = {
id: 'default-widget-notes',
pageLayoutTabId: 'default-tab-notes',
title: 'Notes',
type: WidgetType.VIEW,
type: WidgetType.NOTES,
objectMetadataId: null,
gridPosition: {
__typename: 'GridPosition',
Expand Down Expand Up @@ -166,7 +167,7 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = {
id: 'default-widget-files',
pageLayoutTabId: 'default-tab-files',
title: 'Files',
type: WidgetType.VIEW,
type: WidgetType.FILES,
objectMetadataId: null,
gridPosition: {
__typename: 'GridPosition',
Expand Down Expand Up @@ -199,7 +200,7 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = {
id: 'default-widget-emails',
pageLayoutTabId: 'default-tab-emails',
title: 'Emails',
type: WidgetType.VIEW,
type: WidgetType.EMAILS,
objectMetadataId: null,
gridPosition: {
__typename: 'GridPosition',
Expand Down Expand Up @@ -232,7 +233,7 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = {
id: 'default-widget-calendar',
pageLayoutTabId: 'default-tab-calendar',
title: 'Calendar',
type: WidgetType.VIEW,
type: WidgetType.CALENDAR,
objectMetadataId: null,
gridPosition: {
__typename: 'GridPosition',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ export type PageLayoutTab = Omit<PageLayoutTabGenerated, 'widgets'> & {
* Only available behind IS_RECORD_PAGE_LAYOUT_ENABLED for now.
*/
layoutMode?: 'grid' | 'vertical-list';
selfDisplayMode?: 'pinned-left';
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { CalendarEventsCard } from '@/activities/calendar/components/CalendarEventsCard';
import { useLayoutRenderingContext } from '@/ui/layout/contexts/LayoutRenderingContext';
import { RightDrawerProvider } from '@/ui/layout/right-drawer/contexts/RightDrawerContext';
import styled from '@emotion/styled';
import { type PageLayoutWidget } from '~/generated/graphql';

const StyledContainer = styled.div`
display: flex;
flex-direction: column;
width: 100%;
`;

type CalendarWidgetProps = {
widget: PageLayoutWidget;
};

export const CalendarWidget = ({ widget: _widget }: CalendarWidgetProps) => {
const { isInRightDrawer } = useLayoutRenderingContext();

return (
<RightDrawerProvider value={{ isInRightDrawer }}>
<StyledContainer>
<CalendarEventsCard />
</StyledContainer>
</RightDrawerProvider>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import { CalendarWidget } from '@/page-layout/widgets/calendar/components/CalendarWidget';
import { EmailWidget } from '@/page-layout/widgets/emails/components/EmailWidget';
import { FieldsWidget } from '@/page-layout/widgets/fields/components/FieldsWidget';
import { FileWidget } from '@/page-layout/widgets/files/components/FileWidget';
import { GraphWidgetRenderer } from '@/page-layout/widgets/graph/components/GraphWidgetRenderer';
import { IframeWidget } from '@/page-layout/widgets/iframe/components/IframeWidget';
import { NoteWidget } from '@/page-layout/widgets/notes/components/NoteWidget';
import { TaskWidget } from '@/page-layout/widgets/tasks/components/TaskWidget';
import { TimelineWidget } from '@/page-layout/widgets/timeline/components/TimelineWidget';
import { type PageLayoutWidget, WidgetType } from '~/generated/graphql';

type WidgetContentRendererProps = {
Expand All @@ -20,6 +26,24 @@ export const WidgetContentRenderer = ({
case WidgetType.FIELDS:
return <FieldsWidget widget={widget} />;

case WidgetType.TIMELINE:
return <TimelineWidget widget={widget} />;

case WidgetType.TASKS:
return <TaskWidget widget={widget} />;

case WidgetType.NOTES:
return <NoteWidget widget={widget} />;

case WidgetType.FILES:
return <FileWidget widget={widget} />;

case WidgetType.EMAILS:
return <EmailWidget widget={widget} />;

case WidgetType.CALENDAR:
return <CalendarWidget widget={widget} />;
Comment on lines +29 to +45
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At one point or another, we'll have to lazy-load the components


default:
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { EmailsCard } from '@/activities/emails/components/EmailsCard';
import { useLayoutRenderingContext } from '@/ui/layout/contexts/LayoutRenderingContext';
import { RightDrawerProvider } from '@/ui/layout/right-drawer/contexts/RightDrawerContext';
import styled from '@emotion/styled';
import { type PageLayoutWidget } from '~/generated/graphql';

const StyledContainer = styled.div`
display: flex;
flex-direction: column;
width: 100%;
`;

type EmailWidgetProps = {
widget: PageLayoutWidget;
};

export const EmailWidget = ({ widget: _widget }: EmailWidgetProps) => {
const { isInRightDrawer } = useLayoutRenderingContext();

return (
<RightDrawerProvider value={{ isInRightDrawer }}>
<StyledContainer>
<EmailsCard />
</StyledContainer>
</RightDrawerProvider>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { type PageLayoutWidget } from '~/generated/graphql';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
width: 100%;
`;

type FieldsWidgetProps = {
Expand Down
Loading
Loading