1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-14 00:19:16 +01:00

feat: select multiple apps (#5860)

This commit is contained in:
Mateusz Kwasniewski 2024-01-12 08:33:52 +01:00 committed by GitHub
parent e3fc4b51fa
commit 6ba4591c7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 55 additions and 71 deletions

View File

@ -8,13 +8,18 @@ import {
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';
import {
ArrayParam,
NumberParam,
StringParam,
useQueryParams,
withDefault,
} from 'use-query-params';
export const FeatureMetrics = () => {
const projectId = useRequiredPathParam('projectId');
@ -23,8 +28,18 @@ export const FeatureMetrics = () => {
const applications = useFeatureMetricsApplications(featureId);
usePageTitle('Metrics');
const [hoursBack = FEATURE_METRIC_HOURS_BACK_DEFAULT, setHoursBack] =
useQueryStringNumberState('hoursBack');
const defaultEnvironment = Array.from(environments)[0];
const defaultApplication = Array.from(applications)[0];
const [query, setQuery] = useQueryParams({
environment: withDefault(StringParam, defaultEnvironment),
applications: withDefault(ArrayParam, [defaultApplication]),
hoursBack: withDefault(NumberParam, FEATURE_METRIC_HOURS_BACK_DEFAULT),
});
const { environment: selectedEnvironment, hoursBack } = query;
const selectedApplications = query.applications.filter(
(item) => item !== null,
) as string[];
const { featureMetrics } = useFeatureMetricsRaw(featureId, hoursBack);
// Keep a cache of the fetched metrics so that we can
@ -37,18 +52,15 @@ export const FeatureMetrics = () => {
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]);
?.filter((metric) => selectedEnvironment === metric.environment)
.filter((metric) => selectedApplications.includes(metric.appName));
}, [
cachedMetrics,
selectedEnvironment,
JSON.stringify(selectedApplications),
]);
if (!filteredMetrics) {
return null;
@ -64,8 +76,10 @@ export const FeatureMetrics = () => {
<FeatureMetricsChips
title='Environments'
values={environments}
value={environment}
setValue={setEnvironment}
selectedValues={[selectedEnvironment]}
toggleValue={(value) => {
setQuery({ environment: value });
}}
/>
}
/>
@ -77,8 +91,24 @@ export const FeatureMetrics = () => {
<FeatureMetricsChips
title='Applications'
values={applications}
value={application}
setValue={setApplication}
selectedValues={selectedApplications}
toggleValue={(value) => {
if (selectedApplications.includes(value)) {
setQuery({
applications:
selectedApplications.filter(
(app) => app !== value,
),
});
} else {
setQuery({
applications: [
...selectedApplications,
value,
],
});
}
}}
/>
}
/>
@ -86,7 +116,7 @@ export const FeatureMetrics = () => {
<Grid item xs={12} md={2}>
<FeatureMetricsHours
hoursBack={hoursBack}
setHoursBack={setHoursBack}
setHoursBack={(value) => setQuery({ hoursBack: value })}
/>
</Grid>
</Grid>

View File

@ -5,8 +5,8 @@ import { focusable } from 'themes/themeStyles';
interface IFeatureMetricsChipsProps {
title: string;
values: Set<string>;
value?: string;
setValue: (value: string) => void;
selectedValues: string[];
toggleValue: (value: string) => void;
}
const StyledTitle = styled('h2')(({ theme }) => ({
@ -39,13 +39,11 @@ const StyledItem = styled('li')(({ theme }) => ({
export const FeatureMetricsChips = ({
title,
values,
value,
setValue,
selectedValues,
toggleValue,
}: IFeatureMetricsChipsProps) => {
const onClick = (value: string) => () => {
if (values.has(value)) {
setValue(value);
}
toggleValue(value);
};
const sortedValues = useMemo(() => {
@ -63,7 +61,7 @@ export const FeatureMetricsChips = ({
<Chip
label={val}
onClick={onClick(val)}
aria-pressed={val === value}
aria-pressed={selectedValues?.includes(val)}
sx={focusable}
/>
</StyledItem>

View File

@ -1,19 +0,0 @@
import { useCallback } from 'react';
import { useQueryStringState } from './useQueryStringState';
// Store a number in the query string. Call setState to update the query string.
export const useQueryStringNumberState = (
key: string,
): [number | undefined, (value: number) => void] => {
const [value, setValue] = useQueryStringState(key);
const setState = useCallback(
(value: number) => setValue(String(value)),
[setValue],
);
return [
Number.isFinite(Number(value)) ? Number(value) : undefined,
setState,
];
};

View File

@ -1,25 +0,0 @@
import { useCallback, useMemo } from 'react';
import { useNavigate } from 'react-router-dom';
// Store a value in the query string. Call setState to update the query string.
export const useQueryStringState = (
key: string,
): [string | undefined, (value: string) => void] => {
const { search } = window.location;
const navigate = useNavigate();
const params = useMemo(() => {
return new URLSearchParams(search);
}, [search]);
const setState = useCallback(
(value: string) => {
const next = new URLSearchParams(search);
next.set(key, value);
navigate({ search: next.toString() }, { replace: true });
},
[key, search, navigate],
);
return [params.get(key) || undefined, setState];
};