mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-03 01:18:43 +02:00
https://linear.app/unleash/issue/2-849/dark-mode-ui-fixes    Also includes misc UI fixes and improvements we identified along the way. Co-authored by @NicolaeUnleash --------- Co-authored-by: NicolaeUnleash <103567375+NicolaeUnleash@users.noreply.github.com>
130 lines
4.9 KiB
TypeScript
130 lines
4.9 KiB
TypeScript
import { useFeatureMetricsRaw } from 'hooks/api/getters/useFeatureMetricsRaw/useFeatureMetricsRaw';
|
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
|
import { useEffect, useMemo, useState } from 'react';
|
|
import {
|
|
FEATURE_METRIC_HOURS_BACK_MAX,
|
|
FeatureMetricsHours,
|
|
} from './FeatureMetricsHours/FeatureMetricsHours';
|
|
import { IFeatureMetricsRaw } from 'interfaces/featureToggle';
|
|
import { Grid } from '@mui/material';
|
|
import { FeatureMetricsContent } from './FeatureMetricsContent/FeatureMetricsContent';
|
|
import { useQueryStringNumberState } from 'hooks/useQueryStringNumberState';
|
|
import { useQueryStringState } from 'hooks/useQueryStringState';
|
|
import { FeatureMetricsChips } from './FeatureMetricsChips/FeatureMetricsChips';
|
|
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
import { usePageTitle } from 'hooks/usePageTitle';
|
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
|
|
|
export const FeatureMetrics = () => {
|
|
const projectId = useRequiredPathParam('projectId');
|
|
const featureId = useRequiredPathParam('featureId');
|
|
const environments = useFeatureMetricsEnvironments(projectId, featureId);
|
|
const applications = useFeatureMetricsApplications(featureId);
|
|
usePageTitle('Metrics');
|
|
|
|
const [hoursBack = FEATURE_METRIC_HOURS_BACK_MAX, setHoursBack] =
|
|
useQueryStringNumberState('hoursBack');
|
|
const { featureMetrics } = useFeatureMetricsRaw(featureId, hoursBack);
|
|
|
|
// Keep a cache of the fetched metrics so that we can
|
|
// show the cached result while fetching new metrics.
|
|
const [cachedMetrics, setCachedMetrics] = useState<
|
|
Readonly<IFeatureMetricsRaw[]> | undefined
|
|
>(featureMetrics);
|
|
|
|
useEffect(() => {
|
|
featureMetrics && setCachedMetrics(featureMetrics);
|
|
}, [featureMetrics]);
|
|
|
|
const defaultEnvironment = Array.from(environments)[0];
|
|
const defaultApplication = Array.from(applications)[0];
|
|
const [environment = defaultEnvironment, setEnvironment] =
|
|
useQueryStringState('environment');
|
|
const [application = defaultApplication, setApplication] =
|
|
useQueryStringState('application');
|
|
|
|
const filteredMetrics = useMemo(() => {
|
|
return cachedMetrics
|
|
?.filter(metric => metric.environment === environment)
|
|
.filter(metric => metric.appName === application);
|
|
}, [cachedMetrics, environment, application]);
|
|
|
|
if (!filteredMetrics) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<PageContent>
|
|
<Grid container component="header" spacing={2}>
|
|
<Grid item xs={12} md={5}>
|
|
<ConditionallyRender
|
|
condition={environments.size > 0}
|
|
show={
|
|
<FeatureMetricsChips
|
|
title="Environments"
|
|
values={environments}
|
|
value={environment}
|
|
setValue={setEnvironment}
|
|
/>
|
|
}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} md={5}>
|
|
<ConditionallyRender
|
|
condition={applications.size > 0}
|
|
show={
|
|
<FeatureMetricsChips
|
|
title="Applications"
|
|
values={applications}
|
|
value={application}
|
|
setValue={setApplication}
|
|
/>
|
|
}
|
|
/>
|
|
</Grid>
|
|
<Grid item xs={12} md={2}>
|
|
<FeatureMetricsHours
|
|
hoursBack={hoursBack}
|
|
setHoursBack={setHoursBack}
|
|
/>
|
|
</Grid>
|
|
</Grid>
|
|
<FeatureMetricsContent
|
|
metrics={filteredMetrics}
|
|
hoursBack={hoursBack}
|
|
/>
|
|
</PageContent>
|
|
);
|
|
};
|
|
|
|
// Get all the environment names for a feature,
|
|
// not just the one's we have metrics for.
|
|
const useFeatureMetricsEnvironments = (
|
|
projectId: string,
|
|
featureId: string
|
|
): Set<string> => {
|
|
const { feature } = useFeature(projectId, featureId);
|
|
|
|
const environments = feature.environments.map(environment => {
|
|
return environment.name;
|
|
});
|
|
|
|
return new Set(environments);
|
|
};
|
|
|
|
// Get all application names for a feature. Fetch apps for the max time range
|
|
// so that the list of apps doesn't change when selecting a shorter range.
|
|
const useFeatureMetricsApplications = (featureId: string): Set<string> => {
|
|
const { featureMetrics = [] } = useFeatureMetricsRaw(
|
|
featureId,
|
|
FEATURE_METRIC_HOURS_BACK_MAX
|
|
);
|
|
|
|
const applications = featureMetrics.map(metric => {
|
|
return metric.appName;
|
|
});
|
|
|
|
return new Set(applications);
|
|
};
|