Lazy load Nivo (#14454)

oops :p
This commit is contained in:
nitin
2025-09-13 18:52:43 +05:30
committed by GitHub
parent da5ecf35fa
commit b5809096f8
5 changed files with 135 additions and 81 deletions
@@ -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 = {
@@ -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 (
<SkeletonTheme
baseColor={theme.background.tertiary}
highlightColor={theme.background.transparent.lighter}
borderRadius={4}
>
<Skeleton width={120} height={SKELETON_LOADER_HEIGHT_SIZES.standard.m} />
</SkeletonTheme>
);
};
@@ -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 (
<GraphWidgetGaugeChart
data={{
value: data.value,
min: data.min,
max: data.max,
label: data.label,
}}
displayType="percentage"
showValue
id={`gauge-chart-${widget.id}`}
/>
<Suspense fallback={<ChartSkeletonLoader />}>
<GraphWidgetGaugeChart
data={{
value: data.value,
min: data.min,
max: data.max,
label: data.label,
}}
displayType="percentage"
showValue
id={`gauge-chart-${widget.id}`}
/>
</Suspense>
);
case GraphType.PIE:
return (
<GraphWidgetPieChart
data={data.items}
showLegend
displayType="percentage"
id={`pie-chart-${widget.id}`}
/>
<Suspense fallback={<ChartSkeletonLoader />}>
<GraphWidgetPieChart
data={data.items}
showLegend
displayType="percentage"
id={`pie-chart-${widget.id}`}
/>
</Suspense>
);
case GraphType.BAR:
return (
<GraphWidgetBarChart
data={data.items}
indexBy={data.indexBy}
keys={data.keys}
seriesLabels={data.seriesLabels}
layout={data.layout}
showLegend
showGrid
displayType="number"
id={`bar-chart-${widget.id}`}
/>
<Suspense fallback={<ChartSkeletonLoader />}>
<GraphWidgetBarChart
data={data.items}
indexBy={data.indexBy}
keys={data.keys}
seriesLabels={data.seriesLabels}
layout={data.layout}
showLegend
showGrid
displayType="number"
id={`bar-chart-${widget.id}`}
/>
</Suspense>
);
case GraphType.LINE:
return (
<GraphWidgetLineChart
id={`line-chart-${widget.id}`}
data={data.series}
enableArea={data.enableArea}
showLegend={data.showLegend}
showGrid={data.showGrid}
enablePoints={data.enablePoints}
xAxisLabel={data.xAxisLabel}
yAxisLabel={data.yAxisLabel}
displayType={data.displayType}
prefix={data.prefix}
suffix={data.suffix}
xScale={data.xScale}
yScale={data.yScale}
curve={data.curve}
stackedArea={data.stackedArea}
enableSlices={data.enableSlices}
/>
<Suspense fallback={<ChartSkeletonLoader />}>
<GraphWidgetLineChart
id={`line-chart-${widget.id}`}
data={data.series}
enableArea={data.enableArea}
showLegend={data.showLegend}
showGrid={data.showGrid}
enablePoints={data.enablePoints}
xAxisLabel={data.xAxisLabel}
yAxisLabel={data.yAxisLabel}
displayType={data.displayType}
prefix={data.prefix}
suffix={data.suffix}
xScale={data.xScale}
yScale={data.yScale}
curve={data.curve}
stackedArea={data.stackedArea}
enableSlices={data.enableSlices}
/>
</Suspense>
);
default:
@@ -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 = ({
<StyledContainer>
{isLoading && (
<StyledLoadingContainer>
<SkeletonTheme
baseColor={theme.background.tertiary}
highlightColor={theme.background.transparent.lighter}
borderRadius={4}
>
<Skeleton
width={120}
height={SKELETON_LOADER_HEIGHT_SIZES.standard.m}
/>
</SkeletonTheme>
<ChartSkeletonLoader />
</StyledLoadingContainer>
)}
<StyledIframe
@@ -1,15 +1,21 @@
import { ChartSkeletonLoader } from '@/page-layout/widgets/graph/components/ChartSkeletonLoader';
import { WORKER_QUEUE_METRICS_SELECT_OPTIONS } from '@/settings/admin-panel/health-status/constants/WorkerQueueMetricsSelectOptions';
import { Select } from '@/ui/input/components/Select';
import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
import { useState } from 'react';
import { lazy, Suspense, useState } from 'react';
import { H2Title } from 'twenty-ui/display';
import { Section } from 'twenty-ui/layout';
import {
type AdminPanelWorkerQueueHealth,
QueueMetricsTimeRange,
} from '~/generated-metadata/graphql';
import { WorkerMetricsGraph } from './WorkerMetricsGraph';
const WorkerMetricsGraph = lazy(() =>
import('./WorkerMetricsGraph').then((module) => ({
default: module.WorkerMetricsGraph,
})),
);
type WorkerQueueMetricsSectionProps = {
queue: AdminPanelWorkerQueueHealth;
@@ -50,11 +56,13 @@ export const WorkerQueueMetricsSection = ({
/>
</StyledControlsContainer>
</Section>
<WorkerMetricsGraph
queueName={queue.queueName}
timeRange={timeRange}
onTimeRangeChange={setTimeRange}
/>
<Suspense fallback={<ChartSkeletonLoader />}>
<WorkerMetricsGraph
queueName={queue.queueName}
timeRange={timeRange}
onTimeRangeChange={setTimeRange}
/>
</Suspense>
</StyledContainer>
);
};