mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
New insights layout - feature flag (#7598)
Preparing insights component for refactoring and enhancements.
This commit is contained in:
parent
7ed1d770a8
commit
7b2532ea4f
@ -10,6 +10,9 @@ import { useInsights } from 'hooks/api/getters/useInsights/useInsights';
|
||||
import { InsightsHeader } from './components/InsightsHeader/InsightsHeader';
|
||||
import { useInsightsData } from './hooks/useInsightsData';
|
||||
import { InsightsCharts } from './InsightsCharts';
|
||||
import { LegacyInsightsCharts } from './LegacyInsightsCharts';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
|
||||
const StickyWrapper = styled(Box, {
|
||||
shouldForwardProp: (prop) => prop !== 'scrolled',
|
||||
@ -50,6 +53,8 @@ export const Insights: VFC = () => {
|
||||
window.addEventListener('scroll', handleScroll);
|
||||
}
|
||||
|
||||
const isInsightsV2Enabled = useUiFlag('insightsV2');
|
||||
|
||||
return (
|
||||
<>
|
||||
<StickyWrapper scrolled={scrolled}>
|
||||
@ -69,10 +74,22 @@ export const Insights: VFC = () => {
|
||||
}
|
||||
/>
|
||||
</StickyWrapper>
|
||||
<InsightsCharts
|
||||
loading={loading}
|
||||
projects={projects}
|
||||
{...insightsData}
|
||||
<ConditionallyRender
|
||||
condition={isInsightsV2Enabled}
|
||||
show={
|
||||
<InsightsCharts
|
||||
loading={loading}
|
||||
projects={projects}
|
||||
{...insightsData}
|
||||
/>
|
||||
}
|
||||
elseShow={
|
||||
<LegacyInsightsCharts
|
||||
loading={loading}
|
||||
projects={projects}
|
||||
{...insightsData}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
251
frontend/src/component/insights/LegacyInsightsCharts.tsx
Normal file
251
frontend/src/component/insights/LegacyInsightsCharts.tsx
Normal file
@ -0,0 +1,251 @@
|
||||
import type { VFC } from 'react';
|
||||
import { Box, styled } from '@mui/material';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { Widget } from './components/Widget/Widget';
|
||||
import { UserStats } from './componentsStat/UserStats/UserStats';
|
||||
import { UsersChart } from './componentsChart/UsersChart/UsersChart';
|
||||
import { UsersPerProjectChart } from './componentsChart/UsersPerProjectChart/UsersPerProjectChart';
|
||||
import { FlagStats } from './componentsStat/FlagStats/FlagStats';
|
||||
import { FlagsChart } from './componentsChart/FlagsChart/FlagsChart';
|
||||
import { FlagsProjectChart } from './componentsChart/FlagsProjectChart/FlagsProjectChart';
|
||||
import { HealthStats } from './componentsStat/HealthStats/HealthStats';
|
||||
import { ProjectHealthChart } from './componentsChart/ProjectHealthChart/ProjectHealthChart';
|
||||
import { TimeToProduction } from './componentsStat/TimeToProduction/TimeToProduction';
|
||||
import { TimeToProductionChart } from './componentsChart/TimeToProductionChart/TimeToProductionChart';
|
||||
import { MetricsSummaryChart } from './componentsChart/MetricsSummaryChart/MetricsSummaryChart';
|
||||
import { UpdatesPerEnvironmentTypeChart } from './componentsChart/UpdatesPerEnvironmentTypeChart/UpdatesPerEnvironmentTypeChart';
|
||||
import type {
|
||||
InstanceInsightsSchema,
|
||||
InstanceInsightsSchemaFlags,
|
||||
InstanceInsightsSchemaUsers,
|
||||
} from 'openapi';
|
||||
import type { GroupedDataByProject } from './hooks/useGroupedProjectTrends';
|
||||
import { allOption } from 'component/common/ProjectSelect/ProjectSelect';
|
||||
import { chartInfo } from './chart-info';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
|
||||
interface IChartsProps {
|
||||
flags: InstanceInsightsSchema['flags'];
|
||||
flagTrends: InstanceInsightsSchema['flagTrends'];
|
||||
projectsData: InstanceInsightsSchema['projectFlagTrends'];
|
||||
groupedProjectsData: GroupedDataByProject<
|
||||
InstanceInsightsSchema['projectFlagTrends']
|
||||
>;
|
||||
metricsData: InstanceInsightsSchema['metricsSummaryTrends'];
|
||||
groupedMetricsData: GroupedDataByProject<
|
||||
InstanceInsightsSchema['metricsSummaryTrends']
|
||||
>;
|
||||
users: InstanceInsightsSchema['users'];
|
||||
userTrends: InstanceInsightsSchema['userTrends'];
|
||||
environmentTypeTrends: InstanceInsightsSchema['environmentTypeTrends'];
|
||||
summary: {
|
||||
total: number;
|
||||
active: number;
|
||||
stale: number;
|
||||
potentiallyStale: number;
|
||||
averageUsers: number;
|
||||
averageHealth?: string;
|
||||
flagsPerUser?: string;
|
||||
medianTimeToProduction?: number;
|
||||
};
|
||||
loading: boolean;
|
||||
projects: string[];
|
||||
allMetricsDatapoints: string[];
|
||||
}
|
||||
|
||||
const StyledGrid = styled(Box)(({ theme }) => ({
|
||||
display: 'grid',
|
||||
gridTemplateColumns: `repeat(2, 1fr)`,
|
||||
gridAutoRows: 'auto',
|
||||
gap: theme.spacing(2),
|
||||
paddingBottom: theme.spacing(2),
|
||||
[theme.breakpoints.up('md')]: {
|
||||
gridTemplateColumns: `300px 1fr`,
|
||||
},
|
||||
}));
|
||||
|
||||
const ChartWidget = styled(Widget)(({ theme }) => ({
|
||||
[theme.breakpoints.down('md')]: {
|
||||
gridColumnStart: 'span 2',
|
||||
order: 2,
|
||||
},
|
||||
}));
|
||||
|
||||
export const LegacyInsightsCharts: VFC<IChartsProps> = ({
|
||||
projects,
|
||||
flags,
|
||||
users,
|
||||
summary,
|
||||
userTrends,
|
||||
groupedProjectsData,
|
||||
flagTrends,
|
||||
groupedMetricsData,
|
||||
environmentTypeTrends,
|
||||
allMetricsDatapoints,
|
||||
loading,
|
||||
}) => {
|
||||
const { isEnterprise } = useUiConfig();
|
||||
const showAllProjects = projects[0] === allOption.id;
|
||||
const isOneProjectSelected = projects.length === 1;
|
||||
|
||||
function getFlagsPerUser(
|
||||
flags: InstanceInsightsSchemaFlags,
|
||||
users: InstanceInsightsSchemaUsers,
|
||||
) {
|
||||
const flagsPerUserCalculation = flags.total / users.total;
|
||||
return Number.isNaN(flagsPerUserCalculation)
|
||||
? 'N/A'
|
||||
: flagsPerUserCalculation.toFixed(2);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<StyledGrid>
|
||||
<ConditionallyRender
|
||||
condition={showAllProjects}
|
||||
show={
|
||||
<Widget {...chartInfo.totalUsers}>
|
||||
<UserStats
|
||||
count={users.total}
|
||||
active={users.active}
|
||||
inactive={users.inactive}
|
||||
isLoading={loading}
|
||||
/>
|
||||
</Widget>
|
||||
}
|
||||
elseShow={
|
||||
<Widget
|
||||
{...(isOneProjectSelected
|
||||
? chartInfo.usersInProject
|
||||
: chartInfo.avgUsersPerProject)}
|
||||
>
|
||||
<UserStats
|
||||
count={summary.averageUsers}
|
||||
isLoading={loading}
|
||||
/>
|
||||
</Widget>
|
||||
}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={showAllProjects}
|
||||
show={
|
||||
<ChartWidget {...chartInfo.users}>
|
||||
<UsersChart
|
||||
userTrends={userTrends}
|
||||
isLoading={loading}
|
||||
/>
|
||||
</ChartWidget>
|
||||
}
|
||||
elseShow={
|
||||
<ChartWidget {...chartInfo.usersPerProject}>
|
||||
<UsersPerProjectChart
|
||||
projectFlagTrends={groupedProjectsData}
|
||||
isLoading={loading}
|
||||
/>
|
||||
</ChartWidget>
|
||||
}
|
||||
/>
|
||||
<Widget {...chartInfo.totalFlags}>
|
||||
<FlagStats
|
||||
count={showAllProjects ? flags.total : summary.total}
|
||||
flagsPerUser={
|
||||
showAllProjects ? getFlagsPerUser(flags, users) : ''
|
||||
}
|
||||
isLoading={loading}
|
||||
/>
|
||||
</Widget>
|
||||
<ConditionallyRender
|
||||
condition={showAllProjects}
|
||||
show={
|
||||
<ChartWidget {...chartInfo.flags}>
|
||||
<FlagsChart
|
||||
flagTrends={flagTrends}
|
||||
isLoading={loading}
|
||||
/>
|
||||
</ChartWidget>
|
||||
}
|
||||
elseShow={
|
||||
<ChartWidget {...chartInfo.flagsPerProject}>
|
||||
<FlagsProjectChart
|
||||
projectFlagTrends={groupedProjectsData}
|
||||
isLoading={loading}
|
||||
/>
|
||||
</ChartWidget>
|
||||
}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={isEnterprise()}
|
||||
show={
|
||||
<>
|
||||
<Widget {...chartInfo.averageHealth}>
|
||||
<HealthStats
|
||||
value={summary.averageHealth}
|
||||
healthy={summary.active}
|
||||
stale={summary.stale}
|
||||
potentiallyStale={summary.potentiallyStale}
|
||||
/>
|
||||
</Widget>
|
||||
<ChartWidget
|
||||
{...(showAllProjects
|
||||
? chartInfo.overallHealth
|
||||
: chartInfo.healthPerProject)}
|
||||
>
|
||||
<ProjectHealthChart
|
||||
projectFlagTrends={groupedProjectsData}
|
||||
isAggregate={showAllProjects}
|
||||
isLoading={loading}
|
||||
/>
|
||||
</ChartWidget>
|
||||
<Widget {...chartInfo.medianTimeToProduction}>
|
||||
<TimeToProduction
|
||||
daysToProduction={
|
||||
summary.medianTimeToProduction
|
||||
}
|
||||
/>
|
||||
</Widget>
|
||||
<ChartWidget
|
||||
{...(showAllProjects
|
||||
? chartInfo.timeToProduction
|
||||
: chartInfo.timeToProductionPerProject)}
|
||||
>
|
||||
<TimeToProductionChart
|
||||
projectFlagTrends={groupedProjectsData}
|
||||
isAggregate={showAllProjects}
|
||||
isLoading={loading}
|
||||
/>
|
||||
</ChartWidget>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</StyledGrid>
|
||||
<ConditionallyRender
|
||||
condition={isEnterprise()}
|
||||
show={
|
||||
<>
|
||||
<Widget
|
||||
{...(showAllProjects
|
||||
? chartInfo.metrics
|
||||
: chartInfo.metricsPerProject)}
|
||||
>
|
||||
<MetricsSummaryChart
|
||||
metricsSummaryTrends={groupedMetricsData}
|
||||
allDatapointsSorted={allMetricsDatapoints}
|
||||
isAggregate={showAllProjects}
|
||||
isLoading={loading}
|
||||
/>
|
||||
</Widget>
|
||||
<Widget
|
||||
{...chartInfo.updates}
|
||||
sx={{ mt: (theme) => theme.spacing(2) }}
|
||||
>
|
||||
<UpdatesPerEnvironmentTypeChart
|
||||
environmentTypeTrends={environmentTypeTrends}
|
||||
isLoading={loading}
|
||||
/>
|
||||
</Widget>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
@ -90,6 +90,7 @@ export type UiFlags = {
|
||||
commandBarUI?: boolean;
|
||||
flagCreator?: boolean;
|
||||
resourceLimits?: boolean;
|
||||
insightsV2?: boolean;
|
||||
};
|
||||
|
||||
export interface IVersionInfo {
|
||||
|
@ -126,6 +126,7 @@ exports[`should create default config 1`] = `
|
||||
"filterInvalidClientMetrics": false,
|
||||
"flagCreator": false,
|
||||
"googleAuthEnabled": false,
|
||||
"insightsV2": false,
|
||||
"killInsightsUI": false,
|
||||
"killScheduledChangeRequestCache": false,
|
||||
"maintenanceMode": false,
|
||||
|
@ -66,7 +66,8 @@ export type IFlagKey =
|
||||
| 'extendedMetrics'
|
||||
| 'cleanApiTokenWhenOrphaned'
|
||||
| 'allowOrphanedWildcardTokens'
|
||||
| 'removeUnsafeInlineStyleSrc';
|
||||
| 'removeUnsafeInlineStyleSrc'
|
||||
| 'insightsV2';
|
||||
|
||||
export type IFlags = Partial<{ [key in IFlagKey]: boolean | Variant }>;
|
||||
|
||||
@ -319,6 +320,10 @@ const flags: IFlags = {
|
||||
process.env.UNLEASH_EXPERIMENTAL_REMOVE_UNSAFE_INLINE_STYLE_SRC,
|
||||
false,
|
||||
),
|
||||
insightsV2: parseEnvVarBoolean(
|
||||
process.env.UNLEASH_EXPERIMENTAL_INSIGHTS_V2,
|
||||
false,
|
||||
),
|
||||
};
|
||||
|
||||
export const defaultExperimentalOptions: IExperimentalOptions = {
|
||||
|
@ -56,6 +56,7 @@ process.nextTick(async () => {
|
||||
flagCreator: true,
|
||||
resourceLimits: true,
|
||||
extendedMetrics: true,
|
||||
insightsV2: true,
|
||||
},
|
||||
},
|
||||
authentication: {
|
||||
|
Loading…
Reference in New Issue
Block a user