-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Scaffold all company cards as widgets #15149
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
575d134
6558f7e
1a4e2c5
c320228
dc3ce58
1076fe5
995679a
0ba89e4
83891d9
a92e2ed
fe67470
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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%; | ||
|
|
@@ -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%; | ||
| overflow: auto; | ||
| `; | ||
|
|
||
| const StyledTabList = styled(TabList)` | ||
| padding-left: ${({ theme }) => theme.spacing(2)}; | ||
| `; | ||
|
|
@@ -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; | ||
|
|
@@ -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
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
|
||
| 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} | ||
FelixMalfait marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /> | ||
FelixMalfait marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| <PageLayoutGridLayout tabId={pinnedLeftTab.id} /> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 AIThis 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
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| </ShowPageContainer> | ||
| ); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,6 +24,7 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = { | |
| title: 'Fields', | ||
| position: 100, | ||
| layoutMode: 'vertical-list', | ||
| selfDisplayMode: 'pinned-left', | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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(), | ||
|
|
@@ -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', | ||
|
|
@@ -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', | ||
|
|
@@ -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', | ||
|
|
@@ -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', | ||
|
|
@@ -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', | ||
|
|
@@ -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', | ||
|
|
||
| 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 = { | ||
|
|
@@ -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
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
| } | ||
|
|
||
| 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> | ||
| ); | ||
| }; |
There was a problem hiding this comment.
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%linesPrompt To Fix With AI
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes @Devessier