From 4e4950adb7f93e77624b7ff47e6dbdb269383180 Mon Sep 17 00:00:00 2001 From: Mateusz Kwasniewski Date: Thu, 4 Sep 2025 15:09:49 +0200 Subject: [PATCH] feat: grid layout for flag impact metrics (#10619) --- .../FeatureMetrics/FeatureImpactMetrics.tsx | 41 +++++++++++++------ .../component/impact-metrics/ChartItem.tsx | 20 ++------- .../impact-metrics/ImpactMetrics.tsx | 21 +++++++++- 3 files changed, 52 insertions(+), 30 deletions(-) diff --git a/frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureImpactMetrics.tsx b/frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureImpactMetrics.tsx index 8a7f6960b6..d5c92a75b6 100644 --- a/frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureImpactMetrics.tsx +++ b/frontend/src/component/feature/FeatureView/FeatureMetrics/FeatureImpactMetrics.tsx @@ -9,6 +9,10 @@ import { useImpactMetricsApi } from 'hooks/api/actions/useImpactMetricsSettingsA import { useRequiredPathParam } from 'hooks/useRequiredPathParam.ts'; import { useFeatureImpactMetrics } from 'hooks/api/getters/useFeatureImpactMetrics/useFeatureImpactMetrics.ts'; import { ChartItem } from '../../../impact-metrics/ChartItem.tsx'; +import { + GridLayoutWrapper, + type GridItem, +} from '../../../impact-metrics/GridLayoutWrapper.tsx'; import PermissionButton from 'component/common/PermissionButton/PermissionButton.tsx'; import { UPDATE_FEATURE } from 'component/providers/AccessProvider/permissions.ts'; import useToast from 'hooks/useToast.tsx'; @@ -98,6 +102,28 @@ export const FeatureImpactMetrics: FC = () => { const editingChart = modalState.type === 'editing' ? modalState.config : undefined; + const gridItems: GridItem[] = useMemo( + () => + impactMetrics.configs.map((config, index) => ({ + id: config.id, + component: ( + handleEditChart(config)} + onDelete={() => handleDeleteChart(config.id)} + permission={UPDATE_FEATURE} + projectId={project} + /> + ), + w: 6, + h: 2, + x: (index % 2) * 6, + y: Math.floor(index / 2) * 2, + static: true, + })), + [impactMetrics.configs, project], + ); + return ( { } /> - <> - {impactMetrics.configs.map((config) => ( - handleEditChart(config)} - onDelete={() => handleDeleteChart(config.id)} - permission={UPDATE_FEATURE} - projectId={project} - /> - ))} - + {impactMetrics.configs.length > 0 && ( + + )} void; permission?: string; projectId?: string; + dragHandle?: React.ReactNode; } const getConfigDescription = (config: DisplayChartConfig): string => { @@ -77,19 +77,6 @@ const StyledHeader = styled(Box)(({ theme }) => ({ 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 StyledChartTitle = styled(Box)(({ theme }) => ({ display: 'flex', flexDirection: 'column', @@ -112,12 +99,11 @@ export const ChartItem: FC = ({ onDelete, permission = ADMIN, projectId, + dragHandle, }) => ( - - - + {dragHandle} {config.title && ( {config.title} diff --git a/frontend/src/component/impact-metrics/ImpactMetrics.tsx b/frontend/src/component/impact-metrics/ImpactMetrics.tsx index 1b636f0993..4e7c2eba6a 100644 --- a/frontend/src/component/impact-metrics/ImpactMetrics.tsx +++ b/frontend/src/component/impact-metrics/ImpactMetrics.tsx @@ -1,7 +1,8 @@ import type { FC } from 'react'; import { useMemo, useState, useCallback } from 'react'; -import { Typography, Button, Paper, styled } from '@mui/material'; +import { Typography, Button, Paper, styled, Box } from '@mui/material'; import Add from '@mui/icons-material/Add'; +import DragHandle from '@mui/icons-material/DragHandle'; import { PageHeader } from 'component/common/PageHeader/PageHeader.tsx'; import { useImpactMetricsMetadata } from 'hooks/api/getters/useImpactMetricsMetadata/useImpactMetricsMetadata'; import { ChartConfigModal } from './ChartConfigModal/ChartConfigModal.tsx'; @@ -22,6 +23,19 @@ const StyledEmptyState = styled(Paper)(({ theme }) => ({ boxShadow: 'none', })); +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 ImpactMetrics: FC = () => { const [modalOpen, setModalOpen] = useState(false); const [editingChart, setEditingChart] = useState(); @@ -112,6 +126,11 @@ export const ImpactMetrics: FC = () => { config={config} onEdit={handleEditChart} onDelete={handleDeleteChart} + dragHandle={ + + + + } /> ), w: existingLayout?.w ?? 6,