2024-03-04 12:56:17 +01:00
|
|
|
import { VFC } from 'react';
|
|
|
|
import { Box, styled } from '@mui/material';
|
|
|
|
import { ArrayParam, withDefault } from 'use-query-params';
|
|
|
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
|
|
import { usePersistentTableState } from 'hooks/usePersistentTableState';
|
2024-03-01 13:28:57 +01:00
|
|
|
import {
|
|
|
|
allOption,
|
2024-03-04 12:56:17 +01:00
|
|
|
ProjectSelect,
|
|
|
|
} from 'component/common/ProjectSelect/ProjectSelect';
|
|
|
|
import { useExecutiveDashboard } from 'hooks/api/getters/useExecutiveSummary/useExecutiveSummary';
|
|
|
|
|
|
|
|
import { useFilteredFlagsSummary } from './hooks/useFilteredFlagsSummary';
|
|
|
|
import { useFilteredTrends } from './hooks/useFilteredTrends';
|
|
|
|
|
|
|
|
import { Widget } from './components/Widget/Widget';
|
|
|
|
import { DashboardHeader } from './components/DashboardHeader/DashboardHeader';
|
|
|
|
|
|
|
|
import { UserStats } from './componentsStat/UserStats/UserStats';
|
|
|
|
import { FlagStats } from './componentsStat/FlagStats/FlagStats';
|
|
|
|
import { HealthStats } from './componentsStat/HealthStats/HealthStats';
|
|
|
|
|
|
|
|
import { UsersChart } from './componentsChart/UsersChart/UsersChart';
|
|
|
|
import { FlagsChart } from './componentsChart/FlagsChart/FlagsChart';
|
|
|
|
import { FlagsProjectChart } from './componentsChart/FlagsProjectChart/FlagsProjectChart';
|
|
|
|
import { ProjectHealthChart } from './componentsChart/ProjectHealthChart/ProjectHealthChart';
|
|
|
|
import { MetricsSummaryChart } from './componentsChart/MetricsSummaryChart/MetricsSummaryChart';
|
|
|
|
import { UsersPerProjectChart } from './componentsChart/UsersPerProjectChart/UsersPerProjectChart';
|
2024-03-07 10:00:18 +01:00
|
|
|
import { UpdatesPerEnvironmentTypeChart } from './componentsChart/UpdatesPerEnvironmentTypeChart/UpdatesPerEnvironmentTypeChart';
|
2024-01-22 11:07:38 +01:00
|
|
|
|
|
|
|
const StyledGrid = styled(Box)(({ theme }) => ({
|
|
|
|
display: 'grid',
|
2024-03-04 12:56:17 +01:00
|
|
|
gridTemplateColumns: `repeat(2, 1fr)`,
|
2024-01-30 09:00:06 +01:00
|
|
|
gridAutoRows: 'auto',
|
2024-01-22 11:07:38 +01:00
|
|
|
gap: theme.spacing(2),
|
2024-03-04 12:56:17 +01:00
|
|
|
paddingBottom: theme.spacing(2),
|
|
|
|
[theme.breakpoints.up('md')]: {
|
|
|
|
gridTemplateColumns: `300px 1fr`,
|
|
|
|
},
|
2024-01-22 11:07:38 +01:00
|
|
|
}));
|
2024-01-18 12:32:25 +01:00
|
|
|
|
2024-03-04 12:56:17 +01:00
|
|
|
const ChartWidget = styled(Widget)(({ theme }) => ({
|
|
|
|
[theme.breakpoints.down('md')]: {
|
|
|
|
gridColumnStart: 'span 2',
|
|
|
|
order: 2,
|
2024-03-01 13:28:57 +01:00
|
|
|
},
|
|
|
|
}));
|
|
|
|
|
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-03-04 12:56:17 +01:00
|
|
|
const stateConfig = {
|
|
|
|
projects: withDefault(ArrayParam, [allOption.id]),
|
|
|
|
};
|
2024-03-06 12:19:27 +01:00
|
|
|
const [state, setState] = usePersistentTableState('insights', stateConfig);
|
2024-03-04 12:56:17 +01:00
|
|
|
const setProjects = (projects: string[]) => {
|
|
|
|
setState({ projects });
|
|
|
|
};
|
|
|
|
const projects = state.projects
|
|
|
|
? (state.projects.filter(Boolean) as string[])
|
|
|
|
: [];
|
|
|
|
const showAllProjects = projects[0] === allOption.id;
|
|
|
|
const projectsData = useFilteredTrends(
|
|
|
|
executiveDashboardData.projectFlagTrends,
|
|
|
|
projects,
|
|
|
|
);
|
|
|
|
const metricsData = useFilteredTrends(
|
|
|
|
executiveDashboardData.metricsSummaryTrends,
|
|
|
|
projects,
|
|
|
|
);
|
2024-03-07 10:00:18 +01:00
|
|
|
|
|
|
|
const { users, environmentTypeTrends } = executiveDashboardData;
|
2024-02-19 15:28:03 +01:00
|
|
|
|
2024-03-04 12:56:17 +01:00
|
|
|
const summary = useFilteredFlagsSummary(projectsData);
|
|
|
|
const isOneProjectSelected = projects.length === 1;
|
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-03-04 12:56:17 +01:00
|
|
|
<DashboardHeader
|
|
|
|
actions={
|
|
|
|
<ProjectSelect
|
|
|
|
selectedProjects={projects}
|
|
|
|
onChange={setProjects}
|
|
|
|
dataTestId={'DASHBOARD_PROJECT_SELECT'}
|
2024-03-06 12:19:27 +01:00
|
|
|
sx={{ flex: 1, maxWidth: '360px', width: '100%' }}
|
2024-03-04 12:56:17 +01:00
|
|
|
/>
|
|
|
|
}
|
|
|
|
/>
|
2024-01-22 11:07:38 +01:00
|
|
|
</Box>
|
2024-03-04 12:56:17 +01:00
|
|
|
<StyledGrid>
|
|
|
|
<ConditionallyRender
|
|
|
|
condition={showAllProjects}
|
|
|
|
show={
|
|
|
|
<Widget title='Total users'>
|
|
|
|
<UserStats
|
|
|
|
count={users.total}
|
|
|
|
active={users.active}
|
|
|
|
inactive={users.inactive}
|
|
|
|
/>
|
|
|
|
</Widget>
|
|
|
|
}
|
|
|
|
elseShow={
|
|
|
|
<Widget
|
|
|
|
title={
|
|
|
|
isOneProjectSelected
|
|
|
|
? 'Users in project'
|
|
|
|
: 'Users per project on average'
|
|
|
|
}
|
|
|
|
>
|
|
|
|
<UserStats count={summary.averageUsers} />
|
|
|
|
</Widget>
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
<ConditionallyRender
|
|
|
|
condition={showAllProjects}
|
|
|
|
show={
|
|
|
|
<ChartWidget title='Users'>
|
|
|
|
<UsersChart
|
|
|
|
userTrends={executiveDashboardData.userTrends}
|
|
|
|
isLoading={loading}
|
|
|
|
/>
|
|
|
|
</ChartWidget>
|
|
|
|
}
|
|
|
|
elseShow={
|
|
|
|
<ChartWidget title='Users per project'>
|
|
|
|
<UsersPerProjectChart
|
|
|
|
projectFlagTrends={projectsData}
|
|
|
|
/>
|
|
|
|
</ChartWidget>
|
|
|
|
}
|
|
|
|
/>
|
2024-01-30 17:02:13 +01:00
|
|
|
<Widget
|
|
|
|
title='Total flags'
|
2024-03-04 12:56:17 +01:00
|
|
|
tooltip='Active flags (not archived) that currently exist across selected projects.'
|
2024-01-30 17:02:13 +01:00
|
|
|
>
|
|
|
|
<FlagStats
|
2024-03-04 12:56:17 +01:00
|
|
|
count={summary.total}
|
|
|
|
flagsPerUser={
|
|
|
|
showAllProjects
|
|
|
|
? (summary.total / users.total).toFixed(2)
|
|
|
|
: ''
|
|
|
|
}
|
2024-01-30 17:02:13 +01:00
|
|
|
/>
|
|
|
|
</Widget>
|
2024-03-04 12:56:17 +01:00
|
|
|
<ConditionallyRender
|
|
|
|
condition={showAllProjects}
|
|
|
|
show={
|
|
|
|
<ChartWidget title='Number of flags'>
|
|
|
|
<FlagsChart
|
|
|
|
flagTrends={executiveDashboardData.flagTrends}
|
|
|
|
isLoading={loading}
|
|
|
|
/>
|
|
|
|
</ChartWidget>
|
|
|
|
}
|
|
|
|
elseShow={
|
|
|
|
<ChartWidget title='Flags per project'>
|
|
|
|
<FlagsProjectChart
|
|
|
|
projectFlagTrends={projectsData}
|
|
|
|
/>
|
|
|
|
</ChartWidget>
|
|
|
|
}
|
2024-03-01 13:28:57 +01:00
|
|
|
/>
|
2024-03-06 12:19:27 +01:00
|
|
|
<Widget
|
|
|
|
title='Average health'
|
|
|
|
tooltip='Average health is a percentage of flags that are not stale nor potencially stale.'
|
|
|
|
>
|
2024-02-23 09:05:59 +01:00
|
|
|
<HealthStats
|
2024-03-04 12:56:17 +01:00
|
|
|
value={summary.averageHealth}
|
|
|
|
healthy={summary.active}
|
|
|
|
stale={summary.stale}
|
|
|
|
potentiallyStale={summary.potentiallyStale}
|
2024-01-31 13:19:28 +01:00
|
|
|
/>
|
|
|
|
</Widget>
|
2024-03-04 12:56:17 +01:00
|
|
|
<ChartWidget
|
|
|
|
title={
|
|
|
|
showAllProjects ? 'Healthy flags' : 'Health per project'
|
|
|
|
}
|
2024-02-23 14:17:58 +01:00
|
|
|
>
|
2024-03-04 12:56:17 +01:00
|
|
|
<ProjectHealthChart
|
|
|
|
projectFlagTrends={projectsData}
|
|
|
|
isAggregate={showAllProjects}
|
2024-02-23 14:17:58 +01:00
|
|
|
/>
|
2024-03-04 12:56:17 +01:00
|
|
|
</ChartWidget>
|
|
|
|
{/* <Widget title='Average time to production'>
|
2024-02-23 09:05:59 +01:00
|
|
|
<TimeToProduction
|
2024-03-04 12:56:17 +01:00
|
|
|
//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-03-04 12:56:17 +01:00
|
|
|
<ChartWidget title='Time to production'>
|
|
|
|
<TimeToProductionChart projectFlagTrends={projectsData} />
|
|
|
|
</ChartWidget> */}
|
2024-01-22 11:07:38 +01:00
|
|
|
</StyledGrid>
|
2024-03-06 12:19:27 +01:00
|
|
|
<Widget
|
|
|
|
title='Metrics'
|
|
|
|
tooltip='Summary of all flag evaluations reported by SDKs.'
|
|
|
|
>
|
2024-03-04 12:56:17 +01:00
|
|
|
<MetricsSummaryChart metricsSummaryTrends={metricsData} />
|
|
|
|
</Widget>
|
2024-03-07 10:00:18 +01:00
|
|
|
<Widget
|
|
|
|
title='Updates per environment type'
|
|
|
|
tooltip='Summary of all configuration updates per environment type'
|
|
|
|
sx={{ mt: (theme) => theme.spacing(2) }}
|
|
|
|
>
|
|
|
|
<UpdatesPerEnvironmentTypeChart
|
|
|
|
environmentTypeTrends={environmentTypeTrends}
|
|
|
|
isLoading={loading}
|
|
|
|
/>
|
|
|
|
</Widget>
|
2024-01-22 11:07:38 +01:00
|
|
|
</>
|
|
|
|
);
|
2024-01-18 12:32:25 +01:00
|
|
|
};
|