Scaffold all company cards as widgets (#15149)
This PR doesn't support mobile and side-panel modes. The fields tab will be displayed in these cases. ## Demo https://github.com/user-attachments/assets/0b2e699c-2b8e-4212-8c75-00d7d2e25237 --------- Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
committed by
GitHub
parent
357a12f902
commit
f6d133f285
@@ -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'
|
||||
}
|
||||
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
|
||||
|
||||
@@ -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';
|
||||
@@ -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,
|
||||
);
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
+63
-17
@@ -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',
|
||||
);
|
||||
|
||||
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} />
|
||||
</ShowPageLeftContainer>
|
||||
)}
|
||||
|
||||
<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>
|
||||
</ShowPageContainer>
|
||||
);
|
||||
};
|
||||
|
||||
+14
-1
@@ -10,8 +10,10 @@ import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
import { FIND_ONE_PAGE_LAYOUT } from '@/dashboards/graphql/queries/findOnePageLayout';
|
||||
import { ApolloCoreClientContext } from '@/object-metadata/contexts/ApolloCoreClientContext';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { PageLayoutRenderer } from '@/page-layout/components/PageLayoutRenderer';
|
||||
import { generateGroupByQuery } from '@/page-layout/widgets/graph/utils/generateGroupByQuery';
|
||||
import { LayoutRenderingProvider } from '@/ui/layout/contexts/LayoutRenderingContext';
|
||||
import {
|
||||
GraphOrderBy,
|
||||
GraphType,
|
||||
@@ -270,7 +272,18 @@ const meta: Meta<typeof PageLayoutRenderer> = {
|
||||
<MemoryRouter>
|
||||
<JestMetadataAndApolloMocksWrapper>
|
||||
<CoreClientProviderWrapper>
|
||||
<Story />
|
||||
<LayoutRenderingProvider
|
||||
value={{
|
||||
isInRightDrawer: false,
|
||||
layoutType: PageLayoutType.DASHBOARD,
|
||||
targetRecordIdentifier: {
|
||||
targetObjectNameSingular: CoreObjectNameSingular.Dashboard,
|
||||
id: mixedGraphsPageLayoutMocks.id,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Story />
|
||||
</LayoutRenderingProvider>
|
||||
</CoreClientProviderWrapper>
|
||||
</JestMetadataAndApolloMocksWrapper>
|
||||
</MemoryRouter>
|
||||
|
||||
@@ -24,6 +24,7 @@ export const DEFAULT_PAGE_LAYOUT: PageLayout = {
|
||||
title: 'Fields',
|
||||
position: 100,
|
||||
layoutMode: 'vertical-list',
|
||||
selfDisplayMode: 'pinned-left',
|
||||
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',
|
||||
|
||||
@@ -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';
|
||||
};
|
||||
|
||||
+27
@@ -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>
|
||||
);
|
||||
};
|
||||
+24
@@ -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} />;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
+27
@@ -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>
|
||||
);
|
||||
};
|
||||
+1
@@ -8,6 +8,7 @@ import { type PageLayoutWidget } from '~/generated/graphql';
|
||||
const StyledContainer = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
type FieldsWidgetProps = {
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import { FilesCard } from '@/activities/files/components/FilesCard';
|
||||
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 FileWidgetProps = {
|
||||
widget: PageLayoutWidget;
|
||||
};
|
||||
|
||||
export const FileWidget = ({ widget: _widget }: FileWidgetProps) => {
|
||||
const { isInRightDrawer } = useLayoutRenderingContext();
|
||||
|
||||
return (
|
||||
<RightDrawerProvider value={{ isInRightDrawer }}>
|
||||
<StyledContainer>
|
||||
<FilesCard />
|
||||
</StyledContainer>
|
||||
</RightDrawerProvider>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
import { NotesCard } from '@/activities/notes/components/NotesCard';
|
||||
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 NoteWidgetProps = {
|
||||
widget: PageLayoutWidget;
|
||||
};
|
||||
|
||||
export const NoteWidget = ({ widget: _widget }: NoteWidgetProps) => {
|
||||
const { isInRightDrawer } = useLayoutRenderingContext();
|
||||
|
||||
return (
|
||||
<RightDrawerProvider value={{ isInRightDrawer }}>
|
||||
<StyledContainer>
|
||||
<NotesCard />
|
||||
</StyledContainer>
|
||||
</RightDrawerProvider>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
import { TasksCard } from '@/activities/tasks/components/TasksCard';
|
||||
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 TaskWidgetProps = {
|
||||
widget: PageLayoutWidget;
|
||||
};
|
||||
|
||||
export const TaskWidget = ({ widget: _widget }: TaskWidgetProps) => {
|
||||
const { isInRightDrawer } = useLayoutRenderingContext();
|
||||
|
||||
return (
|
||||
<RightDrawerProvider value={{ isInRightDrawer }}>
|
||||
<StyledContainer>
|
||||
<TasksCard />
|
||||
</StyledContainer>
|
||||
</RightDrawerProvider>
|
||||
);
|
||||
};
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { TimelineCard } from '@/activities/timeline-activities/components/TimelineCard';
|
||||
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 TimelineWidgetProps = {
|
||||
widget: PageLayoutWidget;
|
||||
};
|
||||
|
||||
export const TimelineWidget = ({ widget: _widget }: TimelineWidgetProps) => {
|
||||
const { isInRightDrawer } = useLayoutRenderingContext();
|
||||
|
||||
return (
|
||||
<RightDrawerProvider value={{ isInRightDrawer }}>
|
||||
<StyledContainer>
|
||||
<TimelineCard />
|
||||
</StyledContainer>
|
||||
</RightDrawerProvider>
|
||||
);
|
||||
};
|
||||
@@ -1,5 +1,5 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { type ReactElement } from 'react';
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||
@@ -24,7 +24,7 @@ const StyledScrollWrapper = styled(ScrollWrapper)`
|
||||
`;
|
||||
|
||||
export type ShowPageContainerProps = {
|
||||
children: ReactElement[] | ReactElement;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
export const ShowPageContainer = ({ children }: ShowPageContainerProps) => {
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
import { type MigrationInterface, type QueryRunner } from 'typeorm';
|
||||
|
||||
export class AddNewWidgetTypes1760628085765 implements MigrationInterface {
|
||||
name = 'AddNewWidgetTypes1760628085765';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TYPE "core"."pageLayoutWidget_type_enum" RENAME TO "pageLayoutWidget_type_enum_old"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TYPE "core"."pageLayoutWidget_type_enum" AS ENUM('VIEW', 'IFRAME', 'FIELDS', 'GRAPH', 'TIMELINE', 'TASKS', 'NOTES', 'FILES', 'EMAILS', 'CALENDAR')`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "type" DROP DEFAULT`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "type" TYPE "core"."pageLayoutWidget_type_enum" USING "type"::"text"::"core"."pageLayoutWidget_type_enum"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "type" SET DEFAULT 'VIEW'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP TYPE "core"."pageLayoutWidget_type_enum_old"`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TYPE "core"."pageLayoutWidget_type_enum_old" AS ENUM('FIELDS', 'GRAPH', 'IFRAME', 'VIEW')`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "type" DROP DEFAULT`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "type" TYPE "core"."pageLayoutWidget_type_enum_old" USING "type"::"text"::"core"."pageLayoutWidget_type_enum_old"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "type" SET DEFAULT 'VIEW'`,
|
||||
);
|
||||
await queryRunner.query(`DROP TYPE "core"."pageLayoutWidget_type_enum"`);
|
||||
await queryRunner.query(
|
||||
`ALTER TYPE "core"."pageLayoutWidget_type_enum_old" RENAME TO "pageLayoutWidget_type_enum"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1132,7 +1132,18 @@ export const computeMetadataSchemaComponents = (
|
||||
title: { type: 'string' },
|
||||
type: {
|
||||
type: 'string',
|
||||
enum: ['VIEW', 'IFRAME', 'FIELDS', 'GRAPH'],
|
||||
enum: [
|
||||
'VIEW',
|
||||
'IFRAME',
|
||||
'FIELDS',
|
||||
'GRAPH',
|
||||
'TIMELINE',
|
||||
'TASKS',
|
||||
'NOTES',
|
||||
'FILES',
|
||||
'EMAILS',
|
||||
'CALENDAR',
|
||||
],
|
||||
default: 'VIEW',
|
||||
},
|
||||
objectMetadataId: { type: 'string', format: 'uuid' },
|
||||
|
||||
@@ -3,4 +3,10 @@ export enum WidgetType {
|
||||
IFRAME = 'IFRAME',
|
||||
FIELDS = 'FIELDS',
|
||||
GRAPH = 'GRAPH',
|
||||
TIMELINE = 'TIMELINE',
|
||||
TASKS = 'TASKS',
|
||||
NOTES = 'NOTES',
|
||||
FILES = 'FILES',
|
||||
EMAILS = 'EMAILS',
|
||||
CALENDAR = 'CALENDAR',
|
||||
}
|
||||
|
||||
+6
@@ -268,6 +268,12 @@ export function getValidConfigForWidgetType(widgetType: string): any {
|
||||
}
|
||||
case 'VIEW':
|
||||
case 'FIELDS':
|
||||
case 'TIMELINE':
|
||||
case 'TASKS':
|
||||
case 'NOTES':
|
||||
case 'FILES':
|
||||
case 'EMAILS':
|
||||
case 'CALENDAR':
|
||||
return null;
|
||||
default:
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user