mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-20 00:08:02 +01:00
Dashboard health stats widget (#6262)
This commit is contained in:
parent
474e53460a
commit
7682429839
@ -18,6 +18,7 @@ import { ProjectHealthChart } from './ProjectHealthChart/ProjectHealthChart';
|
||||
import { TimeToProductionChart } from './TimeToProductionChart/TimeToProductionChart';
|
||||
import { TimeToProduction } from './TimeToProduction/TimeToProduction';
|
||||
import { ProjectSelect, allOption } from './ProjectSelect/ProjectSelect';
|
||||
import { HealthStats } from './HealthStats/HealthStats';
|
||||
|
||||
const StyledGrid = styled(Box)(({ theme }) => ({
|
||||
display: 'grid',
|
||||
@ -144,20 +145,27 @@ export const ExecutiveDashboard: VFC = () => {
|
||||
projectFlagTrends={filteredProjectFlagTrends}
|
||||
/>
|
||||
</Widget>
|
||||
<Widget
|
||||
title='Health per project'
|
||||
order={6}
|
||||
span={largeChartSpan}
|
||||
>
|
||||
<Widget title='Average health' order={6}>
|
||||
<HealthStats
|
||||
// FIXME: data from API
|
||||
value={90}
|
||||
healthy={50}
|
||||
stale={10}
|
||||
potenciallyStale={5}
|
||||
/>
|
||||
</Widget>
|
||||
<Widget title='Health per project' order={7} span={chartSpan}>
|
||||
<ProjectHealthChart
|
||||
projectFlagTrends={filteredProjectFlagTrends}
|
||||
/>
|
||||
</Widget>
|
||||
<Widget title='Average time to production' order={7}>
|
||||
{/* FIXME: data from API */}
|
||||
<TimeToProduction daysToProduction={12} />
|
||||
<Widget title='Average time to production' order={8}>
|
||||
<TimeToProduction
|
||||
//FIXME: data from API
|
||||
daysToProduction={12}
|
||||
/>
|
||||
</Widget>
|
||||
<Widget title='Time to production' order={8} span={chartSpan}>
|
||||
<Widget title='Time to production' order={9} span={chartSpan}>
|
||||
<TimeToProductionChart
|
||||
projectFlagTrends={filteredProjectFlagTrends}
|
||||
/>
|
||||
|
@ -13,5 +13,5 @@ export const FlagsProjectChart: VFC<IFlagsProjectChartProps> = ({
|
||||
}) => {
|
||||
const data = useProjectChartData(projectFlagTrends, 'total');
|
||||
|
||||
return <LineChart data={data} />;
|
||||
return <LineChart data={data} isLocalTooltip />;
|
||||
};
|
||||
|
@ -23,7 +23,7 @@ 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 d = [
|
||||
const dSvgAttribute = [
|
||||
'M',
|
||||
start.x,
|
||||
start.y,
|
||||
@ -36,7 +36,7 @@ const describeArc = (radius: number, startAngle: number, endAngle: number) => {
|
||||
end.x,
|
||||
end.y,
|
||||
].join(' ');
|
||||
return d;
|
||||
return dSvgAttribute;
|
||||
};
|
||||
|
||||
const GaugeLines = () => {
|
||||
|
@ -0,0 +1,312 @@
|
||||
import { VFC } from 'react';
|
||||
import { useThemeMode } from 'hooks/useThemeMode';
|
||||
import { useTheme } from '@mui/material';
|
||||
|
||||
interface IHealthStatsProps {
|
||||
value: number;
|
||||
healthy: number;
|
||||
stale: number;
|
||||
potenciallyStale: number;
|
||||
}
|
||||
|
||||
export const HealthStats: VFC<IHealthStatsProps> = ({
|
||||
value,
|
||||
healthy,
|
||||
stale,
|
||||
potenciallyStale,
|
||||
}) => {
|
||||
const { themeMode } = useThemeMode();
|
||||
const isDark = themeMode === 'dark';
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<svg
|
||||
viewBox='0 0 268 281'
|
||||
fill='none'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
>
|
||||
<title>Health Stats</title>
|
||||
<g filter={!isDark ? 'url(#filter0_d_22043_268578)' : undefined}>
|
||||
<circle
|
||||
cx='134'
|
||||
cy='129'
|
||||
r='97'
|
||||
fill={theme.palette.charts.health.mainCircleBackground}
|
||||
/>
|
||||
</g>
|
||||
<circle
|
||||
cx='134'
|
||||
cy='129'
|
||||
r='121'
|
||||
stroke={theme.palette.charts.health.orbit}
|
||||
stroke-width='3'
|
||||
/>
|
||||
<text
|
||||
x={134}
|
||||
y={149}
|
||||
textAnchor='middle'
|
||||
fontSize={48}
|
||||
fill={theme.palette.charts.health.title}
|
||||
fontWeight={700}
|
||||
>
|
||||
{value !== undefined ? `${value}%` : 'N/A'}
|
||||
</text>
|
||||
<g filter={!isDark ? 'url(#filter1_d_22043_268578)' : undefined}>
|
||||
<circle
|
||||
cx='206'
|
||||
cy='58'
|
||||
r='50'
|
||||
fill={theme.palette.charts.health.circles}
|
||||
/>
|
||||
</g>
|
||||
<text
|
||||
x={206}
|
||||
y={56}
|
||||
fill={theme.palette.charts.health.healthy}
|
||||
fontWeight={700}
|
||||
fontSize={20}
|
||||
textAnchor='middle'
|
||||
>
|
||||
{healthy || 0}
|
||||
</text>
|
||||
<text
|
||||
x={206}
|
||||
y={72}
|
||||
fill={theme.palette.charts.health.text}
|
||||
fontSize={12}
|
||||
textAnchor='middle'
|
||||
>
|
||||
Healthy
|
||||
</text>
|
||||
<g filter={!isDark ? 'url(#filter2_d_22043_268578)' : undefined}>
|
||||
<circle
|
||||
cx='53'
|
||||
cy='66'
|
||||
r='41'
|
||||
fill={theme.palette.charts.health.circles}
|
||||
/>
|
||||
</g>
|
||||
<text
|
||||
x={53}
|
||||
y={65}
|
||||
fill={theme.palette.charts.health.stale}
|
||||
fontWeight={700}
|
||||
fontSize={20}
|
||||
textAnchor='middle'
|
||||
>
|
||||
{stale || 0}
|
||||
</text>
|
||||
<text
|
||||
x={53}
|
||||
y={81}
|
||||
fill={theme.palette.charts.health.text}
|
||||
fontSize={12}
|
||||
textAnchor='middle'
|
||||
>
|
||||
Stale
|
||||
</text>
|
||||
<g filter={!isDark ? 'url(#filter3_d_22043_268578)' : undefined}>
|
||||
<circle
|
||||
cx='144'
|
||||
cy='224'
|
||||
r='41'
|
||||
fill={theme.palette.charts.health.circles}
|
||||
/>
|
||||
</g>
|
||||
<text
|
||||
x={144}
|
||||
y={216}
|
||||
fill={theme.palette.charts.health.potenciallyStale}
|
||||
fontWeight={700}
|
||||
fontSize={20}
|
||||
textAnchor='middle'
|
||||
>
|
||||
{potenciallyStale || 0}
|
||||
</text>
|
||||
<text
|
||||
x={144}
|
||||
y={232}
|
||||
fill={theme.palette.charts.health.text}
|
||||
fontSize={12}
|
||||
textAnchor='middle'
|
||||
>
|
||||
<tspan x={144} dy='0'>
|
||||
Potentially
|
||||
</tspan>
|
||||
<tspan x={144} dy='1.2em'>
|
||||
stale
|
||||
</tspan>
|
||||
</text>
|
||||
<path
|
||||
d='M99.5 247.275C99.5 251.693 103.082 255.275 107.5 255.275C111.918 255.275 115.5 251.693 115.5 247.275C115.5 242.857 111.918 239.275 107.5 239.275C103.082 239.275 99.5 242.857 99.5 247.275ZM10.8811 92C10.8811 96.4183 14.4629 100 18.8811 100C23.2994 100 26.8811 96.4183 26.8811 92C26.8811 87.5817 23.2994 84 18.8811 84C14.4629 84 10.8811 87.5817 10.8811 92ZM107.827 245.811C54.4151 233.886 14.5 186.258 14.5 129.325H11.5C11.5 187.696 52.4223 236.515 107.173 248.739L107.827 245.811ZM14.5 129.325C14.5 116.458 16.5379 104.07 20.3078 92.4634L17.4545 91.5366C13.5886 103.439 11.5 116.14 11.5 129.325H14.5Z'
|
||||
fill='url(#paint0_linear_22043_268578)'
|
||||
/>
|
||||
<defs>
|
||||
<filter
|
||||
id='filter0_d_22043_268578'
|
||||
x='15'
|
||||
y='13'
|
||||
width='238'
|
||||
height='238'
|
||||
filterUnits='userSpaceOnUse'
|
||||
color-interpolation-filters='sRGB'
|
||||
>
|
||||
<feFlood flood-opacity='0' result='BackgroundImageFix' />
|
||||
<feColorMatrix
|
||||
in='SourceAlpha'
|
||||
type='matrix'
|
||||
values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'
|
||||
result='hardAlpha'
|
||||
/>
|
||||
<feMorphology
|
||||
radius='2'
|
||||
operator='dilate'
|
||||
in='SourceAlpha'
|
||||
result='effect1_dropShadow_22043_268578'
|
||||
/>
|
||||
<feOffset dy='3' />
|
||||
<feGaussianBlur stdDeviation='10' />
|
||||
<feComposite in2='hardAlpha' operator='out' />
|
||||
<feColorMatrix
|
||||
type='matrix'
|
||||
values='0 0 0 0 0.505882 0 0 0 0 0.478431 0 0 0 0 0.996078 0 0 0 0.36 0'
|
||||
/>
|
||||
<feBlend
|
||||
mode='normal'
|
||||
in2='BackgroundImageFix'
|
||||
result='effect1_dropShadow_22043_268578'
|
||||
/>
|
||||
<feBlend
|
||||
mode='normal'
|
||||
in='SourceGraphic'
|
||||
in2='effect1_dropShadow_22043_268578'
|
||||
result='shape'
|
||||
/>
|
||||
</filter>
|
||||
<filter
|
||||
id='filter1_d_22043_268578'
|
||||
x='144'
|
||||
y='0'
|
||||
width='124'
|
||||
height='124'
|
||||
filterUnits='userSpaceOnUse'
|
||||
color-interpolation-filters='sRGB'
|
||||
>
|
||||
<feFlood flood-opacity='0' result='BackgroundImageFix' />
|
||||
<feColorMatrix
|
||||
in='SourceAlpha'
|
||||
type='matrix'
|
||||
values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'
|
||||
result='hardAlpha'
|
||||
/>
|
||||
<feOffset dy='4' />
|
||||
<feGaussianBlur stdDeviation='6' />
|
||||
<feComposite in2='hardAlpha' operator='out' />
|
||||
<feColorMatrix
|
||||
type='matrix'
|
||||
values='0 0 0 0 0.380392 0 0 0 0 0.356863 0 0 0 0 0.760784 0 0 0 0.16 0'
|
||||
/>
|
||||
<feBlend
|
||||
mode='normal'
|
||||
in2='BackgroundImageFix'
|
||||
result='effect1_dropShadow_22043_268578'
|
||||
/>
|
||||
<feBlend
|
||||
mode='normal'
|
||||
in='SourceGraphic'
|
||||
in2='effect1_dropShadow_22043_268578'
|
||||
result='shape'
|
||||
/>
|
||||
</filter>
|
||||
<filter
|
||||
id='filter2_d_22043_268578'
|
||||
x='0'
|
||||
y='17'
|
||||
width='106'
|
||||
height='106'
|
||||
filterUnits='userSpaceOnUse'
|
||||
color-interpolation-filters='sRGB'
|
||||
>
|
||||
<feFlood flood-opacity='0' result='BackgroundImageFix' />
|
||||
<feColorMatrix
|
||||
in='SourceAlpha'
|
||||
type='matrix'
|
||||
values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'
|
||||
result='hardAlpha'
|
||||
/>
|
||||
<feOffset dy='4' />
|
||||
<feGaussianBlur stdDeviation='6' />
|
||||
<feComposite in2='hardAlpha' operator='out' />
|
||||
<feColorMatrix
|
||||
type='matrix'
|
||||
values='0 0 0 0 0.380392 0 0 0 0 0.356863 0 0 0 0 0.760784 0 0 0 0.16 0'
|
||||
/>
|
||||
<feBlend
|
||||
mode='normal'
|
||||
in2='BackgroundImageFix'
|
||||
result='effect1_dropShadow_22043_268578'
|
||||
/>
|
||||
<feBlend
|
||||
mode='normal'
|
||||
in='SourceGraphic'
|
||||
in2='effect1_dropShadow_22043_268578'
|
||||
result='shape'
|
||||
/>
|
||||
</filter>
|
||||
<filter
|
||||
id='filter3_d_22043_268578'
|
||||
x='91'
|
||||
y='175'
|
||||
width='106'
|
||||
height='106'
|
||||
filterUnits='userSpaceOnUse'
|
||||
color-interpolation-filters='sRGB'
|
||||
>
|
||||
<feFlood flood-opacity='0' result='BackgroundImageFix' />
|
||||
<feColorMatrix
|
||||
in='SourceAlpha'
|
||||
type='matrix'
|
||||
values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0'
|
||||
result='hardAlpha'
|
||||
/>
|
||||
<feOffset dy='4' />
|
||||
<feGaussianBlur stdDeviation='6' />
|
||||
<feComposite in2='hardAlpha' operator='out' />
|
||||
<feColorMatrix
|
||||
type='matrix'
|
||||
values='0 0 0 0 0.380392 0 0 0 0 0.356863 0 0 0 0 0.760784 0 0 0 0.16 0'
|
||||
/>
|
||||
<feBlend
|
||||
mode='normal'
|
||||
in2='BackgroundImageFix'
|
||||
result='effect1_dropShadow_22043_268578'
|
||||
/>
|
||||
<feBlend
|
||||
mode='normal'
|
||||
in='SourceGraphic'
|
||||
in2='effect1_dropShadow_22043_268578'
|
||||
result='shape'
|
||||
/>
|
||||
</filter>
|
||||
<linearGradient
|
||||
id='paint0_linear_22043_268578'
|
||||
x1='64.2447'
|
||||
y1='87'
|
||||
x2='64.2447'
|
||||
y2='249'
|
||||
gradientUnits='userSpaceOnUse'
|
||||
>
|
||||
<stop
|
||||
stop-color={theme.palette.charts.health.gradientStale}
|
||||
/>
|
||||
<stop
|
||||
offset='1'
|
||||
stop-color={
|
||||
theme.palette.charts.health.gradientPotenciallyStale
|
||||
}
|
||||
/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
};
|
@ -28,6 +28,7 @@ const createOptions = (
|
||||
locationSettings: ILocationSettings,
|
||||
setTooltip: React.Dispatch<React.SetStateAction<TooltipState | null>>,
|
||||
isPlaceholder?: boolean,
|
||||
localTooltip?: boolean,
|
||||
) =>
|
||||
({
|
||||
responsive: true,
|
||||
@ -82,13 +83,12 @@ const createOptions = (
|
||||
tooltip: {
|
||||
enabled: false,
|
||||
external: (context: any) => {
|
||||
const tooltipModel = context.tooltip;
|
||||
if (tooltipModel.opacity === 0) {
|
||||
const tooltip = context.tooltip;
|
||||
if (tooltip.opacity === 0) {
|
||||
setTooltip(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const tooltip = context.tooltip;
|
||||
setTooltip({
|
||||
caretX: tooltip?.caretX,
|
||||
caretY: tooltip?.caretY,
|
||||
@ -106,15 +106,17 @@ const createOptions = (
|
||||
},
|
||||
locale: locationSettings.locale,
|
||||
interaction: {
|
||||
intersect: false,
|
||||
intersect: localTooltip || false,
|
||||
axis: 'x',
|
||||
},
|
||||
elements: {
|
||||
point: {
|
||||
radius: 0,
|
||||
hitRadius: 15,
|
||||
},
|
||||
},
|
||||
// cubicInterpolationMode: 'monotone',
|
||||
tension: 0.1,
|
||||
color: theme.palette.text.secondary,
|
||||
scales: {
|
||||
y: {
|
||||
@ -127,12 +129,14 @@ const createOptions = (
|
||||
ticks: {
|
||||
color: theme.palette.text.secondary,
|
||||
display: !isPlaceholder,
|
||||
precision: 0,
|
||||
},
|
||||
},
|
||||
x: {
|
||||
type: 'time',
|
||||
time: {
|
||||
unit: 'month',
|
||||
unit: 'day',
|
||||
tooltipFormat: 'PPP',
|
||||
},
|
||||
grid: {
|
||||
color: 'transparent',
|
||||
@ -206,14 +210,21 @@ const LineChartComponent: VFC<{
|
||||
data: ChartData<'line', (number | ScatterDataPoint | null)[], unknown>;
|
||||
aspectRatio?: number;
|
||||
cover?: ReactNode;
|
||||
}> = ({ data, aspectRatio, cover }) => {
|
||||
isLocalTooltip?: boolean;
|
||||
}> = ({ data, aspectRatio, cover, isLocalTooltip }) => {
|
||||
const theme = useTheme();
|
||||
const { locationSettings } = useLocationSettings();
|
||||
|
||||
const [tooltip, setTooltip] = useState<null | TooltipState>(null);
|
||||
const options = useMemo(
|
||||
() =>
|
||||
createOptions(theme, locationSettings, setTooltip, Boolean(cover)),
|
||||
createOptions(
|
||||
theme,
|
||||
locationSettings,
|
||||
setTooltip,
|
||||
Boolean(cover),
|
||||
isLocalTooltip,
|
||||
),
|
||||
[theme, locationSettings],
|
||||
);
|
||||
|
||||
|
@ -13,5 +13,5 @@ export const ProjectHealthChart: VFC<IFlagsProjectChartProps> = ({
|
||||
}) => {
|
||||
const data = useProjectChartData(projectFlagTrends, 'health');
|
||||
|
||||
return <LineChart data={data} />;
|
||||
return <LineChart data={data} isLocalTooltip />;
|
||||
};
|
||||
|
@ -13,5 +13,5 @@ export const TimeToProductionChart: VFC<IFlagsProjectChartProps> = ({
|
||||
}) => {
|
||||
const data = useProjectChartData(projectFlagTrends, 'timeToProduction');
|
||||
|
||||
return <LineChart data={data} />;
|
||||
return <LineChart data={data} isLocalTooltip />;
|
||||
};
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
LineChart,
|
||||
NotEnoughData,
|
||||
} from '../LineChart/LineChart';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
|
||||
interface IUsersChartProps {
|
||||
userTrends: ExecutiveSummarySchema['userTrends'];
|
||||
@ -17,6 +18,7 @@ export const UsersChart: VFC<IUsersChartProps> = ({
|
||||
userTrends,
|
||||
isLoading,
|
||||
}) => {
|
||||
const showInactiveUsers = useUiFlag('showInactiveUsers');
|
||||
const theme = useTheme();
|
||||
const notEnoughData = userTrends.length < 2;
|
||||
const placeholderData = useMemo(
|
||||
@ -50,23 +52,28 @@ export const UsersChart: VFC<IUsersChartProps> = ({
|
||||
data: userTrends.map((item) => item.total),
|
||||
borderColor: theme.palette.primary.light,
|
||||
backgroundColor: fillGradientPrimary,
|
||||
pointBackgroundColor: theme.palette.primary.main,
|
||||
fill: true,
|
||||
order: 3,
|
||||
},
|
||||
{
|
||||
label: 'Active users',
|
||||
data: userTrends.map((item) => item.active),
|
||||
borderColor: theme.palette.success.border,
|
||||
backgroundColor: theme.palette.success.border,
|
||||
order: 2,
|
||||
},
|
||||
{
|
||||
label: 'Inactive users',
|
||||
data: userTrends.map((item) => item.inactive),
|
||||
borderColor: theme.palette.warning.border,
|
||||
backgroundColor: theme.palette.warning.border,
|
||||
order: 1,
|
||||
},
|
||||
...(showInactiveUsers
|
||||
? [
|
||||
{
|
||||
label: 'Active users',
|
||||
data: userTrends.map((item) => item.active),
|
||||
borderColor: theme.palette.success.border,
|
||||
backgroundColor: theme.palette.success.border,
|
||||
order: 2,
|
||||
},
|
||||
{
|
||||
label: 'Inactive users',
|
||||
data: userTrends.map((item) => item.inactive),
|
||||
borderColor: theme.palette.warning.border,
|
||||
backgroundColor: theme.palette.warning.border,
|
||||
order: 1,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
],
|
||||
}),
|
||||
[theme, userTrends],
|
||||
|
@ -1,9 +1,16 @@
|
||||
// TODO: Replace this function with something more tailored to our color palette
|
||||
export const getRandomColor = () => {
|
||||
const letters = '0123456789ABCDEF';
|
||||
let color = '#';
|
||||
for (let i = 0; i < 6; i++) {
|
||||
color += letters[Math.floor(Math.random() * 16)];
|
||||
import { colors } from 'themes/colors';
|
||||
|
||||
export const getProjectColor = (str: string): string => {
|
||||
if (str === 'default') {
|
||||
// Special case for default project - use primary color
|
||||
return colors.purple[800];
|
||||
}
|
||||
return color;
|
||||
|
||||
let hash = 0;
|
||||
|
||||
for (let i = 0; i < str.length; i++) {
|
||||
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
||||
}
|
||||
const c = (hash & 0x00ffffff).toString(16).toUpperCase();
|
||||
return `#${'00000'.substring(0, 6 - c.length)}${c}`;
|
||||
};
|
||||
|
@ -3,7 +3,7 @@ import {
|
||||
ExecutiveSummarySchema,
|
||||
ExecutiveSummarySchemaProjectFlagTrendsItem,
|
||||
} from '../../openapi';
|
||||
import { getRandomColor } from './executive-dashboard-utils';
|
||||
import { getProjectColor } from './executive-dashboard-utils';
|
||||
import { useTheme } from '@mui/material';
|
||||
|
||||
type ProjectFlagTrends = ExecutiveSummarySchema['projectFlagTrends'];
|
||||
@ -27,7 +27,7 @@ export const useProjectChartData = (
|
||||
|
||||
const datasets = Object.entries(groupedFlagTrends).map(
|
||||
([project, trends]) => {
|
||||
const color = getRandomColor();
|
||||
const color = getProjectColor(project);
|
||||
return {
|
||||
label: project,
|
||||
data: trends.map((item) => {
|
||||
|
@ -290,6 +290,18 @@ const theme = {
|
||||
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],
|
||||
potenciallyStale: colors.orange[800],
|
||||
gradientStale: '#8A3E45',
|
||||
gradientPotenciallyStale: '#875D21',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -275,6 +275,18 @@ export const theme = {
|
||||
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],
|
||||
potenciallyStale: colors.orange[800],
|
||||
gradientStale: colors.red[300],
|
||||
gradientPotenciallyStale: colors.orange[500],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -133,6 +133,18 @@ declare module '@mui/material/styles' {
|
||||
sectionLine: string;
|
||||
text: string;
|
||||
};
|
||||
health: {
|
||||
mainCircleBackground: string;
|
||||
orbit: string;
|
||||
circles: string;
|
||||
text: string;
|
||||
title: string;
|
||||
healthy: string;
|
||||
stale: string;
|
||||
potenciallyStale: string;
|
||||
gradientStale: string;
|
||||
gradientPotenciallyStale: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
interface Theme extends CustomTheme {}
|
||||
|
Loading…
Reference in New Issue
Block a user