mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01: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);
 | 
						|
};
 |