2024-02-20 15:56:53 +01:00
|
|
|
|
import { useMemo, useState, VFC } from 'react';
|
2024-03-01 13:28:57 +01:00
|
|
|
|
import {
|
|
|
|
|
Box,
|
|
|
|
|
styled,
|
|
|
|
|
Typography,
|
|
|
|
|
useMediaQuery,
|
|
|
|
|
useTheme,
|
|
|
|
|
} from '@mui/material';
|
2024-01-22 11:07:38 +01:00
|
|
|
|
import { UsersChart } from './UsersChart/UsersChart';
|
2024-01-22 12:15:49 +01:00
|
|
|
|
import { FlagsChart } from './FlagsChart/FlagsChart';
|
2024-01-26 09:03:12 +01:00
|
|
|
|
import { useExecutiveDashboard } from 'hooks/api/getters/useExecutiveSummary/useExecutiveSummary';
|
2024-01-25 14:43:59 +01:00
|
|
|
|
import { UserStats } from './UserStats/UserStats';
|
2024-01-26 14:22:16 +01:00
|
|
|
|
import { FlagStats } from './FlagStats/FlagStats';
|
2024-01-30 17:02:13 +01:00
|
|
|
|
import { Widget } from './Widget/Widget';
|
2024-01-31 08:48:10 +01:00
|
|
|
|
import { FlagsProjectChart } from './FlagsProjectChart/FlagsProjectChart';
|
2024-01-31 13:19:28 +01:00
|
|
|
|
import { ProjectHealthChart } from './ProjectHealthChart/ProjectHealthChart';
|
2024-02-01 12:22:27 +01:00
|
|
|
|
import { TimeToProductionChart } from './TimeToProductionChart/TimeToProductionChart';
|
2024-02-14 13:32:12 +01:00
|
|
|
|
import { TimeToProduction } from './TimeToProduction/TimeToProduction';
|
2024-03-01 13:28:57 +01:00
|
|
|
|
import {
|
|
|
|
|
ProjectSelect,
|
|
|
|
|
allOption,
|
|
|
|
|
} from '../common/ProjectSelect/ProjectSelect';
|
2024-02-23 14:17:58 +01:00
|
|
|
|
import { MetricsSummaryChart } from './MetricsSummaryChart/MetricsSummaryChart';
|
|
|
|
|
import {
|
|
|
|
|
ExecutiveSummarySchemaMetricsSummaryTrendsItem,
|
|
|
|
|
ExecutiveSummarySchemaProjectFlagTrendsItem,
|
2024-02-27 08:57:50 +01:00
|
|
|
|
} from 'openapi';
|
2024-02-23 09:05:59 +01:00
|
|
|
|
import { HealthStats } from './HealthStats/HealthStats';
|
2024-02-27 13:12:18 +01:00
|
|
|
|
import { DashboardHeader } from './DashboardHeader/DashboardHeader';
|
2024-01-22 11:07:38 +01:00
|
|
|
|
|
|
|
|
|
const StyledGrid = styled(Box)(({ theme }) => ({
|
|
|
|
|
display: 'grid',
|
2024-01-26 14:33:11 +01:00
|
|
|
|
gridTemplateColumns: `300px 1fr`,
|
2024-01-30 09:00:06 +01:00
|
|
|
|
gridAutoRows: 'auto',
|
2024-01-22 11:07:38 +01:00
|
|
|
|
gap: theme.spacing(2),
|
|
|
|
|
}));
|
2024-01-18 12:32:25 +01:00
|
|
|
|
|
2024-03-01 13:28:57 +01:00
|
|
|
|
const StyledBox = styled(Box)(({ theme }) => ({
|
|
|
|
|
marginBottom: theme.spacing(4),
|
|
|
|
|
marginTop: theme.spacing(4),
|
|
|
|
|
[theme.breakpoints.down('lg')]: {
|
|
|
|
|
width: '100%',
|
|
|
|
|
marginLeft: 0,
|
|
|
|
|
},
|
|
|
|
|
display: 'flex',
|
|
|
|
|
justifyContent: 'space-between',
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
}));
|
|
|
|
|
|
2024-01-30 17:02:13 +01:00
|
|
|
|
const useDashboardGrid = () => {
|
|
|
|
|
const theme = useTheme();
|
|
|
|
|
const isMediumScreen = useMediaQuery(theme.breakpoints.down('lg'));
|
|
|
|
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
|
|
|
|
|
|
|
|
|
if (isSmallScreen) {
|
|
|
|
|
return {
|
|
|
|
|
gridTemplateColumns: `1fr`,
|
|
|
|
|
chartSpan: 1,
|
|
|
|
|
userTrendsOrder: 3,
|
|
|
|
|
flagStatsOrder: 2,
|
2024-01-31 10:50:50 +01:00
|
|
|
|
largeChartSpan: 1,
|
2024-01-30 17:02:13 +01:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isMediumScreen) {
|
|
|
|
|
return {
|
|
|
|
|
gridTemplateColumns: `1fr 1fr`,
|
|
|
|
|
chartSpan: 2,
|
|
|
|
|
userTrendsOrder: 3,
|
|
|
|
|
flagStatsOrder: 2,
|
2024-01-31 10:50:50 +01:00
|
|
|
|
largeChartSpan: 2,
|
2024-01-30 17:02:13 +01:00
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
gridTemplateColumns: `300px auto`,
|
|
|
|
|
chartSpan: 1,
|
|
|
|
|
userTrendsOrder: 2,
|
|
|
|
|
flagStatsOrder: 3,
|
2024-01-31 10:50:50 +01:00
|
|
|
|
largeChartSpan: 2,
|
2024-01-30 17:02:13 +01:00
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2024-02-23 14:17:58 +01:00
|
|
|
|
interface FilteredProjectData {
|
|
|
|
|
filteredProjectFlagTrends: ExecutiveSummarySchemaProjectFlagTrendsItem[];
|
|
|
|
|
filteredMetricsSummaryTrends: ExecutiveSummarySchemaMetricsSummaryTrendsItem[];
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-18 12:32:25 +01:00
|
|
|
|
export const ExecutiveDashboard: VFC = () => {
|
2024-01-26 09:03:12 +01:00
|
|
|
|
const { executiveDashboardData, loading, error } = useExecutiveDashboard();
|
2024-02-19 15:28:03 +01:00
|
|
|
|
const [projects, setProjects] = useState([allOption.id]);
|
2024-01-26 09:03:12 +01:00
|
|
|
|
|
2024-01-30 17:02:13 +01:00
|
|
|
|
const flagPerUsers = useMemo(() => {
|
2024-01-30 10:07:16 +01:00
|
|
|
|
if (
|
|
|
|
|
executiveDashboardData.users.total === 0 ||
|
|
|
|
|
executiveDashboardData.flags.total === 0
|
|
|
|
|
)
|
|
|
|
|
return '0';
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
executiveDashboardData.flags.total /
|
|
|
|
|
executiveDashboardData.users.total
|
|
|
|
|
).toFixed(1);
|
2024-01-30 17:02:13 +01:00
|
|
|
|
}, [executiveDashboardData]);
|
|
|
|
|
|
2024-02-23 14:17:58 +01:00
|
|
|
|
const { filteredProjectFlagTrends, filteredMetricsSummaryTrends } =
|
|
|
|
|
useMemo<FilteredProjectData>(() => {
|
|
|
|
|
if (projects[0] === allOption.id) {
|
|
|
|
|
return {
|
|
|
|
|
filteredProjectFlagTrends:
|
|
|
|
|
executiveDashboardData.projectFlagTrends,
|
|
|
|
|
filteredMetricsSummaryTrends:
|
|
|
|
|
executiveDashboardData.metricsSummaryTrends,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const filteredProjectFlagTrends =
|
|
|
|
|
executiveDashboardData.projectFlagTrends.filter((trend) =>
|
|
|
|
|
projects.includes(trend.project),
|
|
|
|
|
) as ExecutiveSummarySchemaProjectFlagTrendsItem[];
|
2024-02-19 15:28:03 +01:00
|
|
|
|
|
2024-02-23 14:17:58 +01:00
|
|
|
|
const filteredImpressionsSummary =
|
|
|
|
|
executiveDashboardData.metricsSummaryTrends.filter((summary) =>
|
|
|
|
|
projects.includes(summary.project),
|
|
|
|
|
) as ExecutiveSummarySchemaMetricsSummaryTrendsItem[];
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
filteredProjectFlagTrends,
|
|
|
|
|
filteredMetricsSummaryTrends: filteredImpressionsSummary,
|
|
|
|
|
};
|
|
|
|
|
}, [executiveDashboardData, projects]);
|
2024-02-19 15:28:03 +01:00
|
|
|
|
|
2024-01-31 10:50:50 +01:00
|
|
|
|
const {
|
|
|
|
|
gridTemplateColumns,
|
|
|
|
|
chartSpan,
|
|
|
|
|
userTrendsOrder,
|
|
|
|
|
flagStatsOrder,
|
|
|
|
|
largeChartSpan,
|
|
|
|
|
} = useDashboardGrid();
|
2024-01-30 10:07:16 +01:00
|
|
|
|
|
2024-01-22 11:07:38 +01:00
|
|
|
|
return (
|
|
|
|
|
<>
|
|
|
|
|
<Box sx={(theme) => ({ paddingBottom: theme.spacing(4) })}>
|
2024-02-27 13:12:18 +01:00
|
|
|
|
<DashboardHeader />
|
2024-01-22 11:07:38 +01:00
|
|
|
|
</Box>
|
2024-01-30 17:02:13 +01:00
|
|
|
|
<StyledGrid sx={{ gridTemplateColumns }}>
|
|
|
|
|
<Widget title='Total users' order={1}>
|
2024-02-26 15:51:14 +01:00
|
|
|
|
<UserStats
|
|
|
|
|
count={executiveDashboardData.users.total}
|
|
|
|
|
active={executiveDashboardData.users.active}
|
|
|
|
|
inactive={executiveDashboardData.users.inactive}
|
|
|
|
|
/>
|
2024-01-30 17:02:13 +01:00
|
|
|
|
</Widget>
|
|
|
|
|
<Widget title='Users' order={userTrendsOrder} span={chartSpan}>
|
|
|
|
|
<UsersChart
|
|
|
|
|
userTrends={executiveDashboardData.userTrends}
|
2024-02-12 16:10:46 +01:00
|
|
|
|
isLoading={loading}
|
2024-01-30 17:02:13 +01:00
|
|
|
|
/>
|
|
|
|
|
</Widget>
|
|
|
|
|
<Widget
|
|
|
|
|
title='Total flags'
|
2024-02-26 15:51:14 +01:00
|
|
|
|
tooltip='Total flags represent the total active flags (not archived) that currently exist across all projects of your application.'
|
2024-01-30 17:02:13 +01:00
|
|
|
|
order={flagStatsOrder}
|
|
|
|
|
>
|
|
|
|
|
<FlagStats
|
|
|
|
|
count={executiveDashboardData.flags.total}
|
|
|
|
|
flagsPerUser={flagPerUsers}
|
|
|
|
|
/>
|
|
|
|
|
</Widget>
|
|
|
|
|
<Widget title='Number of flags' order={4} span={chartSpan}>
|
|
|
|
|
<FlagsChart
|
|
|
|
|
flagTrends={executiveDashboardData.flagTrends}
|
2024-02-12 16:10:46 +01:00
|
|
|
|
isLoading={loading}
|
2024-01-30 17:02:13 +01:00
|
|
|
|
/>
|
|
|
|
|
</Widget>
|
2024-02-19 15:28:03 +01:00
|
|
|
|
</StyledGrid>
|
2024-03-01 13:28:57 +01:00
|
|
|
|
<StyledBox>
|
|
|
|
|
<Typography variant='h2' component='span'>
|
|
|
|
|
Insights per project
|
|
|
|
|
</Typography>
|
|
|
|
|
<ProjectSelect
|
|
|
|
|
selectedProjects={projects}
|
|
|
|
|
onChange={setProjects}
|
|
|
|
|
dataTestId={'DASHBOARD_PROJECT_SELECT'}
|
|
|
|
|
sx={{ flex: 1, maxWidth: '360px' }}
|
|
|
|
|
/>
|
|
|
|
|
</StyledBox>
|
2024-02-19 15:28:03 +01:00
|
|
|
|
<StyledGrid>
|
2024-01-31 10:50:50 +01:00
|
|
|
|
<Widget
|
|
|
|
|
title='Number of flags per project'
|
|
|
|
|
order={5}
|
|
|
|
|
span={largeChartSpan}
|
|
|
|
|
>
|
|
|
|
|
<FlagsProjectChart
|
2024-02-19 15:28:03 +01:00
|
|
|
|
projectFlagTrends={filteredProjectFlagTrends}
|
2024-01-31 10:50:50 +01:00
|
|
|
|
/>
|
|
|
|
|
</Widget>
|
2024-02-23 09:05:59 +01:00
|
|
|
|
<Widget title='Average health' order={6}>
|
|
|
|
|
<HealthStats
|
|
|
|
|
// FIXME: data from API
|
2024-02-26 15:51:14 +01:00
|
|
|
|
value={80}
|
|
|
|
|
healthy={4}
|
|
|
|
|
stale={1}
|
2024-02-28 08:58:27 +01:00
|
|
|
|
potentiallyStale={0}
|
2024-02-23 09:05:59 +01:00
|
|
|
|
/>
|
|
|
|
|
</Widget>
|
|
|
|
|
<Widget title='Health per project' order={7} span={chartSpan}>
|
2024-01-31 13:19:28 +01:00
|
|
|
|
<ProjectHealthChart
|
2024-02-19 15:28:03 +01:00
|
|
|
|
projectFlagTrends={filteredProjectFlagTrends}
|
2024-01-31 13:19:28 +01:00
|
|
|
|
/>
|
|
|
|
|
</Widget>
|
2024-02-23 14:17:58 +01:00
|
|
|
|
<Widget
|
|
|
|
|
title='Metrics over time per project'
|
|
|
|
|
order={8}
|
|
|
|
|
span={largeChartSpan}
|
|
|
|
|
>
|
|
|
|
|
<MetricsSummaryChart
|
|
|
|
|
metricsSummaryTrends={filteredMetricsSummaryTrends}
|
|
|
|
|
/>
|
|
|
|
|
</Widget>
|
|
|
|
|
|
|
|
|
|
<Widget title='Average time to production' order={9}>
|
2024-02-23 09:05:59 +01:00
|
|
|
|
<TimeToProduction
|
|
|
|
|
//FIXME: data from API
|
2024-02-26 15:51:14 +01:00
|
|
|
|
daysToProduction={5.2}
|
2024-02-23 09:05:59 +01:00
|
|
|
|
/>
|
2024-02-14 13:32:12 +01:00
|
|
|
|
</Widget>
|
2024-02-23 14:17:58 +01:00
|
|
|
|
<Widget title='Time to production' order={10} span={chartSpan}>
|
2024-02-01 12:22:27 +01:00
|
|
|
|
<TimeToProductionChart
|
2024-02-19 15:28:03 +01:00
|
|
|
|
projectFlagTrends={filteredProjectFlagTrends}
|
2024-02-01 12:22:27 +01:00
|
|
|
|
/>
|
|
|
|
|
</Widget>
|
2024-01-22 11:07:38 +01:00
|
|
|
|
</StyledGrid>
|
|
|
|
|
</>
|
|
|
|
|
);
|
2024-01-18 12:32:25 +01:00
|
|
|
|
};
|