diff --git a/frontend/src/component/insights/Insights.tsx b/frontend/src/component/insights/Insights.tsx
index d7cfcd447bc3..cebc93fdcc1b 100644
--- a/frontend/src/component/insights/Insights.tsx
+++ b/frontend/src/component/insights/Insights.tsx
@@ -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 (
<>
@@ -69,10 +74,22 @@ export const Insights: VFC = () => {
}
/>
-
+ }
+ elseShow={
+
+ }
/>
>
);
diff --git a/frontend/src/component/insights/LegacyInsightsCharts.tsx b/frontend/src/component/insights/LegacyInsightsCharts.tsx
new file mode 100644
index 000000000000..681860e9a64e
--- /dev/null
+++ b/frontend/src/component/insights/LegacyInsightsCharts.tsx
@@ -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 = ({
+ 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 (
+ <>
+
+
+
+
+ }
+ elseShow={
+
+
+
+ }
+ />
+
+
+
+ }
+ elseShow={
+
+
+
+ }
+ />
+
+
+
+
+
+
+ }
+ elseShow={
+
+
+
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ }
+ />
+
+
+
+
+
+ theme.spacing(2) }}
+ >
+
+
+ >
+ }
+ />
+ >
+ );
+};
diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts
index 4c91256200c2..860e155cb3b4 100644
--- a/frontend/src/interfaces/uiConfig.ts
+++ b/frontend/src/interfaces/uiConfig.ts
@@ -90,6 +90,7 @@ export type UiFlags = {
commandBarUI?: boolean;
flagCreator?: boolean;
resourceLimits?: boolean;
+ insightsV2?: boolean;
};
export interface IVersionInfo {
diff --git a/src/lib/__snapshots__/create-config.test.ts.snap b/src/lib/__snapshots__/create-config.test.ts.snap
index f7c66b6045ad..ec18e916e79b 100644
--- a/src/lib/__snapshots__/create-config.test.ts.snap
+++ b/src/lib/__snapshots__/create-config.test.ts.snap
@@ -126,6 +126,7 @@ exports[`should create default config 1`] = `
"filterInvalidClientMetrics": false,
"flagCreator": false,
"googleAuthEnabled": false,
+ "insightsV2": false,
"killInsightsUI": false,
"killScheduledChangeRequestCache": false,
"maintenanceMode": false,
diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts
index 906604a882b9..2cc86ea82a97 100644
--- a/src/lib/types/experimental.ts
+++ b/src/lib/types/experimental.ts
@@ -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 = {
diff --git a/src/server-dev.ts b/src/server-dev.ts
index 6dd12fcf6c99..877ed1065c8b 100644
--- a/src/server-dev.ts
+++ b/src/server-dev.ts
@@ -56,6 +56,7 @@ process.nextTick(async () => {
flagCreator: true,
resourceLimits: true,
extendedMetrics: true,
+ insightsV2: true,
},
},
authentication: {