diff --git a/frontend/src/component/insights/InsightsCharts.tsx b/frontend/src/component/insights/InsightsCharts.tsx deleted file mode 100644 index 9656343411..0000000000 --- a/frontend/src/component/insights/InsightsCharts.tsx +++ /dev/null @@ -1,307 +0,0 @@ -import type { FC } from 'react'; -import { Box, Paper, styled } from '@mui/material'; -import { UserStats } from './componentsStat/UserStats/UserStats.tsx'; -import { UsersChart } from './componentsChart/UsersChart/UsersChart.tsx'; -import { UsersPerProjectChart } from './componentsChart/UsersPerProjectChart/UsersPerProjectChart.tsx'; -import { FlagStats } from './componentsStat/FlagStats/FlagStats.tsx'; -import { FlagsChart } from './componentsChart/FlagsChart/FlagsChart.tsx'; -import { FlagsProjectChart } from './componentsChart/FlagsProjectChart/FlagsProjectChart.tsx'; -import { HealthStats } from './componentsStat/HealthStats/HealthStats.tsx'; -import { ProjectHealthChart } from './componentsChart/ProjectHealthChart/ProjectHealthChart.tsx'; -import { TimeToProduction } from './componentsStat/TimeToProduction/TimeToProduction.tsx'; -import { TimeToProductionChart } from './componentsChart/TimeToProductionChart/TimeToProductionChart.tsx'; -import { MetricsSummaryChart } from './componentsChart/MetricsSummaryChart/MetricsSummaryChart.tsx'; -import { UpdatesPerEnvironmentTypeChart } from './componentsChart/UpdatesPerEnvironmentTypeChart/UpdatesPerEnvironmentTypeChart.tsx'; -import type { InstanceInsightsSchema } from 'openapi'; -import type { GroupedDataByProject } from './hooks/useGroupedProjectTrends.ts'; -import { allOption } from 'component/common/ProjectSelect/ProjectSelect'; -import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; -import { WidgetTitle } from './components/WidgetTitle/WidgetTitle.tsx'; -import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; - -export interface IChartsProps { - flagTrends: InstanceInsightsSchema['flagTrends']; - projectsData: InstanceInsightsSchema['projectFlagTrends']; - groupedProjectsData: GroupedDataByProject< - InstanceInsightsSchema['projectFlagTrends'] - >; - metricsData: InstanceInsightsSchema['metricsSummaryTrends']; - groupedMetricsData: GroupedDataByProject< - InstanceInsightsSchema['metricsSummaryTrends'] - >; - userTrends: InstanceInsightsSchema['userTrends']; - environmentTypeTrends: InstanceInsightsSchema['environmentTypeTrends']; - lifecycleTrends: InstanceInsightsSchema['lifecycleTrends']; - summary: { - total: number; - active: number; - stale: number; - potentiallyStale: number; - averageUsers: number; - averageHealth?: string; - technicalDebt?: string; - flagsPerUser?: string; - medianTimeToProduction?: number; - }; - loading: boolean; - projects: string[]; - allMetricsDatapoints: string[]; -} - -const StyledContainer = styled(Box)(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', - gap: theme.spacing(2), -})); - -const StyledWidget = styled(Paper)(({ theme }) => ({ - borderRadius: `${theme.shape.borderRadiusLarge}px`, - boxShadow: 'none', - display: 'flex', - flexWrap: 'wrap', - [theme.breakpoints.up('md')]: { - flexDirection: 'row', - flexWrap: 'nowrap', - }, -})); - -const StyledWidgetContent = styled(Box)(({ theme }) => ({ - padding: theme.spacing(3), - width: '100%', -})); - -const StyledWidgetStats = styled(Box)<{ width?: number; padding?: number }>( - ({ theme, width = 300, padding = 3 }) => ({ - display: 'flex', - flexDirection: 'column', - gap: theme.spacing(2), - padding: theme.spacing(padding), - minWidth: '100%', - [theme.breakpoints.up('md')]: { - minWidth: `${width}px`, - borderRight: `1px solid ${theme.palette.background.application}`, - }, - }), -); - -const StyledChartContainer = styled(Box)(({ theme }) => ({ - position: 'relative', - minWidth: 0, // bugfix, see: https://github.com/chartjs/Chart.js/issues/4156#issuecomment-295180128 - flexGrow: 1, - margin: 'auto 0', - padding: theme.spacing(3), -})); - -export const InsightsCharts: FC = ({ - projects, - summary, - userTrends, - groupedProjectsData, - flagTrends, - groupedMetricsData, - environmentTypeTrends, - allMetricsDatapoints, - loading, -}) => { - const showAllProjects = projects[0] === allOption.id; - const isOneProjectSelected = projects.length === 1; - const { isEnterprise } = useUiConfig(); - - const lastUserTrend = userTrends[userTrends.length - 1]; - const lastFlagTrend = flagTrends[flagTrends.length - 1]; - - const usersTotal = lastUserTrend?.total ?? 0; - const usersActive = lastUserTrend?.active ?? 0; - const usersInactive = lastUserTrend?.inactive ?? 0; - const flagsTotal = lastFlagTrend?.total ?? 0; - - function getFlagsPerUser(flagsTotal: number, usersTotal: number) { - const flagsPerUserCalculation = flagsTotal / usersTotal; - return Number.isNaN(flagsPerUserCalculation) - ? 'N/A' - : flagsPerUserCalculation.toFixed(2); - } - - return ( - - - - - - - - - - - } - elseShow={ - - - - - - - - - - } - /> - - - - - } - /> - - - - - - - - - - - - - - - - } - /> - - - - - - - - - - } - elseShow={ - - - - - - - - - - } - /> - - - - - - - - - - - - - - - - - } - /> - - ); -}; diff --git a/frontend/src/component/insights/components/Gauge/Gauge.tsx b/frontend/src/component/insights/components/Gauge/Gauge.tsx deleted file mode 100644 index def392ceda..0000000000 --- a/frontend/src/component/insights/components/Gauge/Gauge.tsx +++ /dev/null @@ -1,192 +0,0 @@ -import { Fragment, type VFC } from 'react'; -import { Box, useTheme } from '@mui/material'; -import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; - -const polarToCartesian = ( - centerX: number, - centerY: number, - radius: number, - angleInRadians: number, -) => { - return { - x: centerX + radius * Math.cos(angleInRadians), - y: centerY + radius * Math.sin(angleInRadians), - }; -}; - -const degreesToRadians = (degrees: number) => degrees * (Math.PI / 180); - -const normalizeValue = (value: number, min: number, max: number) => - (value - min) / (max - min); - -const describeArc = (radius: number, startAngle: number, endAngle: number) => { - const start = polarToCartesian(0, 0, radius, endAngle); - const end = polarToCartesian(0, 0, radius, startAngle); - const largeArcFlag = endAngle - startAngle <= Math.PI ? '0' : '1'; - const dSvgAttribute = [ - 'M', - start.x, - start.y, - 'A', - radius, - radius, - 0, - largeArcFlag, - 0, - end.x, - end.y, - ].join(' '); - return dSvgAttribute; -}; - -const GaugeLines = () => { - const theme = useTheme(); - const startRadius = 0.875; - const endRadius = 1.14; - const lineWidth = 0.1; - const lineBorder = 0.05; - - const angles = [180 + 50, 180 + 90 + 40]; - - return ( - <> - {angles.map(degreesToRadians).map((angle) => { - const start = polarToCartesian(0, 0, startRadius, angle); - const end = polarToCartesian(0, 0, endRadius, angle); - - return ( - - - - - ); - })} - - ); -}; - -const GaugeText = () => { - const fontSize = 0.175; - - return ( - <> - - Slow - - - Medium - - - Fast - - - ); -}; - -type GaugeProps = { - value?: number; - min?: number; - max?: number; -}; - -export const Gauge: VFC = ({ value, min = 0, max = 100 }) => { - const theme = useTheme(); - const radius = 1; - const lineWidth = 0.25; - const startAngle = -Math.PI; - const endAngle = 0; - - // Calculate the filled arc proportion based on the value - const valueAngle = - startAngle + - (endAngle - startAngle) * normalizeValue(value || 0, min, max); - - const backgroundArcPath = describeArc(radius, startAngle, endAngle); - const filledArcPath = describeArc(radius, startAngle, valueAngle); - - return ( - - - Gauge chart for time to production - - - - - - - - - } - /> - - - - - ); -}; diff --git a/frontend/src/component/insights/componentsStat/TimeToProduction/TimeToProduction.tsx b/frontend/src/component/insights/componentsStat/TimeToProduction/TimeToProduction.tsx deleted file mode 100644 index bcf8687be5..0000000000 --- a/frontend/src/component/insights/componentsStat/TimeToProduction/TimeToProduction.tsx +++ /dev/null @@ -1,106 +0,0 @@ -import type { VFC } from 'react'; -import { Typography, styled } from '@mui/material'; -import { Gauge } from 'component/insights/components/Gauge/Gauge'; - -const StyledContainer = styled('div')(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - justifyContent: 'center', - gap: theme.spacing(1), - textAlign: 'center', -})); - -const StyledText = styled('div')(({ theme }) => ({ - marginTop: theme.spacing(-7), - display: 'flex', - flexDirection: 'column', -})); - -type TimeToProductionProps = { - daysToProduction: number | undefined; -}; - -const interpolate = ( - value: number, - [fromStart, fromEnd]: [number, number], - [toStart, toEnd]: [number, number], -): number => { - if (value < fromStart) { - return toStart; - } - - if (value > fromEnd) { - return toEnd; - } - - return ( - ((value - fromStart) / (fromEnd - fromStart)) * (toEnd - toStart) + - toStart - ); -}; - -const resolveValue = ( - daysToProduction: number | undefined, -): { - value: string | undefined; - gauge: number | undefined; - score: 'Fast' | 'Medium' | 'Slow' | undefined; -} => { - if (daysToProduction === undefined || daysToProduction === 0) { - return { - value: undefined, - gauge: undefined, - score: undefined, - }; - } - - if (daysToProduction <= 7) { - return { - value: `${daysToProduction.toFixed(1)} days`, - gauge: interpolate(daysToProduction, [1, 7], [100, 75]), - score: 'Fast', - }; - } - - if (daysToProduction <= 31) { - return { - value: `${(daysToProduction / 7).toFixed(1)} weeks`, - gauge: interpolate(daysToProduction, [7, 31], [67.5, 30]), - score: 'Medium', - }; - } - - return { - value: `${(daysToProduction / 30).toFixed(1)} months`, - gauge: interpolate(daysToProduction, [31, 365 / 4], [23, 0]), - score: 'Slow', - }; -}; - -export const TimeToProduction: VFC = ({ - daysToProduction, -}) => { - const { value, gauge, score } = resolveValue(daysToProduction); - - return ( - - - - - {daysToProduction !== undefined ? value : 'N/A'} - - ({ - color: score - ? theme.palette.primary.main - : theme.palette.text.secondary, - })} - > - {score || 'No data'} - - - - ); -}; diff --git a/frontend/src/themes/dark-theme.ts b/frontend/src/themes/dark-theme.ts index 448048eb29..67b61740e5 100644 --- a/frontend/src/themes/dark-theme.ts +++ b/frontend/src/themes/dark-theme.ts @@ -220,25 +220,6 @@ const theme = { * Dashboard and charts */ charts: { - gauge: { - gradientStart: '#4C4992', - gradientEnd: '#9792ED', - background: '#39384C', - sectionLine: '#8c89bf', - text: colors.grey[800], - }, - health: { - mainCircleBackground: '#34325E', - orbit: '#4C4992', - circles: '#2B2A3C', - text: colors.grey[500], - title: colors.grey[50], - healthy: colors.purple[800], - stale: colors.red[800], - potentiallyStale: colors.orange[800], - gradientStale: '#8A3E45', - gradientPotentiallyStale: '#875D21', - }, series: colors.chartSeries, }, }, diff --git a/frontend/src/themes/theme.ts b/frontend/src/themes/theme.ts index 720922d03f..120a3ca5e9 100644 --- a/frontend/src/themes/theme.ts +++ b/frontend/src/themes/theme.ts @@ -276,25 +276,6 @@ const theme = { * Dashboard and charts */ charts: { - gauge: { - gradientStart: colors.purple[100], - gradientEnd: colors.purple[700], - background: colors.purple[50], - sectionLine: colors.purple[500], - text: colors.grey[600], - }, - health: { - mainCircleBackground: colors.purple[800], - orbit: colors.grey[300], - circles: colors.grey[50], - text: colors.grey[900], - title: colors.grey[50], - healthy: colors.purple[800], - stale: colors.red[800], - potentiallyStale: colors.orange[900], - gradientStale: colors.red[300], - gradientPotentiallyStale: colors.orange[500], - }, series: colors.chartSeries, }, }, diff --git a/frontend/src/themes/themeTypes.ts b/frontend/src/themes/themeTypes.ts index 28615b985b..66fe6f520b 100644 --- a/frontend/src/themes/themeTypes.ts +++ b/frontend/src/themes/themeTypes.ts @@ -138,25 +138,6 @@ declare module '@mui/material/styles' { * Dashboard and charts */ charts: { - gauge: { - gradientStart: string; - gradientEnd: string; - background: string; - sectionLine: string; - text: string; - }; - health: { - mainCircleBackground: string; - orbit: string; - circles: string; - text: string; - title: string; - healthy: string; - stale: string; - potentiallyStale: string; - gradientStale: string; - gradientPotentiallyStale: string; - }; series: string[]; }; }