From 96c86b221ba75e44df5183f9d133821372656250 Mon Sep 17 00:00:00 2001 From: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com> Date: Wed, 28 Feb 2024 08:58:27 +0100 Subject: [PATCH] feat: improved health chart tooltip (#6359) --- .../executiveDashboard/ExecutiveDashboard.tsx | 2 +- .../HealthStats/HealthStats.tsx | 10 +- .../HorizontalDistributionChart.tsx | 41 +++++ .../LineChart/ChartTooltip/ChartTooltip.tsx | 37 +++- .../LineChart/LineChartComponent.tsx | 149 +--------------- .../LineChart/createChartOptions.ts | 77 ++++++++ .../LineChart/createTooltip.ts | 29 ++++ .../LineChart/legendOptions.ts | 34 ++++ .../HealthChartTooltip/HealthChartTooltip.tsx | 164 ++++++++++++++++++ .../ProjectHealthChart/ProjectHealthChart.tsx | 75 +------- .../UserStats/UserDistributionInfo.tsx | 78 +++++++++ .../UserStats/UserStats.tsx | 135 ++------------ frontend/src/themes/dark-theme.ts | 4 +- frontend/src/themes/theme.ts | 4 +- frontend/src/themes/themeTypes.ts | 4 +- 15 files changed, 489 insertions(+), 354 deletions(-) create mode 100644 frontend/src/component/executiveDashboard/HorizontalDistributionChart/HorizontalDistributionChart.tsx create mode 100644 frontend/src/component/executiveDashboard/LineChart/createChartOptions.ts create mode 100644 frontend/src/component/executiveDashboard/LineChart/createTooltip.ts create mode 100644 frontend/src/component/executiveDashboard/LineChart/legendOptions.ts create mode 100644 frontend/src/component/executiveDashboard/ProjectHealthChart/HealthChartTooltip/HealthChartTooltip.tsx create mode 100644 frontend/src/component/executiveDashboard/UserStats/UserDistributionInfo.tsx diff --git a/frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx b/frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx index 51dcdf63ff..7eeb912ed9 100644 --- a/frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx +++ b/frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx @@ -178,7 +178,7 @@ export const ExecutiveDashboard: VFC = () => { value={80} healthy={4} stale={1} - potenciallyStale={0} + potentiallyStale={0} /> diff --git a/frontend/src/component/executiveDashboard/HealthStats/HealthStats.tsx b/frontend/src/component/executiveDashboard/HealthStats/HealthStats.tsx index b742e636ee..5817fcdccd 100644 --- a/frontend/src/component/executiveDashboard/HealthStats/HealthStats.tsx +++ b/frontend/src/component/executiveDashboard/HealthStats/HealthStats.tsx @@ -6,14 +6,14 @@ interface IHealthStatsProps { value: number; healthy: number; stale: number; - potenciallyStale: number; + potentiallyStale: number; } export const HealthStats: VFC = ({ value, healthy, stale, - potenciallyStale, + potentiallyStale, }) => { const { themeMode } = useThemeMode(); const isDark = themeMode === 'dark'; @@ -116,12 +116,12 @@ export const HealthStats: VFC = ({ - {potenciallyStale || 0} + {potentiallyStale || 0} = ({ diff --git a/frontend/src/component/executiveDashboard/HorizontalDistributionChart/HorizontalDistributionChart.tsx b/frontend/src/component/executiveDashboard/HorizontalDistributionChart/HorizontalDistributionChart.tsx new file mode 100644 index 0000000000..06b0d21860 --- /dev/null +++ b/frontend/src/component/executiveDashboard/HorizontalDistributionChart/HorizontalDistributionChart.tsx @@ -0,0 +1,41 @@ +import { VFC } from 'react'; +import { Box, styled } from '@mui/material'; + +type DistributionLineTypes = 'default' | 'success' | 'warning' | 'error'; + +const StyledDistributionLine = styled(Box)<{ + type: DistributionLineTypes; + size?: 'large' | 'small'; +}>(({ theme, type, size = 'large' }) => { + const color: Record = { + default: theme.palette.secondary.border, + success: theme.palette.success.border, + warning: theme.palette.warning.border, + error: theme.palette.error.border, + }; + + return { + borderRadius: theme.shape.borderRadius, + height: size === 'large' ? theme.spacing(2) : theme.spacing(1), + backgroundColor: color[type], + marginBottom: theme.spacing(0.5), + }; +}); + +export const HorizontalDistributionChart: VFC<{ + sections: Array<{ type: DistributionLineTypes; value: number }>; + size?: 'large' | 'small'; +}> = ({ sections, size }) => ( + ({ display: 'flex', gap: theme.spacing(0.5) })}> + {sections.map((section, index) => + section.value ? ( + + ) : null, + )} + +); diff --git a/frontend/src/component/executiveDashboard/LineChart/ChartTooltip/ChartTooltip.tsx b/frontend/src/component/executiveDashboard/LineChart/ChartTooltip/ChartTooltip.tsx index b189c78747..d0c0732d3d 100644 --- a/frontend/src/component/executiveDashboard/LineChart/ChartTooltip/ChartTooltip.tsx +++ b/frontend/src/component/executiveDashboard/LineChart/ChartTooltip/ChartTooltip.tsx @@ -7,7 +7,7 @@ export type TooltipState = { caretX: number; caretY: number; title: string; - align: 'left' | 'right'; + align: 'left' | 'right' | 'center'; body: { title: string; color: string; @@ -40,22 +40,47 @@ const StyledLabelIcon = styled('span')(({ theme }) => ({ marginRight: theme.spacing(1), })); +const offset = 16; + +const getAlign = (align?: 'left' | 'right' | 'center') => { + if (align === 'left') { + return 'flex-start'; + } + + if (align === 'right') { + return 'flex-end'; + } + + return 'center'; +}; + +const getLeftOffset = (caretX = 0, align?: 'left' | 'right' | 'center') => { + if (align === 'left') { + return caretX + offset; + } + + if (align === 'right') { + return caretX - offset; + } + + return caretX; +}; + export const ChartTooltipContainer: FC = ({ tooltip, children, }) => ( ({ - top: tooltip?.caretY, - left: tooltip?.align === 'left' ? tooltip?.caretX + 20 : 0, - right: - tooltip?.align === 'right' ? tooltip?.caretX + 20 : undefined, + top: (tooltip?.caretY || 0) + offset, + left: getLeftOffset(tooltip?.caretX, tooltip?.align), + width: '1px', position: 'absolute', display: tooltip ? 'flex' : 'none', pointerEvents: 'none', zIndex: theme.zIndex.tooltip, flexDirection: 'column', - alignItems: tooltip?.align === 'left' ? 'flex-start' : 'flex-end', + alignItems: getAlign(tooltip?.align), })} > {children} diff --git a/frontend/src/component/executiveDashboard/LineChart/LineChartComponent.tsx b/frontend/src/component/executiveDashboard/LineChart/LineChartComponent.tsx index e8024032b2..46d1c7b318 100644 --- a/frontend/src/component/executiveDashboard/LineChart/LineChartComponent.tsx +++ b/frontend/src/component/executiveDashboard/LineChart/LineChartComponent.tsx @@ -10,16 +10,12 @@ import { Chart, Filler, type ChartData, - TooltipModel, - ChartOptions, + type ChartOptions, } 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 { useTheme } from '@mui/material'; +import { useLocationSettings } from 'hooks/useLocationSettings'; import { ChartTooltip, ChartTooltipContainer, @@ -27,144 +23,7 @@ import { } from './ChartTooltip/ChartTooltip'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { styled } from '@mui/material'; - -const createTooltip = - (setTooltip: React.Dispatch>) => - (context: { - chart: Chart; - tooltip: TooltipModel; - }) => { - const tooltip = context.tooltip; - if (tooltip.opacity === 0) { - setTooltip(null); - return; - } - - setTooltip({ - caretX: - tooltip?.xAlign === 'right' - ? context.chart.width - tooltip?.caretX - : tooltip?.caretX, - caretY: tooltip?.caretY, - title: tooltip?.title?.join(' ') || '', - align: tooltip?.xAlign === 'right' ? 'right' : 'left', - body: - tooltip?.body?.map((item: any, index: number) => ({ - title: item?.lines?.join(' '), - color: tooltip?.labelColors?.[index]?.borderColor as string, - value: '', - })) || [], - dataPoints: tooltip?.dataPoints || [], - }); - }; - -const createOptions = ( - theme: Theme, - locationSettings: ILocationSettings, - setTooltip: React.Dispatch>, - isPlaceholder?: boolean, - localTooltip?: boolean, -) => - ({ - responsive: true, - ...(isPlaceholder - ? { - animation: { - duration: 0, - }, - } - : {}), - plugins: { - legend: { - display: !isPlaceholder, - position: 'bottom', - labels: { - boxWidth: 12, - padding: 30, - generateLabels: (chart: Chart) => { - const datasets = chart.data.datasets; - const { - labels: { - usePointStyle, - pointStyle, - textAlign, - color, - }, - } = chart?.legend?.options || { - labels: {}, - }; - return (chart as any) - ._getSortedDatasetMetas() - .map((meta: any) => { - const style = meta.controller.getStyle( - usePointStyle ? 0 : undefined, - ); - return { - text: datasets[meta.index].label, - fillStyle: style.backgroundColor, - fontColor: color, - hidden: !meta.visible, - lineWidth: 0, - borderRadius: 6, - strokeStyle: style.borderColor, - pointStyle: pointStyle || style.pointStyle, - textAlign: textAlign || style.textAlign, - datasetIndex: meta.index, - }; - }); - }, - }, - }, - tooltip: { - enabled: false, - external: createTooltip(setTooltip), - }, - }, - locale: locationSettings.locale, - interaction: { - intersect: localTooltip || false, - axis: 'x', - }, - elements: { - point: { - radius: 0, - hitRadius: 15, - }, - }, - // cubicInterpolationMode: 'monotone', - tension: 0.1, - color: theme.palette.text.secondary, - scales: { - y: { - beginAtZero: true, - type: 'linear', - grid: { - color: theme.palette.divider, - borderColor: theme.palette.divider, - }, - ticks: { - color: theme.palette.text.secondary, - display: !isPlaceholder, - precision: 0, - }, - }, - x: { - type: 'time', - time: { - unit: 'day', - tooltipFormat: 'PPP', - }, - grid: { - color: 'transparent', - borderColor: 'transparent', - }, - ticks: { - color: theme.palette.text.secondary, - display: !isPlaceholder, - }, - }, - }, - }) as const; +import { createOptions } from './createChartOptions'; const StyledContainer = styled('div')(({ theme }) => ({ position: 'relative', diff --git a/frontend/src/component/executiveDashboard/LineChart/createChartOptions.ts b/frontend/src/component/executiveDashboard/LineChart/createChartOptions.ts new file mode 100644 index 0000000000..698cf6fa82 --- /dev/null +++ b/frontend/src/component/executiveDashboard/LineChart/createChartOptions.ts @@ -0,0 +1,77 @@ +import { Theme } from '@mui/material'; +import { ILocationSettings } from 'hooks/useLocationSettings'; +import { TooltipState } from './ChartTooltip/ChartTooltip'; +import { createTooltip } from './createTooltip'; +import { legendOptions } from './legendOptions'; + +export const createOptions = ( + theme: Theme, + locationSettings: ILocationSettings, + setTooltip: React.Dispatch>, + isPlaceholder?: boolean, + localTooltip?: boolean, +) => + ({ + responsive: true, + ...(isPlaceholder + ? { + animation: { + duration: 0, + }, + } + : {}), + plugins: { + legend: { + ...legendOptions, + display: !isPlaceholder, + }, + tooltip: { + enabled: false, + external: createTooltip(setTooltip), + }, + }, + locale: locationSettings.locale, + interaction: { + intersect: localTooltip || false, + axis: 'x', + }, + elements: { + point: { + radius: 0, + hitRadius: 15, + }, + }, + // cubicInterpolationMode: 'monotone', + tension: 0.1, + color: theme.palette.text.secondary, + scales: { + y: { + beginAtZero: true, + type: 'linear', + grid: { + color: theme.palette.divider, + borderColor: theme.palette.divider, + }, + ticks: { + color: theme.palette.text.secondary, + display: !isPlaceholder, + precision: 0, + }, + }, + x: { + type: 'time', + time: { + unit: 'day', + tooltipFormat: 'PPP', + }, + grid: { + color: 'transparent', + borderColor: 'transparent', + }, + ticks: { + color: theme.palette.text.secondary, + display: !isPlaceholder, + }, + }, + }, + }) as const; diff --git a/frontend/src/component/executiveDashboard/LineChart/createTooltip.ts b/frontend/src/component/executiveDashboard/LineChart/createTooltip.ts new file mode 100644 index 0000000000..6bdf661ad1 --- /dev/null +++ b/frontend/src/component/executiveDashboard/LineChart/createTooltip.ts @@ -0,0 +1,29 @@ +import { type Chart, type TooltipModel } from 'chart.js'; +import { type TooltipState } from './ChartTooltip/ChartTooltip'; + +export const createTooltip = + (setTooltip: React.Dispatch>) => + (context: { + chart: Chart; + tooltip: TooltipModel; + }) => { + const tooltip = context.tooltip; + if (tooltip.opacity === 0) { + setTooltip(null); + return; + } + + setTooltip({ + caretX: tooltip?.caretX, + caretY: tooltip?.caretY, + title: tooltip?.title?.join(' ') || '', + align: tooltip?.xAlign, + body: + tooltip?.body?.map((item: any, index: number) => ({ + title: item?.lines?.join(' '), + color: tooltip?.labelColors?.[index]?.borderColor as string, + value: '', + })) || [], + dataPoints: tooltip?.dataPoints || [], + }); + }; diff --git a/frontend/src/component/executiveDashboard/LineChart/legendOptions.ts b/frontend/src/component/executiveDashboard/LineChart/legendOptions.ts new file mode 100644 index 0000000000..9d8e65cb23 --- /dev/null +++ b/frontend/src/component/executiveDashboard/LineChart/legendOptions.ts @@ -0,0 +1,34 @@ +import { Chart } from 'chart.js'; + +export const legendOptions = { + position: 'bottom', + labels: { + boxWidth: 12, + padding: 30, + generateLabels: (chart: Chart) => { + const datasets = chart.data.datasets; + const { + labels: { usePointStyle, pointStyle, textAlign, color }, + } = chart?.legend?.options || { + labels: {}, + }; + return (chart as any)._getSortedDatasetMetas().map((meta: any) => { + const style = meta.controller.getStyle( + usePointStyle ? 0 : undefined, + ); + return { + text: datasets[meta.index].label, + fillStyle: style.backgroundColor, + fontColor: color, + hidden: !meta.visible, + lineWidth: 0, + borderRadius: 6, + strokeStyle: style.borderColor, + pointStyle: pointStyle || style.pointStyle, + textAlign: textAlign || style.textAlign, + datasetIndex: meta.index, + }; + }); + }, + }, +} as const; diff --git a/frontend/src/component/executiveDashboard/ProjectHealthChart/HealthChartTooltip/HealthChartTooltip.tsx b/frontend/src/component/executiveDashboard/ProjectHealthChart/HealthChartTooltip/HealthChartTooltip.tsx new file mode 100644 index 0000000000..381125fae0 --- /dev/null +++ b/frontend/src/component/executiveDashboard/ProjectHealthChart/HealthChartTooltip/HealthChartTooltip.tsx @@ -0,0 +1,164 @@ +import { type VFC } from 'react'; +import { type ExecutiveSummarySchemaProjectFlagTrendsItem } from 'openapi'; +import { Box, Divider, Paper, Typography, styled } from '@mui/material'; +import { Badge } from 'component/common/Badge/Badge'; +import { TooltipState } from '../../LineChart/ChartTooltip/ChartTooltip'; +import { HorizontalDistributionChart } from '../../HorizontalDistributionChart/HorizontalDistributionChart'; +import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; + +const StyledTooltipItemContainer = styled(Paper)(({ theme }) => ({ + padding: theme.spacing(2), +})); + +const StyledItemHeader = styled(Box)(({ theme }) => ({ + display: 'flex', + justifyContent: 'space-between', + gap: theme.spacing(2), + alignItems: 'center', +})); + +const getHealthBadgeColor = (health?: number | null) => { + if (health === undefined || health === null) { + return 'info'; + } + + if (health >= 75) { + return 'success'; + } + + if (health >= 50) { + return 'warning'; + } + + return 'error'; +}; + +const Distribution = ({ stale = 0, potentiallyStale = 0, total = 0 }) => ( + <> + + + ({ marginTop: theme.spacing(0.5) })} + > + ({ + color: theme.palette.error.border, + })} + > + {'● '} + + Stale flags: {stale} + + + ({ + color: theme.palette.warning.border, + })} + > + {'● '} + + Potentially stale flags: {potentiallyStale} + + +); + +export const HealthTooltip: VFC<{ tooltip: TooltipState | null }> = ({ + tooltip, +}) => { + const data = tooltip?.dataPoints.map((point) => { + return { + label: point.label, + title: point.dataset.label, + color: point.dataset.borderColor, + value: point.raw as ExecutiveSummarySchemaProjectFlagTrendsItem, + }; + }); + + const limitedData = data?.slice(0, 5); + + return ( + ({ + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(2), + width: '300px', + })} + > + {limitedData?.map((point, index) => ( + + + + {point.label} + + + Project health + + + + + + {'● '} + + {point.title} + + + {point.value.health}% + + {' '} + ({ margin: theme.spacing(1.5, 0) })} + /> + ({ + marginBottom: theme.spacing(0.5), + })} + > + Total flags: {point.value.total} + + } + /> + + )) || null} + + ); +}; diff --git a/frontend/src/component/executiveDashboard/ProjectHealthChart/ProjectHealthChart.tsx b/frontend/src/component/executiveDashboard/ProjectHealthChart/ProjectHealthChart.tsx index cf8caa44a8..aa265f5234 100644 --- a/frontend/src/component/executiveDashboard/ProjectHealthChart/ProjectHealthChart.tsx +++ b/frontend/src/component/executiveDashboard/ProjectHealthChart/ProjectHealthChart.tsx @@ -1,76 +1,14 @@ -import { type VFC } from 'react'; import 'chartjs-adapter-date-fns'; -import { ExecutiveSummarySchema } from 'openapi'; +import { type VFC } from 'react'; +import { type ExecutiveSummarySchema } from 'openapi'; +import { HealthTooltip } from './HealthChartTooltip/HealthChartTooltip'; import { LineChart } from '../LineChart/LineChart'; import { useProjectChartData } from '../useProjectChartData'; -import { TooltipState } from '../LineChart/ChartTooltip/ChartTooltip'; -import { Box, Paper, styled } from '@mui/material'; -import { Badge } from 'component/common/Badge/Badge'; interface IFlagsProjectChartProps { projectFlagTrends: ExecutiveSummarySchema['projectFlagTrends']; } -const StyledTooltipItemContainer = styled(Paper)(({ theme }) => ({ - padding: theme.spacing(2), -})); - -const StyledItemHeader = styled(Box)(({ theme }) => ({ - display: 'flex', - justifyContent: 'space-between', - gap: theme.spacing(2), - alignItems: 'center', -})); - -const getHealthBadgeColor = (health?: number | null) => { - if (health === undefined || health === null) { - return 'info'; - } - - if (health >= 75) { - return 'success'; - } - - if (health >= 50) { - return 'warning'; - } - - return 'error'; -}; - -const TooltipComponent: VFC<{ tooltip: TooltipState | null }> = ({ - tooltip, -}) => { - const data = tooltip?.dataPoints.map((point) => { - return { - title: point.dataset.label, - color: point.dataset.borderColor, - value: point.raw as number, - }; - }); - - return ( - ({ - display: 'flex', - flexDirection: 'column', - gap: theme.spacing(3), - })} - > - {data?.map((point, index) => ( - - -
{point.title}
{' '} - - {point.value}% - -
-
- )) || null} -
- ); -}; - export const ProjectHealthChart: VFC = ({ projectFlagTrends, }) => { @@ -80,12 +18,9 @@ export const ProjectHealthChart: VFC = ({ ); diff --git a/frontend/src/component/executiveDashboard/UserStats/UserDistributionInfo.tsx b/frontend/src/component/executiveDashboard/UserStats/UserDistributionInfo.tsx new file mode 100644 index 0000000000..b2bc3e30f4 --- /dev/null +++ b/frontend/src/component/executiveDashboard/UserStats/UserDistributionInfo.tsx @@ -0,0 +1,78 @@ +import React from 'react'; +import { Box, Typography, styled } from '@mui/material'; + +type UserType = 'active' | 'inactive'; + +interface StyledLinearProgressProps { + type: UserType; +} +const StyledUserDistContainer = styled(Box)(({ theme }) => ({ + padding: `${theme.spacing(1.5)} ${theme.spacing(2)}`, + borderRadius: `${theme.shape.borderRadius}px`, + border: `1px solid ${theme.palette.divider}`, +})); + +const StyledUserDistIndicator = styled(Box)( + ({ theme, type }) => ({ + width: 8, + height: 8, + backgroundColor: + type === 'active' + ? theme.palette.success.border + : theme.palette.warning.border, + borderRadius: `2px`, + marginRight: theme.spacing(1), + }), +); + +interface IUserDistributionInfoProps { + type: UserType; + count: string; + percentage: string; +} + +const StyledDistInfoInnerContainer = styled(Box)(() => ({ + display: 'flex', + alignItems: 'center', + width: '100%', +})); + +const StyledDistInfoTextContainer = styled(Box)(() => ({ + display: 'flex', + flexDirection: 'column', +})); + +const StyledCountTypography = styled(Typography)(() => ({ + marginLeft: 'auto', + fontWeight: 'normal', +})); + +export const UserDistributionInfo: React.FC = ({ + type, + count, + percentage, +}) => { + return ( + + + + + + + {type === 'active' ? 'Active' : 'Inactive'} users + + + {percentage}% + + + {count} + + + + ); +}; diff --git a/frontend/src/component/executiveDashboard/UserStats/UserStats.tsx b/frontend/src/component/executiveDashboard/UserStats/UserStats.tsx index 013ecb3238..1c22ffa0c9 100644 --- a/frontend/src/component/executiveDashboard/UserStats/UserStats.tsx +++ b/frontend/src/component/executiveDashboard/UserStats/UserStats.tsx @@ -1,9 +1,11 @@ -import React, { type FC } from 'react'; +import { type FC } from 'react'; import { ChevronRight } from '@mui/icons-material'; import { Box, Typography, styled } from '@mui/material'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { useUiFlag } from 'hooks/useUiFlag'; import { Link } from 'react-router-dom'; +import { HorizontalDistributionChart } from '../HorizontalDistributionChart/HorizontalDistributionChart'; +import { UserDistributionInfo } from './UserDistributionInfo'; const StyledUserContainer = styled(Box)(({ theme }) => ({ position: 'relative', @@ -43,12 +45,6 @@ const StyledUserCount = styled(Typography)(({ theme }) => ({ padding: 0, })); -const StyledHeader = styled(Typography)(({ theme }) => ({ - marginBottom: theme.spacing(3), - fontSize: theme.fontSizes.bodySize, - fontWeight: 'bold', -})); - const StyledDistInfoContainer = styled(Box)({ display: 'flex', flexDirection: 'column', @@ -95,8 +91,17 @@ export const UserStats: FC = ({ count, active, inactive }) => { show={ <> - @@ -124,115 +129,3 @@ export const UserStats: FC = ({ count, active, inactive }) => { ); }; - -type UserType = 'active' | 'inactive'; - -interface StyledLinearProgressProps { - type: UserType; -} - -const StyledUserDistributionLine = styled(Box)( - ({ theme, type }) => ({ - borderRadius: theme.shape.borderRadius, - height: 16, - backgroundColor: - type === 'active' - ? theme.palette.success.border - : theme.palette.warning.border, - }), -); - -const UserDistribution = ({ activeUsersPercentage = 100 }) => { - const getLineWidth = () => { - return [activeUsersPercentage, 100 - activeUsersPercentage]; - }; - - const [activeWidth, inactiveWidth] = getLineWidth(); - - return ( - - - ({ - width: `${inactiveWidth}%`, - marginLeft: theme.spacing(0.5), - })} - /> - - ); -}; - -const StyledUserDistContainer = styled(Box)(({ theme }) => ({ - padding: `${theme.spacing(1.5)} ${theme.spacing(2)}`, - borderRadius: `${theme.shape.borderRadius}px`, - border: `1px solid ${theme.palette.divider}`, -})); - -const StyledUserDistIndicator = styled(Box)( - ({ theme, type }) => ({ - width: 8, - height: 8, - backgroundColor: - type === 'active' - ? theme.palette.success.border - : theme.palette.warning.border, - borderRadius: `2px`, - marginRight: theme.spacing(1), - }), -); - -interface IUserDistributionInfoProps { - type: UserType; - count: string; - percentage: string; -} - -const StyledDistInfoInnerContainer = styled(Box)(({ theme }) => ({ - display: 'flex', - alignItems: 'center', - width: '100%', -})); - -const StyledDistInfoTextContainer = styled(Box)(({ theme }) => ({ - display: 'flex', - flexDirection: 'column', -})); - -const StyledCountTypography = styled(Typography)(({ theme }) => ({ - marginLeft: 'auto', - fontWeight: 'normal', -})); - -const UserDistributionInfo: React.FC = ({ - type, - count, - percentage, -}) => { - return ( - - - - - - - {type === 'active' ? 'Active' : 'Inactive'} users - - - {percentage}% - - - {count} - - - - ); -}; diff --git a/frontend/src/themes/dark-theme.ts b/frontend/src/themes/dark-theme.ts index 6bbb91fe13..469e0ce826 100644 --- a/frontend/src/themes/dark-theme.ts +++ b/frontend/src/themes/dark-theme.ts @@ -298,9 +298,9 @@ const theme = { title: colors.grey[50], healthy: colors.purple[800], stale: colors.red[800], - potenciallyStale: colors.orange[800], + potentiallyStale: colors.orange[800], gradientStale: '#8A3E45', - gradientPotenciallyStale: '#875D21', + gradientPotentiallyStale: '#875D21', }, }, }, diff --git a/frontend/src/themes/theme.ts b/frontend/src/themes/theme.ts index 0f9d926d11..9cce1feac9 100644 --- a/frontend/src/themes/theme.ts +++ b/frontend/src/themes/theme.ts @@ -283,9 +283,9 @@ export const theme = { title: colors.grey[50], healthy: colors.purple[800], stale: colors.red[800], - potenciallyStale: colors.orange[800], + potentiallyStale: colors.orange[800], gradientStale: colors.red[300], - gradientPotenciallyStale: colors.orange[500], + gradientPotentiallyStale: colors.orange[500], }, }, }, diff --git a/frontend/src/themes/themeTypes.ts b/frontend/src/themes/themeTypes.ts index 835c1e41b0..f3b8622099 100644 --- a/frontend/src/themes/themeTypes.ts +++ b/frontend/src/themes/themeTypes.ts @@ -141,9 +141,9 @@ declare module '@mui/material/styles' { title: string; healthy: string; stale: string; - potenciallyStale: string; + potentiallyStale: string; gradientStale: string; - gradientPotenciallyStale: string; + gradientPotentiallyStale: string; }; }; }