diff --git a/packages/twenty-front/src/modules/page-layout/components/__stories__/PageLayoutRenderer.stories.tsx b/packages/twenty-front/src/modules/page-layout/components/__stories__/PageLayoutRenderer.stories.tsx
index 4a657a7275..e96cb776a0 100644
--- a/packages/twenty-front/src/modules/page-layout/components/__stories__/PageLayoutRenderer.stories.tsx
+++ b/packages/twenty-front/src/modules/page-layout/components/__stories__/PageLayoutRenderer.stories.tsx
@@ -1,5 +1,5 @@
import type { Meta, StoryObj } from '@storybook/react';
-import { expect, within } from '@storybook/test';
+import { expect, waitFor, within } from '@storybook/test';
import { MemoryRouter } from 'react-router-dom';
import { PageLayoutRenderer } from '@/page-layout/components/PageLayoutRenderer';
@@ -13,18 +13,21 @@ import { type PageLayoutWidgetWithData } from '../../types/pageLayoutTypes';
const validatePageLayoutContent = async (canvasElement: HTMLElement) => {
const canvas = within(canvasElement);
- const revenueElements = await canvas.findAllByText('Revenue');
- await expect(revenueElements).toHaveLength(2);
- const goalProgressElements = await canvas.findAllByText('Goal Progress');
- await expect(goalProgressElements).toHaveLength(2);
+ await waitFor(async () => {
+ const revenueElements = canvas.getAllByText('Revenue');
+ expect(revenueElements).toHaveLength(2);
+
+ const goalProgressElements = canvas.getAllByText('Goal Progress');
+ expect(goalProgressElements).toHaveLength(2);
+
+ expect(canvas.getByText('Product Sales')).toBeInTheDocument();
+ expect(canvas.getByText('Services')).toBeInTheDocument();
+ expect(canvas.getByText('Support')).toBeInTheDocument();
+ });
+
await expect(await canvas.findByText('Revenue Sources')).toBeVisible();
await expect(await canvas.findByText('Quarterly Comparison')).toBeVisible();
-
await expect(await canvas.findByText('$125,000')).toBeVisible();
-
- await expect(await canvas.findByText('Product Sales')).toBeVisible();
- await expect(await canvas.findByText('Services')).toBeVisible();
- await expect(await canvas.findByText('Support')).toBeVisible();
};
const mixedGraphsPageLayout = {
diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/components/ChartSkeletonLoader.tsx b/packages/twenty-front/src/modules/page-layout/widgets/graph/components/ChartSkeletonLoader.tsx
new file mode 100644
index 0000000000..034df965f0
--- /dev/null
+++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/components/ChartSkeletonLoader.tsx
@@ -0,0 +1,17 @@
+import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader';
+import { useTheme } from '@emotion/react';
+import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
+
+export const ChartSkeletonLoader = () => {
+ const theme = useTheme();
+
+ return (
+
+
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/page-layout/widgets/graph/components/GraphWidgetRenderer.tsx b/packages/twenty-front/src/modules/page-layout/widgets/graph/components/GraphWidgetRenderer.tsx
index d5c0352ed9..1b3bd37e2d 100644
--- a/packages/twenty-front/src/modules/page-layout/widgets/graph/components/GraphWidgetRenderer.tsx
+++ b/packages/twenty-front/src/modules/page-layout/widgets/graph/components/GraphWidgetRenderer.tsx
@@ -1,11 +1,41 @@
import { GraphType } from '@/page-layout/mocks/mockWidgets';
import { getDefaultWidgetData } from '@/page-layout/utils/getDefaultWidgetData';
-import { GraphWidgetBarChart } from '@/page-layout/widgets/graph/components/GraphWidgetBarChart';
-import { GraphWidgetGaugeChart } from '@/page-layout/widgets/graph/components/GraphWidgetGaugeChart';
-import { GraphWidgetLineChart } from '@/page-layout/widgets/graph/components/GraphWidgetLineChart';
+import { ChartSkeletonLoader } from '@/page-layout/widgets/graph/components/ChartSkeletonLoader';
import { GraphWidgetNumberChart } from '@/page-layout/widgets/graph/components/GraphWidgetNumberChart';
-import { GraphWidgetPieChart } from '@/page-layout/widgets/graph/components/GraphWidgetPieChart';
import { type GraphWidget } from '@/page-layout/widgets/graph/types/GraphWidget';
+import { lazy, Suspense } from 'react';
+
+const GraphWidgetBarChart = lazy(() =>
+ import('@/page-layout/widgets/graph/components/GraphWidgetBarChart').then(
+ (module) => ({
+ default: module.GraphWidgetBarChart,
+ }),
+ ),
+);
+
+const GraphWidgetLineChart = lazy(() =>
+ import('@/page-layout/widgets/graph/components/GraphWidgetLineChart').then(
+ (module) => ({
+ default: module.GraphWidgetLineChart,
+ }),
+ ),
+);
+
+const GraphWidgetPieChart = lazy(() =>
+ import('@/page-layout/widgets/graph/components/GraphWidgetPieChart').then(
+ (module) => ({
+ default: module.GraphWidgetPieChart,
+ }),
+ ),
+);
+
+const GraphWidgetGaugeChart = lazy(() =>
+ import('@/page-layout/widgets/graph/components/GraphWidgetGaugeChart').then(
+ (module) => ({
+ default: module.GraphWidgetGaugeChart,
+ }),
+ ),
+);
type GraphWidgetRendererProps = {
widget: GraphWidget;
@@ -35,64 +65,72 @@ export const GraphWidgetRenderer = ({ widget }: GraphWidgetRendererProps) => {
case GraphType.GAUGE:
return (
-
+ }>
+
+
);
case GraphType.PIE:
return (
-
+ }>
+
+
);
case GraphType.BAR:
return (
-
+ }>
+
+
);
case GraphType.LINE:
return (
-
+ }>
+
+
);
default:
diff --git a/packages/twenty-front/src/modules/page-layout/widgets/iframe/components/IframeWidget.tsx b/packages/twenty-front/src/modules/page-layout/widgets/iframe/components/IframeWidget.tsx
index 6eb30b458c..90d8c40e9c 100644
--- a/packages/twenty-front/src/modules/page-layout/widgets/iframe/components/IframeWidget.tsx
+++ b/packages/twenty-front/src/modules/page-layout/widgets/iframe/components/IframeWidget.tsx
@@ -1,8 +1,6 @@
-import { SKELETON_LOADER_HEIGHT_SIZES } from '@/activities/components/SkeletonLoader';
-import { useTheme } from '@emotion/react';
+import { ChartSkeletonLoader } from '@/page-layout/widgets/graph/components/ChartSkeletonLoader';
import styled from '@emotion/styled';
import { useState } from 'react';
-import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
const StyledContainer = styled.div`
background: ${({ theme }) => theme.background.transparent.lighter};
@@ -67,7 +65,6 @@ export const IframeWidget = ({
url,
title = 'Embedded Content',
}: IframeWidgetProps) => {
- const theme = useTheme();
const [isLoading, setIsLoading] = useState(true);
const [hasError, setHasError] = useState(false);
@@ -95,16 +92,7 @@ export const IframeWidget = ({
{isLoading && (
-
-
-
+
)}
+ import('./WorkerMetricsGraph').then((module) => ({
+ default: module.WorkerMetricsGraph,
+ })),
+);
type WorkerQueueMetricsSectionProps = {
queue: AdminPanelWorkerQueueHealth;
@@ -50,11 +56,13 @@ export const WorkerQueueMetricsSection = ({
/>
-
+ }>
+
+
);
};