diff --git a/frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx b/frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx
index 1baee2436f..1713033313 100644
--- a/frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx
+++ b/frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx
@@ -33,6 +33,7 @@ const useDashboardGrid = () => {
chartSpan: 1,
userTrendsOrder: 3,
flagStatsOrder: 2,
+ largeChartSpan: 1,
};
}
@@ -42,6 +43,7 @@ const useDashboardGrid = () => {
chartSpan: 2,
userTrendsOrder: 3,
flagStatsOrder: 2,
+ largeChartSpan: 2,
};
}
@@ -50,6 +52,7 @@ const useDashboardGrid = () => {
chartSpan: 1,
userTrendsOrder: 2,
flagStatsOrder: 3,
+ largeChartSpan: 2,
};
};
@@ -69,8 +72,13 @@ export const ExecutiveDashboard: VFC = () => {
).toFixed(1);
}, [executiveDashboardData]);
- const { gridTemplateColumns, chartSpan, userTrendsOrder, flagStatsOrder } =
- useDashboardGrid();
+ const {
+ gridTemplateColumns,
+ chartSpan,
+ userTrendsOrder,
+ flagStatsOrder,
+ largeChartSpan,
+ } = useDashboardGrid();
return (
<>
@@ -107,11 +115,18 @@ export const ExecutiveDashboard: VFC = () => {
flagTrends={executiveDashboardData.flagTrends}
/>
+
+
+
-
-
>
);
};
diff --git a/frontend/src/component/executiveDashboard/FlagsChart/FlagsChart.tsx b/frontend/src/component/executiveDashboard/FlagsChart/FlagsChart.tsx
index 694e0687e8..92d1e5ad13 100644
--- a/frontend/src/component/executiveDashboard/FlagsChart/FlagsChart.tsx
+++ b/frontend/src/component/executiveDashboard/FlagsChart/FlagsChart.tsx
@@ -1,3 +1,37 @@
-import { lazy } from 'react';
+import { useMemo, type VFC } from 'react';
+import 'chartjs-adapter-date-fns';
+import { useTheme } from '@mui/material';
+import { ExecutiveSummarySchema } from 'openapi';
+import { LineChart } from '../LineChart/LineChart';
-export const FlagsChart = lazy(() => import('./FlagsChartComponent'));
+interface IFlagsChartProps {
+ flagTrends: ExecutiveSummarySchema['flagTrends'];
+}
+
+export const FlagsChart: VFC = ({ flagTrends }) => {
+ const theme = useTheme();
+ const data = useMemo(
+ () => ({
+ labels: flagTrends.map((item) => item.date),
+ datasets: [
+ {
+ label: 'Total flags',
+ data: flagTrends.map((item) => item.total),
+ borderColor: theme.palette.primary.light,
+ backgroundColor: theme.palette.primary.light,
+ fill: true,
+ },
+ {
+ label: 'Stale',
+ data: flagTrends.map((item) => item.stale),
+ borderColor: theme.palette.warning.border,
+ backgroundColor: theme.palette.warning.border,
+ fill: true,
+ },
+ ],
+ }),
+ [theme, flagTrends],
+ );
+
+ return ;
+};
diff --git a/frontend/src/component/executiveDashboard/FlagsChart/FlagsChartComponent.tsx b/frontend/src/component/executiveDashboard/FlagsChart/FlagsChartComponent.tsx
deleted file mode 100644
index bcb52b0db9..0000000000
--- a/frontend/src/component/executiveDashboard/FlagsChart/FlagsChartComponent.tsx
+++ /dev/null
@@ -1,137 +0,0 @@
-import { useMemo, type VFC } from 'react';
-import {
- Chart as ChartJS,
- CategoryScale,
- LinearScale,
- PointElement,
- LineElement,
- Title,
- Tooltip,
- Legend,
- TimeScale,
-} from 'chart.js';
-import { Line } from 'react-chartjs-2';
-import 'chartjs-adapter-date-fns';
-import { Theme, useTheme } from '@mui/material';
-import {
- useLocationSettings,
- type ILocationSettings,
-} from 'hooks/useLocationSettings';
-import { formatDateYMD } from 'utils/formatDate';
-import { ExecutiveSummarySchema } from 'openapi';
-
-const createData = (
- theme: Theme,
- flagTrends: ExecutiveSummarySchema['flagTrends'] = [],
-) => ({
- labels: flagTrends.map((item) => item.date),
- datasets: [
- {
- label: 'Total flags',
- data: flagTrends.map((item) => item.total),
- borderColor: theme.palette.primary.main,
- backgroundColor: theme.palette.primary.main,
- fill: true,
- },
- {
- label: 'Stale',
- data: flagTrends.map((item) => item.stale),
- borderColor: theme.palette.warning.main,
- backgroundColor: theme.palette.warning.main,
- fill: true,
- },
- {
- label: 'Active flags',
- data: flagTrends.map((item) => item.active),
- borderColor: theme.palette.success.main,
- backgroundColor: theme.palette.success.main,
- fill: true,
- },
- ],
-});
-
-const createOptions = (theme: Theme, locationSettings: ILocationSettings) =>
- ({
- responsive: true,
- plugins: {
- legend: {
- position: 'bottom',
- },
- tooltip: {
- callbacks: {
- title: (tooltipItems: any) => {
- const item = tooltipItems?.[0];
- const date =
- item?.chart?.data?.labels?.[item.dataIndex];
- return date
- ? formatDateYMD(
- date,
- locationSettings.locale,
- 'UTC',
- )
- : '';
- },
- },
- },
- },
- locale: locationSettings.locale,
- interaction: {
- intersect: false,
- axis: 'x',
- },
- color: theme.palette.text.secondary,
- scales: {
- y: {
- type: 'linear',
- grid: {
- color: theme.palette.divider,
- borderColor: theme.palette.divider,
- },
- ticks: { color: theme.palette.text.secondary },
- },
- x: {
- type: 'time',
- time: {
- unit: 'month',
- },
- grid: {
- color: theme.palette.divider,
- borderColor: theme.palette.divider,
- },
- ticks: {
- color: theme.palette.text.secondary,
- },
- },
- },
- }) as const;
-
-interface IFlagsChartComponentProps {
- flagTrends: ExecutiveSummarySchema['flagTrends'];
-}
-
-const FlagsChartComponent: VFC = ({
- flagTrends,
-}) => {
- const theme = useTheme();
- const { locationSettings } = useLocationSettings();
- const data = useMemo(
- () => createData(theme, flagTrends),
- [theme, flagTrends],
- );
- const options = createOptions(theme, locationSettings);
-
- return ;
-};
-
-ChartJS.register(
- CategoryScale,
- LinearScale,
- PointElement,
- LineElement,
- TimeScale,
- Title,
- Tooltip,
- Legend,
-);
-
-export default FlagsChartComponent;
diff --git a/frontend/src/component/executiveDashboard/FlagsProjectChart/FlagsProjectChart.tsx b/frontend/src/component/executiveDashboard/FlagsProjectChart/FlagsProjectChart.tsx
index 0200b68fd5..8bc0f2a79b 100644
--- a/frontend/src/component/executiveDashboard/FlagsProjectChart/FlagsProjectChart.tsx
+++ b/frontend/src/component/executiveDashboard/FlagsProjectChart/FlagsProjectChart.tsx
@@ -1,5 +1,58 @@
-import { lazy } from 'react';
+import { useMemo, type VFC } from 'react';
+import 'chartjs-adapter-date-fns';
+import { useTheme } from '@mui/material';
+import {
+ ExecutiveSummarySchema,
+ ExecutiveSummarySchemaProjectFlagTrendsItem,
+} from 'openapi';
+import { LineChart } from '../LineChart/LineChart';
-export const FlagsProjectChart = lazy(
- () => import('./FlagsProjectChartComponent'),
-);
+interface IFlagsProjectChartProps {
+ projectFlagTrends: ExecutiveSummarySchema['projectFlagTrends'];
+}
+
+const getRandomColor = () => {
+ const letters = '0123456789ABCDEF';
+ let color = '#';
+ for (let i = 0; i < 6; i++) {
+ color += letters[Math.floor(Math.random() * 16)];
+ }
+ return color;
+};
+
+export const FlagsProjectChart: VFC = ({
+ projectFlagTrends,
+}) => {
+ const theme = useTheme();
+ const data = useMemo(() => {
+ const groupedFlagTrends = projectFlagTrends.reduce<
+ Record
+ >((groups, item) => {
+ if (!groups[item.project]) {
+ groups[item.project] = [];
+ }
+ groups[item.project].push(item);
+ return groups;
+ }, {});
+
+ const datasets = Object.entries(groupedFlagTrends).map(
+ ([project, trends]) => {
+ const color = getRandomColor();
+ return {
+ label: project,
+ data: trends.map((item) => item.total),
+ borderColor: color,
+ backgroundColor: color,
+ fill: true,
+ };
+ },
+ );
+
+ return {
+ labels: projectFlagTrends.map((item) => item.date),
+ datasets,
+ };
+ }, [theme, projectFlagTrends]);
+
+ return ;
+};
diff --git a/frontend/src/component/executiveDashboard/FlagsProjectChart/FlagsProjectChartComponent.tsx b/frontend/src/component/executiveDashboard/FlagsProjectChart/FlagsProjectChartComponent.tsx
deleted file mode 100644
index 07b5424126..0000000000
--- a/frontend/src/component/executiveDashboard/FlagsProjectChart/FlagsProjectChartComponent.tsx
+++ /dev/null
@@ -1,162 +0,0 @@
-import { useMemo, type VFC } from 'react';
-import {
- Chart as ChartJS,
- CategoryScale,
- LinearScale,
- PointElement,
- LineElement,
- Title,
- Tooltip,
- Legend,
- TimeScale,
-} from 'chart.js';
-import { Line } from 'react-chartjs-2';
-import 'chartjs-adapter-date-fns';
-import { Paper, Theme, Typography, useTheme } from '@mui/material';
-import {
- useLocationSettings,
- type ILocationSettings,
-} from 'hooks/useLocationSettings';
-import { formatDateYMD } from 'utils/formatDate';
-import {
- ExecutiveSummarySchema,
- ExecutiveSummarySchemaProjectFlagTrendsItem,
-} from 'openapi';
-
-const getRandomColor = () => {
- const letters = '0123456789ABCDEF';
- let color = '#';
- for (let i = 0; i < 6; i++) {
- color += letters[Math.floor(Math.random() * 16)];
- }
- return color;
-};
-
-const createData = (
- theme: Theme,
- flagTrends: ExecutiveSummarySchema['projectFlagTrends'] = [],
-) => {
- const groupedFlagTrends = flagTrends.reduce<
- Record
- >((groups, item) => {
- if (!groups[item.project]) {
- groups[item.project] = [];
- }
- groups[item.project].push(item);
- return groups;
- }, {});
-
- const datasets = Object.entries(groupedFlagTrends).map(
- ([project, trends]) => {
- const color = getRandomColor();
- return {
- label: project,
- data: trends.map((item) => item.total),
- borderColor: color,
- backgroundColor: color,
- fill: true,
- };
- },
- );
-
- return {
- labels: flagTrends.map((item) => item.date),
- datasets,
- };
-};
-
-const createOptions = (theme: Theme, locationSettings: ILocationSettings) =>
- ({
- responsive: true,
- plugins: {
- legend: {
- position: 'bottom',
- },
- tooltip: {
- callbacks: {
- title: (tooltipItems: any) => {
- const item = tooltipItems?.[0];
- const date =
- item?.chart?.data?.labels?.[item.dataIndex];
- return date
- ? formatDateYMD(
- date,
- locationSettings.locale,
- 'UTC',
- )
- : '';
- },
- },
- },
- },
- locale: locationSettings.locale,
- interaction: {
- intersect: false,
- axis: 'x',
- },
- color: theme.palette.text.secondary,
- scales: {
- y: {
- type: 'linear',
- grid: {
- color: theme.palette.divider,
- borderColor: theme.palette.divider,
- },
- ticks: { color: theme.palette.text.secondary },
- },
- x: {
- type: 'time',
- time: {
- unit: 'month',
- },
- grid: {
- color: theme.palette.divider,
- borderColor: theme.palette.divider,
- },
- ticks: {
- color: theme.palette.text.secondary,
- },
- },
- },
- }) as const;
-
-interface IFlagsChartComponentProps {
- projectFlagTrends: ExecutiveSummarySchema['projectFlagTrends'];
-}
-
-const FlagsProjectChart: VFC = ({
- projectFlagTrends,
-}) => {
- const theme = useTheme();
- const { locationSettings } = useLocationSettings();
- const data = useMemo(
- () => createData(theme, projectFlagTrends),
- [theme, projectFlagTrends],
- );
- const options = createOptions(theme, locationSettings);
-
- return (
- ({ padding: theme.spacing(4) })}>
- ({ marginBottom: theme.spacing(3) })}
- >
- Number of flags per project
-
-
-
- );
-};
-
-ChartJS.register(
- CategoryScale,
- LinearScale,
- PointElement,
- LineElement,
- TimeScale,
- Title,
- Tooltip,
- Legend,
-);
-
-export default FlagsProjectChart;