mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	feat: updates per environment type chart (#6449)
Creates the updates per environment type chart. (forgive the sample data) Closes # [1-2034](https://linear.app/unleash/issue/1-2034/widget-updates-per-environment-type-frontend) <img width="1385" alt="Screenshot 2024-03-06 at 16 52 18" src="https://github.com/Unleash/unleash/assets/104830839/b05479f8-de8b-4de7-98a3-a1285737db0d"> --------- Signed-off-by: andreas-unleash <andreas@getunleash.ai>
This commit is contained in:
		
							parent
							
								
									4a8faacbd8
								
							
						
					
					
						commit
						ec6c439c09
					
				@ -25,6 +25,7 @@ import { FlagsProjectChart } from './componentsChart/FlagsProjectChart/FlagsProj
 | 
				
			|||||||
import { ProjectHealthChart } from './componentsChart/ProjectHealthChart/ProjectHealthChart';
 | 
					import { ProjectHealthChart } from './componentsChart/ProjectHealthChart/ProjectHealthChart';
 | 
				
			||||||
import { MetricsSummaryChart } from './componentsChart/MetricsSummaryChart/MetricsSummaryChart';
 | 
					import { MetricsSummaryChart } from './componentsChart/MetricsSummaryChart/MetricsSummaryChart';
 | 
				
			||||||
import { UsersPerProjectChart } from './componentsChart/UsersPerProjectChart/UsersPerProjectChart';
 | 
					import { UsersPerProjectChart } from './componentsChart/UsersPerProjectChart/UsersPerProjectChart';
 | 
				
			||||||
 | 
					import { UpdatesPerEnvironmentTypeChart } from './componentsChart/UpdatesPerEnvironmentTypeChart/UpdatesPerEnvironmentTypeChart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledGrid = styled(Box)(({ theme }) => ({
 | 
					const StyledGrid = styled(Box)(({ theme }) => ({
 | 
				
			||||||
    display: 'grid',
 | 
					    display: 'grid',
 | 
				
			||||||
@ -65,7 +66,8 @@ export const ExecutiveDashboard: VFC = () => {
 | 
				
			|||||||
        executiveDashboardData.metricsSummaryTrends,
 | 
					        executiveDashboardData.metricsSummaryTrends,
 | 
				
			||||||
        projects,
 | 
					        projects,
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    const { users } = executiveDashboardData;
 | 
					
 | 
				
			||||||
 | 
					    const { users, environmentTypeTrends } = executiveDashboardData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const summary = useFilteredFlagsSummary(projectsData);
 | 
					    const summary = useFilteredFlagsSummary(projectsData);
 | 
				
			||||||
    const isOneProjectSelected = projects.length === 1;
 | 
					    const isOneProjectSelected = projects.length === 1;
 | 
				
			||||||
@ -194,6 +196,16 @@ export const ExecutiveDashboard: VFC = () => {
 | 
				
			|||||||
            >
 | 
					            >
 | 
				
			||||||
                <MetricsSummaryChart metricsSummaryTrends={metricsData} />
 | 
					                <MetricsSummaryChart metricsSummaryTrends={metricsData} />
 | 
				
			||||||
            </Widget>
 | 
					            </Widget>
 | 
				
			||||||
 | 
					            <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>
 | 
				
			||||||
        </>
 | 
					        </>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,8 @@
 | 
				
			|||||||
import { FC, ReactNode } from 'react';
 | 
					import { FC, ReactNode } from 'react';
 | 
				
			||||||
import { Paper, Typography, styled } from '@mui/material';
 | 
					import { Paper, Typography, styled, SxProps } from '@mui/material';
 | 
				
			||||||
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
 | 
					import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
 | 
				
			||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
					import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
 | 
				
			||||||
 | 
					import { Theme } from '@mui/material/styles/createTheme';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const StyledPaper = styled(Paper)(({ theme }) => ({
 | 
					const StyledPaper = styled(Paper)(({ theme }) => ({
 | 
				
			||||||
    padding: theme.spacing(3),
 | 
					    padding: theme.spacing(3),
 | 
				
			||||||
@ -13,6 +14,7 @@ const StyledPaper = styled(Paper)(({ theme }) => ({
 | 
				
			|||||||
export const Widget: FC<{
 | 
					export const Widget: FC<{
 | 
				
			||||||
    title: ReactNode;
 | 
					    title: ReactNode;
 | 
				
			||||||
    tooltip?: ReactNode;
 | 
					    tooltip?: ReactNode;
 | 
				
			||||||
 | 
					    sx?: SxProps<Theme>;
 | 
				
			||||||
}> = ({ title, children, tooltip, ...rest }) => (
 | 
					}> = ({ title, children, tooltip, ...rest }) => (
 | 
				
			||||||
    <StyledPaper elevation={0} {...rest}>
 | 
					    <StyledPaper elevation={0} {...rest}>
 | 
				
			||||||
        <Typography
 | 
					        <Typography
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,73 @@
 | 
				
			|||||||
 | 
					import { useMemo, type VFC } from 'react';
 | 
				
			||||||
 | 
					import 'chartjs-adapter-date-fns';
 | 
				
			||||||
 | 
					import { useTheme } from '@mui/material';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					    ExecutiveSummarySchema,
 | 
				
			||||||
 | 
					    ExecutiveSummarySchemaEnvironmentTypeTrendsItem,
 | 
				
			||||||
 | 
					} from 'openapi';
 | 
				
			||||||
 | 
					import { LineChart, NotEnoughData } from '../../components/LineChart/LineChart';
 | 
				
			||||||
 | 
					import { usePlaceholderData } from 'component/executiveDashboard/hooks/usePlaceholderData';
 | 
				
			||||||
 | 
					import { getProjectColor } from '../../executive-dashboard-utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface IUpdatesPerEnvironmnetTypeChart {
 | 
				
			||||||
 | 
					    environmentTypeTrends: ExecutiveSummarySchema['environmentTypeTrends'];
 | 
				
			||||||
 | 
					    isLoading?: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const groupByDate = (
 | 
				
			||||||
 | 
					    items: ExecutiveSummarySchemaEnvironmentTypeTrendsItem[],
 | 
				
			||||||
 | 
					): Record<string, ExecutiveSummarySchemaEnvironmentTypeTrendsItem[]> => {
 | 
				
			||||||
 | 
					    if (!items) {
 | 
				
			||||||
 | 
					        return {};
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const grouped = items.reduce(
 | 
				
			||||||
 | 
					        (acc, item) => {
 | 
				
			||||||
 | 
					            const key = item.environmentType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (!acc[key]) {
 | 
				
			||||||
 | 
					                acc[key] = [];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            acc[key].push(item);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return acc;
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        {} as Record<string, ExecutiveSummarySchemaEnvironmentTypeTrendsItem[]>,
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return grouped;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const UpdatesPerEnvironmentTypeChart: VFC<
 | 
				
			||||||
 | 
					    IUpdatesPerEnvironmnetTypeChart
 | 
				
			||||||
 | 
					> = ({ environmentTypeTrends, isLoading }) => {
 | 
				
			||||||
 | 
					    const theme = useTheme();
 | 
				
			||||||
 | 
					    const notEnoughData = environmentTypeTrends?.length < 2;
 | 
				
			||||||
 | 
					    const placeholderData = usePlaceholderData({ fill: true, type: 'double' });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const data = useMemo(() => {
 | 
				
			||||||
 | 
					        const grouped = groupByDate(environmentTypeTrends);
 | 
				
			||||||
 | 
					        const labels = environmentTypeTrends?.map((item) => item.date);
 | 
				
			||||||
 | 
					        const datasets = Object.entries(grouped).map(
 | 
				
			||||||
 | 
					            ([environmentType, trends]) => {
 | 
				
			||||||
 | 
					                const color = getProjectColor(environmentType);
 | 
				
			||||||
 | 
					                return {
 | 
				
			||||||
 | 
					                    label: environmentType,
 | 
				
			||||||
 | 
					                    data: trends.map((item) => item.totalUpdates),
 | 
				
			||||||
 | 
					                    borderColor: color,
 | 
				
			||||||
 | 
					                    backgroundColor: color,
 | 
				
			||||||
 | 
					                    fill: false,
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					        return { labels, datasets };
 | 
				
			||||||
 | 
					    }, [theme, environmentTypeTrends]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <LineChart
 | 
				
			||||||
 | 
					            data={notEnoughData || isLoading ? placeholderData : data}
 | 
				
			||||||
 | 
					            cover={notEnoughData ? <NotEnoughData /> : isLoading}
 | 
				
			||||||
 | 
					        />
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -0,0 +1,117 @@
 | 
				
			|||||||
 | 
					import { type VFC } from 'react';
 | 
				
			||||||
 | 
					import { ExecutiveSummarySchemaEnvironmentTypeTrendsItem } from 'openapi';
 | 
				
			||||||
 | 
					import { Box, Divider, Paper, styled, Typography } from '@mui/material';
 | 
				
			||||||
 | 
					import { TooltipState } from '../../../components/LineChart/ChartTooltip/ChartTooltip';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 InfoLine = ({
 | 
				
			||||||
 | 
					    iconChar,
 | 
				
			||||||
 | 
					    title,
 | 
				
			||||||
 | 
					    color,
 | 
				
			||||||
 | 
					}: {
 | 
				
			||||||
 | 
					    iconChar: string;
 | 
				
			||||||
 | 
					    title: string;
 | 
				
			||||||
 | 
					    color: 'info' | 'success' | 'error';
 | 
				
			||||||
 | 
					}) => (
 | 
				
			||||||
 | 
					    <Typography
 | 
				
			||||||
 | 
					        variant='body2'
 | 
				
			||||||
 | 
					        component='p'
 | 
				
			||||||
 | 
					        sx={{
 | 
				
			||||||
 | 
					            color: (theme) => theme.palette[color].main,
 | 
				
			||||||
 | 
					        }}
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					        <Typography component='span'>{iconChar}</Typography>
 | 
				
			||||||
 | 
					        <strong>{title}</strong>
 | 
				
			||||||
 | 
					    </Typography>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const InfoSummary = ({ data }: { data: { key: string; value: number }[] }) => (
 | 
				
			||||||
 | 
					    <Typography variant={'body1'} component={'p'}>
 | 
				
			||||||
 | 
					        <Box display={'flex'} flexDirection={'row'}>
 | 
				
			||||||
 | 
					            {data.map(({ key, value }) => (
 | 
				
			||||||
 | 
					                <div style={{ flex: 1, flexDirection: 'column' }}>
 | 
				
			||||||
 | 
					                    <div
 | 
				
			||||||
 | 
					                        style={{
 | 
				
			||||||
 | 
					                            flex: 1,
 | 
				
			||||||
 | 
					                            textAlign: 'center',
 | 
				
			||||||
 | 
					                            marginBottom: '4px',
 | 
				
			||||||
 | 
					                        }}
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                        {key}
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                    <div style={{ flex: 1, textAlign: 'center' }}>{value}</div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            ))}
 | 
				
			||||||
 | 
					        </Box>
 | 
				
			||||||
 | 
					    </Typography>
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const UpdatesPerEnvironmentTypeChartTooltip: 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 ExecutiveSummarySchemaEnvironmentTypeTrendsItem,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const limitedData = data?.slice(0, 5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (
 | 
				
			||||||
 | 
					        <Box
 | 
				
			||||||
 | 
					            sx={(theme) => ({
 | 
				
			||||||
 | 
					                display: 'flex',
 | 
				
			||||||
 | 
					                flexDirection: 'column',
 | 
				
			||||||
 | 
					                gap: theme.spacing(2),
 | 
				
			||||||
 | 
					                width: '300px',
 | 
				
			||||||
 | 
					            })}
 | 
				
			||||||
 | 
					        >
 | 
				
			||||||
 | 
					            {limitedData?.map((point, index) => (
 | 
				
			||||||
 | 
					                <StyledTooltipItemContainer
 | 
				
			||||||
 | 
					                    elevation={3}
 | 
				
			||||||
 | 
					                    key={`${point.title}-${index}`}
 | 
				
			||||||
 | 
					                >
 | 
				
			||||||
 | 
					                    <StyledItemHeader>
 | 
				
			||||||
 | 
					                        <Typography variant='body2' component='span'>
 | 
				
			||||||
 | 
					                            <Typography
 | 
				
			||||||
 | 
					                                sx={{ color: point.color }}
 | 
				
			||||||
 | 
					                                component='span'
 | 
				
			||||||
 | 
					                            >
 | 
				
			||||||
 | 
					                                {'● '}
 | 
				
			||||||
 | 
					                            </Typography>
 | 
				
			||||||
 | 
					                            <strong>{point.title}</strong>
 | 
				
			||||||
 | 
					                        </Typography>
 | 
				
			||||||
 | 
					                        <Typography
 | 
				
			||||||
 | 
					                            variant='body2'
 | 
				
			||||||
 | 
					                            color='textSecondary'
 | 
				
			||||||
 | 
					                            component='span'
 | 
				
			||||||
 | 
					                        >
 | 
				
			||||||
 | 
					                            {point.label}
 | 
				
			||||||
 | 
					                        </Typography>
 | 
				
			||||||
 | 
					                    </StyledItemHeader>
 | 
				
			||||||
 | 
					                    <Divider
 | 
				
			||||||
 | 
					                        sx={(theme) => ({ margin: theme.spacing(1.5, 0) })}
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                    <InfoLine
 | 
				
			||||||
 | 
					                        iconChar={'● '}
 | 
				
			||||||
 | 
					                        title={`Total updates: ${point.value.totalUpdates}`}
 | 
				
			||||||
 | 
					                        color={'info'}
 | 
				
			||||||
 | 
					                    />
 | 
				
			||||||
 | 
					                </StyledTooltipItemContainer>
 | 
				
			||||||
 | 
					            )) || null}
 | 
				
			||||||
 | 
					        </Box>
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -34,6 +34,7 @@ export const useExecutiveDashboard = (
 | 
				
			|||||||
            flagTrends: [],
 | 
					            flagTrends: [],
 | 
				
			||||||
            projectFlagTrends: [],
 | 
					            projectFlagTrends: [],
 | 
				
			||||||
            metricsSummaryTrends: [],
 | 
					            metricsSummaryTrends: [],
 | 
				
			||||||
 | 
					            environmentTypeTrends: [],
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        refetchExecutiveDashboard,
 | 
					        refetchExecutiveDashboard,
 | 
				
			||||||
        loading: !error && !data,
 | 
					        loading: !error && !data,
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@
 | 
				
			|||||||
 * Do not edit manually.
 | 
					 * Do not edit manually.
 | 
				
			||||||
 * See `gen:api` script in package.json
 | 
					 * See `gen:api` script in package.json
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					import type { ExecutiveSummarySchemaEnvironmentTypeTrendsItem } from './executiveSummarySchemaEnvironmentTypeTrendsItem';
 | 
				
			||||||
import type { ExecutiveSummarySchemaFlags } from './executiveSummarySchemaFlags';
 | 
					import type { ExecutiveSummarySchemaFlags } from './executiveSummarySchemaFlags';
 | 
				
			||||||
import type { ExecutiveSummarySchemaFlagTrendsItem } from './executiveSummarySchemaFlagTrendsItem';
 | 
					import type { ExecutiveSummarySchemaFlagTrendsItem } from './executiveSummarySchemaFlagTrendsItem';
 | 
				
			||||||
import type { ExecutiveSummarySchemaMetricsSummaryTrendsItem } from './executiveSummarySchemaMetricsSummaryTrendsItem';
 | 
					import type { ExecutiveSummarySchemaMetricsSummaryTrendsItem } from './executiveSummarySchemaMetricsSummaryTrendsItem';
 | 
				
			||||||
@ -14,6 +15,8 @@ import type { ExecutiveSummarySchemaUserTrendsItem } from './executiveSummarySch
 | 
				
			|||||||
 * Executive summary of Unleash usage
 | 
					 * Executive summary of Unleash usage
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export interface ExecutiveSummarySchema {
 | 
					export interface ExecutiveSummarySchema {
 | 
				
			||||||
 | 
					    /** How updates per environment type changed over time */
 | 
				
			||||||
 | 
					    environmentTypeTrends: ExecutiveSummarySchemaEnvironmentTypeTrendsItem[];
 | 
				
			||||||
    /** High level flag count statistics */
 | 
					    /** High level flag count statistics */
 | 
				
			||||||
    flags: ExecutiveSummarySchemaFlags;
 | 
					    flags: ExecutiveSummarySchemaFlags;
 | 
				
			||||||
    /** How number of flags changed over time */
 | 
					    /** How number of flags changed over time */
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Generated by Orval
 | 
				
			||||||
 | 
					 * Do not edit manually.
 | 
				
			||||||
 | 
					 * See `gen:api` script in package.json
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export type ExecutiveSummarySchemaEnvironmentTypeTrendsItem = {
 | 
				
			||||||
 | 
					    /** A UTC date when the stats were captured. Time is the very end of a given day. */
 | 
				
			||||||
 | 
					    date: string;
 | 
				
			||||||
 | 
					    /** Environment type the data belongs too */
 | 
				
			||||||
 | 
					    environmentType: string;
 | 
				
			||||||
 | 
					    /** Total number of times configuration has been updated in the environment type  */
 | 
				
			||||||
 | 
					    totalUpdates: number;
 | 
				
			||||||
 | 
					    /** Year and week in a given year for which the stats were calculated */
 | 
				
			||||||
 | 
					    week: string;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@ -5,6 +5,8 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type ExecutiveSummarySchemaMetricsSummaryTrendsItem = {
 | 
					export type ExecutiveSummarySchemaMetricsSummaryTrendsItem = {
 | 
				
			||||||
 | 
					    /** A UTC date when metrics summary was captured. Time is the very end of a given day. */
 | 
				
			||||||
 | 
					    date: string;
 | 
				
			||||||
    /** Project id of the project the impressions summary belong to */
 | 
					    /** Project id of the project the impressions summary belong to */
 | 
				
			||||||
    project: string;
 | 
					    project: string;
 | 
				
			||||||
    /** Total number of applications the impression data belong to */
 | 
					    /** Total number of applications the impression data belong to */
 | 
				
			||||||
 | 
				
			|||||||
@ -515,6 +515,7 @@ export * from './eventsSchema';
 | 
				
			|||||||
export * from './eventsSchemaVersion';
 | 
					export * from './eventsSchemaVersion';
 | 
				
			||||||
export * from './executiveSummarySchema';
 | 
					export * from './executiveSummarySchema';
 | 
				
			||||||
export * from './executiveSummarySchemaFlagTrendsItem';
 | 
					export * from './executiveSummarySchemaFlagTrendsItem';
 | 
				
			||||||
 | 
					export * from './executiveSummarySchemaEnvironmentTypeTrendsItem';
 | 
				
			||||||
export * from './executiveSummarySchemaFlags';
 | 
					export * from './executiveSummarySchemaFlags';
 | 
				
			||||||
export * from './executiveSummarySchemaMetricsSummaryTrendsItem';
 | 
					export * from './executiveSummarySchemaMetricsSummaryTrendsItem';
 | 
				
			||||||
export * from './executiveSummarySchemaProjectFlagTrendsItem';
 | 
					export * from './executiveSummarySchemaProjectFlagTrendsItem';
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user