mirror of
https://github.com/Unleash/unleash.git
synced 2024-12-28 00:06:53 +01:00
feat: insights filters (#7608)
This commit is contained in:
parent
13d02685d8
commit
39f6cbd66c
@ -11,8 +11,9 @@ import { InsightsHeader } from './components/InsightsHeader/InsightsHeader';
|
|||||||
import { useInsightsData } from './hooks/useInsightsData';
|
import { useInsightsData } from './hooks/useInsightsData';
|
||||||
import { InsightsCharts } from './InsightsCharts';
|
import { InsightsCharts } from './InsightsCharts';
|
||||||
import { LegacyInsightsCharts } from './LegacyInsightsCharts';
|
import { LegacyInsightsCharts } from './LegacyInsightsCharts';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
|
import { InsightsFilters } from './InsightsFilters';
|
||||||
|
import { FilterItemParam } from '../../utils/serializeQueryParams';
|
||||||
|
|
||||||
const StickyWrapper = styled(Box, {
|
const StickyWrapper = styled(Box, {
|
||||||
shouldForwardProp: (prop) => prop !== 'scrolled',
|
shouldForwardProp: (prop) => prop !== 'scrolled',
|
||||||
@ -33,7 +34,7 @@ const StyledProjectSelect = styled(ProjectSelect)(({ theme }) => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const Insights: VFC = () => {
|
const LegacyInsights = () => {
|
||||||
const [scrolled, setScrolled] = useState(false);
|
const [scrolled, setScrolled] = useState(false);
|
||||||
const { insights, loading, error } = useInsights();
|
const { insights, loading, error } = useInsights();
|
||||||
const stateConfig = {
|
const stateConfig = {
|
||||||
@ -61,8 +62,6 @@ export const Insights: VFC = () => {
|
|||||||
window.addEventListener('scroll', handleScroll);
|
window.addEventListener('scroll', handleScroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isInsightsV2Enabled = useUiFlag('insightsV2');
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<StickyWrapper scrolled={scrolled}>
|
<StickyWrapper scrolled={scrolled}>
|
||||||
@ -77,23 +76,65 @@ export const Insights: VFC = () => {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</StickyWrapper>
|
</StickyWrapper>
|
||||||
<ConditionallyRender
|
<LegacyInsightsCharts
|
||||||
condition={isInsightsV2Enabled}
|
loading={loading}
|
||||||
show={
|
projects={projects}
|
||||||
<InsightsCharts
|
{...insightsData}
|
||||||
loading={loading}
|
|
||||||
projects={projects}
|
|
||||||
{...insightsData}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
elseShow={
|
|
||||||
<LegacyInsightsCharts
|
|
||||||
loading={loading}
|
|
||||||
projects={projects}
|
|
||||||
{...insightsData}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const NewInsights = () => {
|
||||||
|
const [scrolled, setScrolled] = useState(false);
|
||||||
|
|
||||||
|
const stateConfig = {
|
||||||
|
projects: FilterItemParam,
|
||||||
|
from: FilterItemParam,
|
||||||
|
to: FilterItemParam,
|
||||||
|
};
|
||||||
|
const [state, setState] = usePersistentTableState('insights', stateConfig);
|
||||||
|
const { insights, loading, error } = useInsights(
|
||||||
|
state.from?.values[0],
|
||||||
|
state.to?.values[0],
|
||||||
|
);
|
||||||
|
|
||||||
|
const projects = state.projects?.values ?? [allOption.id];
|
||||||
|
|
||||||
|
const insightsData = useInsightsData(insights, projects);
|
||||||
|
|
||||||
|
const handleScroll = () => {
|
||||||
|
if (!scrolled && window.scrollY > 0) {
|
||||||
|
setScrolled(true);
|
||||||
|
} else if (scrolled && window.scrollY === 0) {
|
||||||
|
setScrolled(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.addEventListener('scroll', handleScroll);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<StickyWrapper scrolled={scrolled}>
|
||||||
|
<InsightsHeader
|
||||||
|
actions={
|
||||||
|
<InsightsFilters state={state} onChange={setState} />
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</StickyWrapper>
|
||||||
|
<InsightsCharts
|
||||||
|
loading={loading}
|
||||||
|
projects={projects}
|
||||||
|
{...insightsData}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Insights: VFC = () => {
|
||||||
|
const isInsightsV2Enabled = useUiFlag('insightsV2');
|
||||||
|
if (isInsightsV2Enabled) return <NewInsights />;
|
||||||
|
return <LegacyInsights />;
|
||||||
|
};
|
||||||
|
69
frontend/src/component/insights/InsightsFilters.tsx
Normal file
69
frontend/src/component/insights/InsightsFilters.tsx
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { type FC, useEffect, useState } from 'react';
|
||||||
|
import useProjects from 'hooks/api/getters/useProjects/useProjects';
|
||||||
|
import {
|
||||||
|
type FilterItemParamHolder,
|
||||||
|
Filters,
|
||||||
|
type IFilterItem,
|
||||||
|
} from 'component/filter/Filters/Filters';
|
||||||
|
|
||||||
|
interface IFeatureToggleFiltersProps {
|
||||||
|
state: FilterItemParamHolder;
|
||||||
|
onChange: (value: FilterItemParamHolder) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const InsightsFilters: FC<IFeatureToggleFiltersProps> = ({
|
||||||
|
state,
|
||||||
|
onChange,
|
||||||
|
}) => {
|
||||||
|
const { projects } = useProjects();
|
||||||
|
|
||||||
|
const [availableFilters, setAvailableFilters] = useState<IFilterItem[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const projectsOptions = (projects || []).map((project) => ({
|
||||||
|
label: project.name,
|
||||||
|
value: project.id,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const hasMultipleProjects = projectsOptions.length > 1;
|
||||||
|
|
||||||
|
const availableFilters: IFilterItem[] = [
|
||||||
|
{
|
||||||
|
label: 'Date From',
|
||||||
|
icon: 'today',
|
||||||
|
options: [],
|
||||||
|
filterKey: 'from',
|
||||||
|
dateOperators: ['IS'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Date To',
|
||||||
|
icon: 'today',
|
||||||
|
options: [],
|
||||||
|
filterKey: 'to',
|
||||||
|
dateOperators: ['IS'],
|
||||||
|
},
|
||||||
|
...(hasMultipleProjects
|
||||||
|
? ([
|
||||||
|
{
|
||||||
|
label: 'Project',
|
||||||
|
icon: 'topic',
|
||||||
|
options: projectsOptions,
|
||||||
|
filterKey: 'projects',
|
||||||
|
singularOperators: ['IS'],
|
||||||
|
pluralOperators: ['IS_ANY_OF'],
|
||||||
|
},
|
||||||
|
] as IFilterItem[])
|
||||||
|
: []),
|
||||||
|
];
|
||||||
|
|
||||||
|
setAvailableFilters(availableFilters);
|
||||||
|
}, [JSON.stringify(projects)]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Filters
|
||||||
|
availableFilters={availableFilters}
|
||||||
|
state={state}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
@ -18,6 +18,7 @@ type DashboardHeaderProps = {
|
|||||||
|
|
||||||
const StyledActionsContainer = styled('div')(({ theme }) => ({
|
const StyledActionsContainer = styled('div')(({ theme }) => ({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
gap: theme.spacing(1),
|
gap: theme.spacing(1),
|
||||||
[theme.breakpoints.down('md')]: {
|
[theme.breakpoints.down('md')]: {
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
|
@ -12,9 +12,11 @@ interface IUseInsightsDataOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const useInsights = (
|
export const useInsights = (
|
||||||
|
from = '',
|
||||||
|
to = '',
|
||||||
options?: SWRConfiguration,
|
options?: SWRConfiguration,
|
||||||
): IUseInsightsDataOutput => {
|
): IUseInsightsDataOutput => {
|
||||||
const path = formatApiPath('api/admin/insights');
|
const path = formatApiPath(`api/admin/insights?from=${from}&to=${to}`);
|
||||||
|
|
||||||
const { data, error } = useSWR<InstanceInsightsSchema>(
|
const { data, error } = useSWR<InstanceInsightsSchema>(
|
||||||
path,
|
path,
|
||||||
|
Loading…
Reference in New Issue
Block a user