From 41e0c3a653e9077dbde8c4525180ca28d8ac6b73 Mon Sep 17 00:00:00 2001 From: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com> Date: Tue, 1 Jul 2025 16:52:29 +0200 Subject: [PATCH] refactor: apply previous pr comments --- .../impact-metrics/ChartConfigModal.tsx | 166 +--------- .../component/impact-metrics/ChartItem.tsx | 305 +++++------------- .../impact-metrics/GridLayoutWrapper.tsx | 13 +- .../impact-metrics/ImpactMetrics.tsx | 4 +- .../impact-metrics/ImpactMetricsChart.tsx | 150 +++++++++ .../ImpactMetricsChartPreview.tsx | 39 +++ .../impact-metrics/ImpactMetricsControls.tsx | 203 ------------ .../impact-metrics/LazyImpactMetricsPage.tsx | 6 +- .../LazyImpactMetricsPageExport.tsx | 3 - ...seUrlState.ts => useImpactMetricsState.ts} | 2 +- .../impact-metrics/hooks/useUrlState.test.tsx | 4 +- 11 files changed, 297 insertions(+), 598 deletions(-) create mode 100644 frontend/src/component/impact-metrics/ImpactMetricsChart.tsx create mode 100644 frontend/src/component/impact-metrics/ImpactMetricsChartPreview.tsx delete mode 100644 frontend/src/component/impact-metrics/ImpactMetricsControls.tsx delete mode 100644 frontend/src/component/impact-metrics/LazyImpactMetricsPageExport.tsx rename frontend/src/component/impact-metrics/hooks/{useUrlState.ts => useImpactMetricsState.ts} (98%) diff --git a/frontend/src/component/impact-metrics/ChartConfigModal.tsx b/frontend/src/component/impact-metrics/ChartConfigModal.tsx index 0acbefe985..83188fac8e 100644 --- a/frontend/src/component/impact-metrics/ChartConfigModal.tsx +++ b/frontend/src/component/impact-metrics/ChartConfigModal.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react'; -import { useState, useEffect, useMemo } from 'react'; +import { useState, useEffect } from 'react'; import { Dialog, DialogTitle, @@ -8,21 +8,11 @@ import { Button, TextField, Box, - Typography, - Alert, styled, } from '@mui/material'; import { ImpactMetricsControls } from './ImpactMetricsControls/ImpactMetricsControls.tsx'; -import { - LineChart, - NotEnoughData, -} from '../insights/components/LineChart/LineChart.tsx'; -import { StyledChartContainer } from 'component/insights/InsightsCharts.styles'; +import { ImpactMetricsChartPreview } from './ImpactMetricsChartPreview.tsx'; import { useImpactMetricsData } from 'hooks/api/getters/useImpactMetricsData/useImpactMetricsData'; -import { usePlaceholderData } from '../insights/hooks/usePlaceholderData.js'; -import { getDisplayFormat, getTimeUnit, formatLargeNumbers } from './utils.ts'; -import { fromUnixTime } from 'date-fns'; -import { useChartData } from './hooks/useChartData.ts'; import type { ChartConfig } from './types.ts'; import type { ImpactMetricsSeries } from 'hooks/api/getters/useImpactMetricsMetadata/useImpactMetricsMetadata'; @@ -82,25 +72,6 @@ export const ChartConfigModal: FC = ({ Record >(initialConfig?.selectedLabels || {}); - // Data for preview - const { - data: { start, end, series: timeSeriesData }, - loading: dataLoading, - error: dataError, - } = useImpactMetricsData( - selectedSeries - ? { - series: selectedSeries, - range: selectedRange, - labels: - Object.keys(selectedLabels).length > 0 - ? selectedLabels - : undefined, - } - : undefined, - ); - - // Fetch available labels for the currently selected series const { data: { labels: currentAvailableLabels }, } = useImpactMetricsData( @@ -112,40 +83,6 @@ export const ChartConfigModal: FC = ({ : undefined, ); - const placeholderData = usePlaceholderData({ - fill: true, - type: 'constant', - }); - - const data = useChartData(timeSeriesData); - - const hasError = !!dataError; - const isLoading = dataLoading; - const shouldShowPlaceholder = !selectedSeries || isLoading || hasError; - const notEnoughData = useMemo( - () => - !isLoading && - (!timeSeriesData || - timeSeriesData.length === 0 || - !data.datasets.some((d) => d.data.length > 1)), - [data, isLoading, timeSeriesData], - ); - - const minTime = start - ? fromUnixTime(Number.parseInt(start, 10)) - : undefined; - const maxTime = end ? fromUnixTime(Number.parseInt(end, 10)) : undefined; - - const placeholder = selectedSeries ? ( - - ) : ( - - ); - const cover = notEnoughData ? placeholder : isLoading; - useEffect(() => { if (open && initialConfig) { setTitle(initialConfig.title || ''); @@ -232,100 +169,13 @@ export const ChartConfigModal: FC = ({ availableLabels={currentAvailableLabels} /> - - {/* Preview Panel */} - - Preview - - - {!selectedSeries && !isLoading ? ( - - Select a metric series to view the preview - - ) : null} - - - {hasError ? ( - - Failed to load impact metrics. Please check - if Prometheus is configured and the feature - flag is enabled. - - ) : null} - - typeof value === - 'number' - ? formatLargeNumbers( - value, - ) - : (value as number), - }, - }, - }, - plugins: { - legend: { - display: - timeSeriesData && - timeSeriesData.length > - 1, - position: - 'bottom' as const, - labels: { - usePointStyle: true, - boxWidth: 8, - padding: 12, - }, - }, - }, - animations: { - x: { duration: 0 }, - y: { duration: 0 }, - }, - } - } - cover={cover} - /> - + diff --git a/frontend/src/component/impact-metrics/ChartItem.tsx b/frontend/src/component/impact-metrics/ChartItem.tsx index 94acbb797d..a8d7daa51a 100644 --- a/frontend/src/component/impact-metrics/ChartItem.tsx +++ b/frontend/src/component/impact-metrics/ChartItem.tsx @@ -1,25 +1,9 @@ import type { FC } from 'react'; -import { useMemo } from 'react'; -import { - Box, - Typography, - IconButton, - Alert, - styled, - Paper, -} from '@mui/material'; +import { Box, Typography, IconButton, styled, Paper } from '@mui/material'; import Edit from '@mui/icons-material/Edit'; import Delete from '@mui/icons-material/Delete'; import DragHandle from '@mui/icons-material/DragHandle'; -import { - LineChart, - NotEnoughData, -} from '../insights/components/LineChart/LineChart.tsx'; -import { useImpactMetricsData } from 'hooks/api/getters/useImpactMetricsData/useImpactMetricsData'; -import { usePlaceholderData } from '../insights/hooks/usePlaceholderData.js'; -import { getDisplayFormat, getTimeUnit, formatLargeNumbers } from './utils.ts'; -import { fromUnixTime } from 'date-fns'; -import { useChartData } from './hooks/useChartData.ts'; +import { ImpactMetricsChart } from './ImpactMetricsChart.tsx'; import type { ChartConfig } from './types.ts'; export interface ChartItemProps { @@ -32,46 +16,30 @@ const getConfigDescription = (config: ChartConfig): string => { const parts: string[] = []; if (config.selectedSeries) { - parts.push(`Series: ${config.selectedSeries}`); + parts.push(`${config.selectedSeries}`); } - parts.push(`Time range: last ${config.selectedRange}`); - - if (config.beginAtZero) { - parts.push('Begin at zero'); - } + parts.push(`last ${config.selectedRange}`); const labelCount = Object.keys(config.selectedLabels).length; if (labelCount > 0) { - parts.push(`${labelCount} label filter${labelCount > 1 ? 's' : ''}`); + parts.push(`${labelCount} filter${labelCount > 1 ? 's' : ''}`); } return parts.join(' • '); }; -const StyledHeader = styled(Box)(({ theme }) => ({ - display: 'flex', - justifyContent: 'space-between', - alignItems: 'flex-start', - padding: theme.spacing(2, 3), - borderBottom: `1px solid ${theme.palette.divider}`, -})); - -const StyledDragHandle = styled(Box)(({ theme }) => ({ - display: 'flex', - alignItems: 'center', - cursor: 'move', - padding: theme.spacing(0.5), - borderRadius: theme.shape.borderRadius, - color: theme.palette.text.secondary, - '&:hover': { - backgroundColor: theme.palette.action.hover, - color: theme.palette.text.primary, +const StyledChartWrapper = styled(Box)({ + height: '100%', + width: '100%', + '& > div': { + height: '100% !important', + width: '100% !important', }, -})); +}); const StyledWidget = styled(Paper)(({ theme }) => ({ - borderRadius: `${theme.shape.borderRadiusLarge}px`, + borderRadius: `${theme.shape.borderRadiusMedium}px`, boxShadow: 'none', display: 'flex', flexDirection: 'column', @@ -97,182 +65,81 @@ const StyledImpactChartContainer = styled(Box)(({ theme }) => ({ padding: theme.spacing(3), })); -const StyledChartWrapper = styled(Box)({ - height: '100%', - width: '100%', - '& > div': { - height: '100% !important', - width: '100% !important', +const StyledHeader = styled(Box)(({ theme }) => ({ + display: 'flex', + gap: theme.spacing(2), + alignItems: 'center', + padding: theme.spacing(1.5, 2), + borderBottom: `1px solid ${theme.palette.divider}`, +})); + +const StyledDragHandle = styled(Box)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + cursor: 'move', + padding: theme.spacing(0.5), + borderRadius: theme.shape.borderRadius, + color: theme.palette.text.secondary, + '&:hover': { + backgroundColor: theme.palette.action.hover, + color: theme.palette.text.primary, }, -}); +})); -export const ChartItem: FC = ({ config, onEdit, onDelete }) => { - const { - data: { start, end, series: timeSeriesData }, - loading: dataLoading, - error: dataError, - } = useImpactMetricsData({ - series: config.selectedSeries, - range: config.selectedRange, - labels: - Object.keys(config.selectedLabels).length > 0 - ? config.selectedLabels - : undefined, - }); +const StyledChartTitle = styled(Box)(({ theme }) => ({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'flex-end', + flexGrow: 1, + overflow: 'hidden', + textOverflow: 'ellipsis', +})); - const placeholderData = usePlaceholderData({ - fill: true, - type: 'constant', - }); +const StyledChartActions = styled(Box)(({ theme }) => ({ + marginLeft: 'auto', + display: 'flex', + alignItems: 'center', + gap: theme.spacing(0.5), +})); - const data = useChartData(timeSeriesData); +export const ChartItem: FC = ({ config, onEdit, onDelete }) => ( + + + + + + + {config.title && ( + {config.title} + )} + + {getConfigDescription(config)} + + + + onEdit(config)}> + + + onDelete(config.id)}> + + + + - const hasError = !!dataError; - const isLoading = dataLoading; - const shouldShowPlaceholder = isLoading || hasError; - const notEnoughData = useMemo( - () => - !isLoading && - (!timeSeriesData || - timeSeriesData.length === 0 || - !data.datasets.some((d) => d.data.length > 1)), - [data, isLoading, timeSeriesData], - ); - - const minTime = start - ? fromUnixTime(Number.parseInt(start, 10)) - : undefined; - const maxTime = end ? fromUnixTime(Number.parseInt(end, 10)) : undefined; - - const placeholder = ( - - ); - const cover = notEnoughData ? placeholder : isLoading; - - return ( - - - - - - - - {config.title && ( - - {config.title} - - )} - - {getConfigDescription(config)} - - - - - onEdit(config)} - size='small' - sx={{ mr: 1 }} - > - - - onDelete(config.id)} - size='small' - > - - - - - - - - {hasError ? ( - - Failed to load impact metrics. Please check if - Prometheus is configured and the feature flag is - enabled. - - ) : null} - - - typeof value === - 'number' - ? formatLargeNumbers( - value, - ) - : (value as number), - }, - }, - }, - plugins: { - legend: { - display: - timeSeriesData && - timeSeriesData.length > 1, - position: 'bottom' as const, - labels: { - usePointStyle: true, - boxWidth: 8, - padding: 12, - }, - }, - }, - animations: { - x: { duration: 0 }, - y: { duration: 0 }, - }, - } - } - cover={cover} - /> - - - - - ); -}; + + + + + + + + +); diff --git a/frontend/src/component/impact-metrics/GridLayoutWrapper.tsx b/frontend/src/component/impact-metrics/GridLayoutWrapper.tsx index 1e0a6d8844..5fdc0365f6 100644 --- a/frontend/src/component/impact-metrics/GridLayoutWrapper.tsx +++ b/frontend/src/component/impact-metrics/GridLayoutWrapper.tsx @@ -15,7 +15,7 @@ const StyledGridContainer = styled('div')(({ theme }) => ({ '& .react-grid-item': { transition: 'all 200ms ease', border: `1px solid ${theme.palette.divider}`, - borderRadius: theme.shape.borderRadius, + borderRadius: `${theme.shape.borderRadiusMedium}px`, backgroundColor: theme.palette.background.paper, overflow: 'hidden', '&.react-grid-item--placeholder': { @@ -44,16 +44,15 @@ const StyledGridContainer = styled('div')(({ theme }) => ({ }, '& .react-resizable-handle': { position: 'absolute', - width: '20px', - height: '20px', + width: theme.spacing(3), + height: theme.spacing(3), bottom: '0px', right: '0px', cursor: 'se-resize', - backgroundImage: `url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMgMTdMMTcgM00zIDEzTDEzIDNNNyAxN0wxNyA3IiBzdHJva2U9IiM5OTkiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cjwvc3ZnPgo=')`, backgroundRepeat: 'no-repeat', backgroundPosition: 'center', - '&:hover': { - backgroundImage: `url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAiIGhlaWdodD0iMjAiIHZpZXdCb3g9IjAgMCAyMCAyMCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMgMTdMMTcgM00zIDEzTDEzIDNNNyAxN0wxNyA3IiBzdHJva2U9IiMzMzMiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIi8+Cjwvc3ZnPgo=')`, + '&::after': { + display: 'none', }, }, })); @@ -93,7 +92,6 @@ export const GridLayoutWrapper: FC = ({ isResizable = true, compactType = 'vertical', }) => { - // Memoize layouts to prevent unnecessary re-renders const layouts = useMemo(() => { const baseLayout = items.map((item, index) => ({ i: item.id, @@ -133,7 +131,6 @@ export const GridLayoutWrapper: FC = ({ }; }, [items, cols]); - // Memoize children to improve performance const children = useMemo( () => items.map((item) =>
{item.component}
), [items], diff --git a/frontend/src/component/impact-metrics/ImpactMetrics.tsx b/frontend/src/component/impact-metrics/ImpactMetrics.tsx index 503746a3fa..0d54641acc 100644 --- a/frontend/src/component/impact-metrics/ImpactMetrics.tsx +++ b/frontend/src/component/impact-metrics/ImpactMetrics.tsx @@ -7,7 +7,7 @@ import { useImpactMetricsMetadata } from 'hooks/api/getters/useImpactMetricsMeta import { ChartConfigModal } from './ChartConfigModal.tsx'; import { ChartItem } from './ChartItem.tsx'; import { GridLayoutWrapper, type GridItem } from './GridLayoutWrapper.tsx'; -import { useUrlState } from './hooks/useUrlState.ts'; +import { useImpactMetricsState } from './hooks/useImpactMetricsState.ts'; import type { ChartConfig, LayoutItem } from './types.ts'; const StyledEmptyState = styled(Paper)(({ theme }) => ({ @@ -23,7 +23,7 @@ export const ImpactMetrics: FC = () => { const [editingChart, setEditingChart] = useState(); const { charts, layout, addChart, updateChart, deleteChart, updateLayout } = - useUrlState(); + useImpactMetricsState(); const { metadata, diff --git a/frontend/src/component/impact-metrics/ImpactMetricsChart.tsx b/frontend/src/component/impact-metrics/ImpactMetricsChart.tsx new file mode 100644 index 0000000000..a28ec3060f --- /dev/null +++ b/frontend/src/component/impact-metrics/ImpactMetricsChart.tsx @@ -0,0 +1,150 @@ +import type { FC, ReactNode } from 'react'; +import { useMemo } from 'react'; +import { Alert } from '@mui/material'; +import { + LineChart, + NotEnoughData, +} from '../insights/components/LineChart/LineChart.tsx'; +import { useImpactMetricsData } from 'hooks/api/getters/useImpactMetricsData/useImpactMetricsData'; +import { usePlaceholderData } from '../insights/hooks/usePlaceholderData.js'; +import { getDisplayFormat, getTimeUnit, formatLargeNumbers } from './utils.ts'; +import { fromUnixTime } from 'date-fns'; +import { useChartData } from './hooks/useChartData.ts'; + +type ImpactMetricsChartProps = { + selectedSeries: string; + selectedRange: 'hour' | 'day' | 'week' | 'month'; + selectedLabels: Record; + beginAtZero: boolean; + aspectRatio?: number; + overrideOptions?: Record; + errorTitle?: string; + emptyDataDescription?: string; + noSeriesPlaceholder?: ReactNode; +}; + +export const ImpactMetricsChart: FC = ({ + selectedSeries, + selectedRange, + selectedLabels, + beginAtZero, + aspectRatio, + overrideOptions = {}, + errorTitle = 'Failed to load impact metrics. Please check if Prometheus is configured and the feature flag is enabled.', + emptyDataDescription = 'Send impact metrics using Unleash SDK and select data series to view the chart.', + noSeriesPlaceholder, +}) => { + const { + data: { start, end, series: timeSeriesData }, + loading: dataLoading, + error: dataError, + } = useImpactMetricsData( + selectedSeries + ? { + series: selectedSeries, + range: selectedRange, + labels: + Object.keys(selectedLabels).length > 0 + ? selectedLabels + : undefined, + } + : undefined, + ); + + const placeholderData = usePlaceholderData({ + fill: true, + type: 'constant', + }); + + const data = useChartData(timeSeriesData); + + const hasError = !!dataError; + const isLoading = dataLoading; + const shouldShowPlaceholder = !selectedSeries || isLoading || hasError; + const notEnoughData = useMemo( + () => + !isLoading && + (!timeSeriesData || + timeSeriesData.length === 0 || + !data.datasets.some((d) => d.data.length > 1)), + [data, isLoading, timeSeriesData], + ); + + const minTime = start + ? fromUnixTime(Number.parseInt(start, 10)) + : undefined; + const maxTime = end ? fromUnixTime(Number.parseInt(end, 10)) : undefined; + + const placeholder = selectedSeries ? ( + + ) : noSeriesPlaceholder ? ( + noSeriesPlaceholder + ) : ( + + ); + const cover = notEnoughData ? placeholder : isLoading; + + const chartOptions = shouldShowPlaceholder + ? overrideOptions + : { + ...overrideOptions, + scales: { + x: { + type: 'time', + min: minTime?.getTime(), + max: maxTime?.getTime(), + time: { + unit: getTimeUnit(selectedRange), + displayFormats: { + [getTimeUnit(selectedRange)]: + getDisplayFormat(selectedRange), + }, + tooltipFormat: 'PPpp', + }, + }, + y: { + beginAtZero, + title: { + display: false, + }, + ticks: { + precision: 0, + callback: (value: unknown): string | number => + typeof value === 'number' + ? formatLargeNumbers(value) + : (value as number), + }, + }, + }, + plugins: { + legend: { + display: timeSeriesData && timeSeriesData.length > 1, + position: 'bottom' as const, + labels: { + usePointStyle: true, + boxWidth: 8, + padding: 12, + }, + }, + }, + animations: { + x: { duration: 0 }, + y: { duration: 0 }, + }, + }; + + return ( + <> + {hasError ? {errorTitle} : null} + + + ); +}; diff --git a/frontend/src/component/impact-metrics/ImpactMetricsChartPreview.tsx b/frontend/src/component/impact-metrics/ImpactMetricsChartPreview.tsx new file mode 100644 index 0000000000..087c9b80ee --- /dev/null +++ b/frontend/src/component/impact-metrics/ImpactMetricsChartPreview.tsx @@ -0,0 +1,39 @@ +import type { FC } from 'react'; +import { Typography } from '@mui/material'; +import { StyledChartContainer } from 'component/insights/InsightsCharts.styles'; +import { ImpactMetricsChart } from './ImpactMetricsChart.tsx'; + +type ImpactMetricsChartPreviewProps = { + selectedSeries: string; + selectedRange: 'hour' | 'day' | 'week' | 'month'; + selectedLabels: Record; + beginAtZero: boolean; +}; + +export const ImpactMetricsChartPreview: FC = ({ + selectedSeries, + selectedRange, + selectedLabels, + beginAtZero, +}) => ( + <> + + Preview + + + {!selectedSeries ? ( + + Select a metric series to view the preview + + ) : null} + + + + + +); diff --git a/frontend/src/component/impact-metrics/ImpactMetricsControls.tsx b/frontend/src/component/impact-metrics/ImpactMetricsControls.tsx deleted file mode 100644 index e658970d7c..0000000000 --- a/frontend/src/component/impact-metrics/ImpactMetricsControls.tsx +++ /dev/null @@ -1,203 +0,0 @@ -import type { FC } from 'react'; -import { - FormControl, - InputLabel, - Select, - MenuItem, - FormControlLabel, - Checkbox, - Box, - Autocomplete, - TextField, - Typography, - Chip, -} from '@mui/material'; -import type { ImpactMetricsSeries } from 'hooks/api/getters/useImpactMetricsMetadata/useImpactMetricsMetadata'; -import type { ImpactMetricsLabels } from 'hooks/api/getters/useImpactMetricsData/useImpactMetricsData'; -import { Highlighter } from 'component/common/Highlighter/Highlighter'; - -export interface ImpactMetricsControlsProps { - selectedSeries: string; - onSeriesChange: (series: string) => void; - selectedRange: 'hour' | 'day' | 'week' | 'month'; - onRangeChange: (range: 'hour' | 'day' | 'week' | 'month') => void; - beginAtZero: boolean; - onBeginAtZeroChange: (beginAtZero: boolean) => void; - metricSeries: (ImpactMetricsSeries & { name: string })[]; - loading?: boolean; - selectedLabels: Record; - onLabelsChange: (labels: Record) => void; - availableLabels?: ImpactMetricsLabels; -} - -export const ImpactMetricsControls: FC = ({ - selectedSeries, - onSeriesChange, - selectedRange, - onRangeChange, - beginAtZero, - onBeginAtZeroChange, - metricSeries, - loading = false, - selectedLabels, - onLabelsChange, - availableLabels, -}) => { - const handleLabelChange = (labelKey: string, values: string[]) => { - const newLabels = { ...selectedLabels }; - if (values.length === 0) { - delete newLabels[labelKey]; - } else { - newLabels[labelKey] = values; - } - onLabelsChange(newLabels); - }; - - const clearAllLabels = () => { - onLabelsChange({}); - }; - - return ( - ({ - display: 'flex', - flexDirection: 'column', - gap: theme.spacing(3), - maxWidth: 400, - })} - > - - Select a custom metric to see its value over time. This can help - you understand the impact of your feature rollout on key - outcomes, such as system performance, usage patterns or error - rates. - - - option.name} - value={ - metricSeries.find( - (option) => option.name === selectedSeries, - ) || null - } - onChange={(_, newValue) => onSeriesChange(newValue?.name || '')} - disabled={loading} - renderOption={(props, option, { inputValue }) => ( - - - - - {option.name} - - - - - {option.help} - - - - - )} - renderInput={(params) => ( - - )} - noOptionsText='No metrics available' - sx={{ minWidth: 300 }} - /> - - - Time - - - - onBeginAtZeroChange(e.target.checked)} - /> - } - label='Begin at zero' - /> - {availableLabels && Object.keys(availableLabels).length > 0 ? ( - - - - Filter by labels - - {Object.keys(selectedLabels).length > 0 && ( - - )} - - - {Object.entries(availableLabels).map( - ([labelKey, values]) => ( - - handleLabelChange(labelKey, newValues) - } - renderTags={(value, getTagProps) => - value.map((option, index) => { - const { key, ...chipProps } = - getTagProps({ index }); - return ( - - ); - }) - } - renderInput={(params) => ( - - )} - sx={{ minWidth: 300 }} - /> - ), - )} - - ) : null} - - ); -}; diff --git a/frontend/src/component/impact-metrics/LazyImpactMetricsPage.tsx b/frontend/src/component/impact-metrics/LazyImpactMetricsPage.tsx index 078c80812d..6d9b9d3422 100644 --- a/frontend/src/component/impact-metrics/LazyImpactMetricsPage.tsx +++ b/frontend/src/component/impact-metrics/LazyImpactMetricsPage.tsx @@ -1,5 +1,7 @@ import { lazy } from 'react'; -export const LazyImpactMetricsPage = lazy( - () => import('./LazyImpactMetricsPageExport.tsx'), +export const LazyImpactMetricsPage = lazy(() => + import('./ImpactMetricsPage.tsx').then((module) => ({ + default: module.ImpactMetricsPage, + })), ); diff --git a/frontend/src/component/impact-metrics/LazyImpactMetricsPageExport.tsx b/frontend/src/component/impact-metrics/LazyImpactMetricsPageExport.tsx deleted file mode 100644 index fd5fd1e6c3..0000000000 --- a/frontend/src/component/impact-metrics/LazyImpactMetricsPageExport.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { ImpactMetricsPage } from './ImpactMetricsPage.tsx'; - -export default ImpactMetricsPage; diff --git a/frontend/src/component/impact-metrics/hooks/useUrlState.ts b/frontend/src/component/impact-metrics/hooks/useImpactMetricsState.ts similarity index 98% rename from frontend/src/component/impact-metrics/hooks/useUrlState.ts rename to frontend/src/component/impact-metrics/hooks/useImpactMetricsState.ts index fc2e851ec4..58069dba09 100644 --- a/frontend/src/component/impact-metrics/hooks/useUrlState.ts +++ b/frontend/src/component/impact-metrics/hooks/useImpactMetricsState.ts @@ -20,7 +20,7 @@ const createArrayParam = () => ({ const ChartsParam = createArrayParam(); const LayoutParam = createArrayParam(); -export const useUrlState = () => { +export const useImpactMetricsState = () => { const stateConfig = { charts: withDefault(ChartsParam, []), layout: withDefault(LayoutParam, []), diff --git a/frontend/src/component/impact-metrics/hooks/useUrlState.test.tsx b/frontend/src/component/impact-metrics/hooks/useUrlState.test.tsx index 2a9fb7b00b..37e17e76b5 100644 --- a/frontend/src/component/impact-metrics/hooks/useUrlState.test.tsx +++ b/frontend/src/component/impact-metrics/hooks/useUrlState.test.tsx @@ -1,12 +1,12 @@ import { render } from 'utils/testRenderer'; -import { useUrlState } from './useUrlState.ts'; +import { useImpactMetricsState } from './useImpactMetricsState.ts'; import { Route, Routes } from 'react-router-dom'; import { createLocalStorage } from '../../../utils/createLocalStorage.ts'; import type { FC } from 'react'; import type { ImpactMetricsState } from '../types.ts'; const TestComponent: FC = () => { - const { charts, layout } = useUrlState(); + const { charts, layout } = useImpactMetricsState(); return (