Skip to content

Commit

Permalink
feat: connect dashboard static widgets to data (#6062)
Browse files Browse the repository at this point in the history
This PR connects the static widgets to actual data
  • Loading branch information
FredrikOseberg committed Jan 30, 2024
1 parent 832884b commit 7d6d406
Show file tree
Hide file tree
Showing 23 changed files with 197 additions and 124 deletions.
26 changes: 19 additions & 7 deletions frontend/src/component/executiveDashboard/ExecutiveDashboard.tsx
Expand Up @@ -18,6 +18,19 @@ const StyledGrid = styled(Box)(({ theme }) => ({
export const ExecutiveDashboard: VFC = () => {
const { executiveDashboardData, loading, error } = useExecutiveDashboard();

const calculateFlagPerUsers = () => {
if (
executiveDashboardData.users.total === 0 ||
executiveDashboardData.flags.total === 0
)
return '0';

return (
executiveDashboardData.flags.total /
executiveDashboardData.users.total
).toFixed(1);
};

return (
<>
<Box sx={(theme) => ({ paddingBottom: theme.spacing(4) })}>
Expand All @@ -30,14 +43,13 @@ export const ExecutiveDashboard: VFC = () => {
/>
</Box>
<StyledGrid>
<UserStats />
<UsersChart
userTrends={executiveDashboardData?.userTrends ?? []}
/>
<FlagStats />
<FlagsChart
flagsTrends={executiveDashboardData?.flagsTrends ?? []}
<UserStats count={executiveDashboardData.users.total} />
<FlagStats
count={executiveDashboardData.flags.total}
flagsPerUser={calculateFlagPerUsers()}
/>
<UsersChart userTrends={executiveDashboardData.userTrends} />
<FlagsChart flagTrends={executiveDashboardData.flagTrends} />
</StyledGrid>
</>
);
Expand Down
14 changes: 11 additions & 3 deletions frontend/src/component/executiveDashboard/FlagStats/FlagStats.tsx
Expand Up @@ -78,7 +78,15 @@ const StyledSettingsIcon = styled(Settings)(({ theme }) => ({
marginRight: theme.spacing(0.5),
}));

export const FlagStats = () => {
interface IFlagStatsProps {
count: number;
flagsPerUser: string;
}

export const FlagStats: React.FC<IFlagStatsProps> = ({
count,
flagsPerUser,
}) => {
return (
<StyledContent>
<StyledHeader variant='h1'>
Expand All @@ -98,7 +106,7 @@ export const FlagStats = () => {
</StyledHeader>
<StyledRingContainer>
<StyledRing>
<StyledRingContent>9999</StyledRingContent>
<StyledRingContent>{count}</StyledRingContent>
</StyledRing>
</StyledRingContainer>

Expand All @@ -116,7 +124,7 @@ export const FlagStats = () => {
</StyledHeaderContainer>
<Typography variant='body2'>Flags per user</Typography>
</StyledTextContainer>
<StyledFlagCountPerUser>3.5</StyledFlagCountPerUser>
<StyledFlagCountPerUser>{flagsPerUser}</StyledFlagCountPerUser>
</StyledInsightsContainer>
</StyledContent>
);
Expand Down
Expand Up @@ -22,27 +22,27 @@ import { ExecutiveSummarySchema } from 'openapi';

const createData = (
theme: Theme,
flagsTrends: ExecutiveSummarySchema['flagsTrends'] = [],
flagTrends: ExecutiveSummarySchema['flagTrends'] = [],
) => ({
labels: flagsTrends.map((item) => item.date),
labels: flagTrends.map((item) => item.date),
datasets: [
{
label: 'Total flags',
data: flagsTrends.map((item) => item.total),
data: flagTrends.map((item) => item.total),
borderColor: theme.palette.primary.main,
backgroundColor: theme.palette.primary.main,
fill: true,
},
{
label: 'Archived flags',
data: flagsTrends.map((item) => item.archived),
borderColor: theme.palette.error.main,
backgroundColor: theme.palette.error.main,
label: 'Stale',
data: flagTrends.map((item) => item.stale),
borderColor: theme.palette.warning.main,
backgroundColor: theme.palette.warning.main,
fill: true,
},
{
label: 'Active flags',
data: flagsTrends.map((item) => item.active),
data: flagTrends.map((item) => item.active),
borderColor: theme.palette.success.main,
backgroundColor: theme.palette.success.main,
fill: true,
Expand Down Expand Up @@ -102,17 +102,17 @@ const createOptions = (theme: Theme, locationSettings: ILocationSettings) =>
}) as const;

interface IFlagsChartComponentProps {
flagsTrends: ExecutiveSummarySchema['flagsTrends'];
flagTrends: ExecutiveSummarySchema['flagTrends'];
}

const FlagsChartComponent: VFC<IFlagsChartComponentProps> = ({
flagsTrends,
flagTrends,
}) => {
const theme = useTheme();
const { locationSettings } = useLocationSettings();
const data = useMemo(
() => createData(theme, flagsTrends),
[theme, flagsTrends],
() => createData(theme, flagTrends),
[theme, flagTrends],
);
const options = createOptions(theme, locationSettings);

Expand Down
88 changes: 55 additions & 33 deletions frontend/src/component/executiveDashboard/UserStats/UserStats.tsx
@@ -1,5 +1,8 @@
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 React from 'react';
import { Link } from 'react-router-dom';

const StyledContent = styled(Box)(({ theme }) => ({
Expand Down Expand Up @@ -73,40 +76,59 @@ const StyledLink = styled(Link)({
justifyContent: 'center',
});

export const UserStats = () => {
interface IUserStatsProps {
count: number;
}

export const UserStats: React.FC<IUserStatsProps> = ({ count }) => {
const showInactiveUsers = useUiFlag('showInactiveUsers');

return (
<StyledContent>
<StyledHeader variant='h1'>Total users</StyledHeader>
<StyledUserContainer>
<StyledUserBox>
<StyledUserCount variant='h2'>9999</StyledUserCount>
</StyledUserBox>
<StyledCustomShadow />
</StyledUserContainer>

<StyledUserDistributionContainer>
<UserDistribution />
</StyledUserDistributionContainer>

<StyledDistInfoContainer>
<UserDistributionInfo
type='active'
percentage='70'
count='9999'
/>
<UserDistributionInfo
type='inactive'
percentage='30'
count='9999'
/>
</StyledDistInfoContainer>

<StyledLinkContainer>
<StyledLink to='/admin/users'>
View users <ChevronRight />
</StyledLink>
</StyledLinkContainer>
</StyledContent>
<>
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
<StyledContent>
<StyledHeader variant='h1'>Total users</StyledHeader>
<StyledUserContainer>
<StyledUserBox>
<StyledUserCount variant='h2'>
{count}
</StyledUserCount>
</StyledUserBox>
<StyledCustomShadow />
</StyledUserContainer>

<ConditionallyRender
condition={showInactiveUsers}
show={
<>
<StyledUserDistributionContainer>
<UserDistribution />
</StyledUserDistributionContainer>

<StyledDistInfoContainer>
<UserDistributionInfo
type='active'
percentage='70'
count='9999'
/>
<UserDistributionInfo
type='inactive'
percentage='30'
count='9999'
/>
</StyledDistInfoContainer>
</>
}
/>

<StyledLinkContainer>
<StyledLink to='/admin/users'>
View users <ChevronRight />
</StyledLink>
</StyledLinkContainer>
</StyledContent>
</Box>
</>
);
};

Expand Down
Expand Up @@ -5,7 +5,7 @@ import handleErrorResponses from '../httpErrorResponseHandler';
import { ExecutiveSummarySchema } from 'openapi';

interface IUseExecutiveDashboardDataOutput {
executiveDashboardData: ExecutiveSummarySchema | undefined;
executiveDashboardData: ExecutiveSummarySchema;
refetchExecutiveDashboard: () => void;
loading: boolean;
error?: Error;
Expand All @@ -27,7 +27,12 @@ export const useExecutiveDashboard = (
}, [path]);

return {
executiveDashboardData: data,
executiveDashboardData: data || {
users: { total: 0, inactive: 0, active: 0 },
flags: { total: 0 },
userTrends: [],
flagTrends: [],
},
refetchExecutiveDashboard,
loading: !error && !data,
error,
Expand Down
1 change: 1 addition & 0 deletions frontend/src/interfaces/uiConfig.ts
Expand Up @@ -80,6 +80,7 @@ export type UiFlags = {
changeRequestConflictHandling?: boolean;
feedbackComments?: Variant;
displayUpgradeEdgeBanner?: boolean;
showInactiveUsers?: boolean;
};

export interface IVersionInfo {
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/openapi/models/actionsListSchema.ts
Expand Up @@ -3,12 +3,12 @@
* Do not edit manually.
* See `gen:api` script in package.json
*/
import type { CreateActionsSchema } from './createActionsSchema';
import type { ActionsSchema } from './actionsSchema';

/**
* A response model with a list of action sets.
*/
export interface ActionsListSchema {
/** A list of action sets. */
actions: CreateActionsSchema[];
actions: ActionsSchema[];
}
2 changes: 2 additions & 0 deletions frontend/src/openapi/models/actionsSchema.ts
Expand Up @@ -18,6 +18,8 @@ export interface ActionsSchema {
createdAt?: string;
/** The id of user that created this action set */
createdByUserId?: number;
/** Whether this action set is enabled or not */
enabled?: boolean;
/** The id of the action set */
id: number;
/** Defines a matching rule for the observable event that will trigger the action set */
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/openapi/models/createActionsSchema.ts
Expand Up @@ -14,6 +14,8 @@ export interface CreateActionsSchema {
actions: CreateActionSchema[];
/** The id of the service account that will execute the action */
actorId: number;
/** Whether this action set is enabled or not */
enabled?: boolean;
/** Defines a matching rule for the observable event that will trigger the action set */
match: CreateActionsSchemaMatch;
/** The name of the action set */
Expand Down
13 changes: 7 additions & 6 deletions frontend/src/openapi/models/executiveSummarySchema.ts
Expand Up @@ -3,20 +3,21 @@
* Do not edit manually.
* See `gen:api` script in package.json
*/
import type { ExecutiveSummarySchemaFlagsTrendsItem } from './executiveSummarySchemaFlagsTrendsItem';
import type { ExecutiveSummarySchemaUserStats } from './executiveSummarySchemaUserStats';
import type { ExecutiveSummarySchemaFlags } from './executiveSummarySchemaFlags';
import type { ExecutiveSummarySchemaFlagTrendsItem } from './executiveSummarySchemaFlagTrendsItem';
import type { ExecutiveSummarySchemaUsers } from './executiveSummarySchemaUsers';
import type { ExecutiveSummarySchemaUserTrendsItem } from './executiveSummarySchemaUserTrendsItem';

/**
* Executive summary of Unleash usage
*/
export interface ExecutiveSummarySchema {
/** High level flag count statistics */
flags: ExecutiveSummarySchemaFlags;
/** How number of flags changed over time */
flagsTrends: ExecutiveSummarySchemaFlagsTrendsItem[];
/** The type of single-sign option configured for the Unleash instance */
ssoType?: string;
flagTrends: ExecutiveSummarySchemaFlagTrendsItem[];
/** High level user count statistics */
userStats: ExecutiveSummarySchemaUserStats;
users: ExecutiveSummarySchemaUsers;
/** How number of users changed over time */
userTrends: ExecutiveSummarySchemaUserTrendsItem[];
}
@@ -0,0 +1,18 @@
/**
* Generated by Orval
* Do not edit manually.
* See `gen:api` script in package.json
*/

export type ExecutiveSummarySchemaFlagTrendsItem = {
/** The number of active flags on a particular day */
active: number;
/** A UTC date when the stats were captured. Time is the very end of a given day. */
date: string;
/** The number of time calculated potentially stale flags on a particular day */
potentiallyStale?: number;
/** The number of user marked stale flags on a particular day */
stale: number;
/** The number of all flags on a particular day */
total: number;
};
13 changes: 13 additions & 0 deletions frontend/src/openapi/models/executiveSummarySchemaFlags.ts
@@ -0,0 +1,13 @@
/**
* Generated by Orval
* Do not edit manually.
* See `gen:api` script in package.json
*/

/**
* High level flag count statistics
*/
export type ExecutiveSummarySchemaFlags = {
/** The number of non-archived flags */
total: number;
};

This file was deleted.

0 comments on commit 7d6d406

Please sign in to comment.