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

feat: add filter dropdowns to event log pages (#7711)

Adds placeholder filter buttons (that don't work at all) yet to the
three event logs.

Flag logs get to choose to and from dates, created by, and event type.

Project logs get all that flag logs get + a filter for flag.

The global log gets all project log filters + a project filter.

There's still work to be done to add data to createdBy, eventType, to
hook it up to the API, and to finalize the layout, but I wanted to get a
rough outline in to iterate on later. The eventType icon will also need
to be decided on.


![image](https://github.com/user-attachments/assets/06a65301-9cc5-45ed-b753-2b9235d64ea6)
This commit is contained in:
Thomas Heartman 2024-08-01 08:23:22 +02:00 committed by GitHub
parent cab18d2881
commit 7db42453b1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 160 additions and 2 deletions

View File

@ -12,6 +12,9 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
import { useOnVisible } from 'hooks/useOnVisible';
import type { IEvent } from 'interfaces/event';
import { styled } from '@mui/system';
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
import { useUiFlag } from 'hooks/useUiFlag';
import { EventLogFilters } from './EventLogFilters';
interface IEventLogProps {
title: string;
@ -37,6 +40,8 @@ export const EventLog = ({ title, project, feature }: IEventLogProps) => {
const fetchNextPageRef = useOnVisible<HTMLDivElement>(fetchNextPage);
const { eventSettings, setEventSettings } = useEventSettings();
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
const { isEnterprise } = useUiConfig();
const showFilters = useUiFlag('newEventSearch');
// Cache the previous search results so that we can show those while
// fetching new results for a new search query in the background.
@ -62,6 +67,7 @@ export const EventLog = ({ title, project, feature }: IEventLogProps) => {
/>
);
const logType = project ? 'project' : feature ? 'flag' : 'global';
const count = events?.length || 0;
const totalCount = totalEvents || 0;
const countText = `${count} of ${totalCount}`;
@ -82,6 +88,10 @@ export const EventLog = ({ title, project, feature }: IEventLogProps) => {
</PageHeader>
}
>
<ConditionallyRender
condition={isEnterprise() && showFilters}
show={<EventLogFilters logType={logType} />}
/>
<ConditionallyRender
condition={Boolean(cache && cache.length === 0)}
show={<p>No events found.</p>}

View File

@ -0,0 +1,148 @@
import { useState, useEffect, type FC } from 'react';
import { Filters, type IFilterItem } from 'component/filter/Filters/Filters';
import useProjects from 'hooks/api/getters/useProjects/useProjects';
import { useFeatureSearch } from 'hooks/api/getters/useFeatureSearch/useFeatureSearch';
const flagLogFilters: IFilterItem[] = [
{
label: 'Date From',
icon: 'today',
options: [],
filterKey: 'from',
dateOperators: ['IS'],
},
{
label: 'Date To',
icon: 'today',
options: [],
filterKey: 'to',
dateOperators: ['IS'],
},
{
// todo fill this in with actual values
label: 'Created by',
icon: 'person',
options: [],
filterKey: 'createdBy',
singularOperators: ['IS'],
pluralOperators: ['IS_ANY_OF'],
},
{
// todo fill this in with actual values
label: 'Event type',
icon: 'announcement',
options: [],
filterKey: 'eventType',
singularOperators: ['IS'],
pluralOperators: ['IS_ANY_OF'],
},
];
export const FlagLogFilters = () => {
return (
<Filters
availableFilters={flagLogFilters}
state={{}}
onChange={(v) => console.log(v)}
/>
);
};
const useProjectLogFilters = () => {
const [availableFilters, setAvailableFilters] = useState<IFilterItem[]>([]);
const { features } = useFeatureSearch({ project: 'default' });
useEffect(() => {
const flagOptions = (features || []).map((flag) => ({
label: flag.name,
value: flag.name,
}));
const availableFilters: IFilterItem[] = [
...flagLogFilters,
{
label: 'Feature Flag',
icon: 'flag',
options: flagOptions,
filterKey: 'flag',
singularOperators: ['IS'],
pluralOperators: ['IS_ANY_OF'],
},
];
setAvailableFilters(availableFilters);
}, [JSON.stringify(features)]);
return availableFilters;
};
export const ProjectLogFilters = () => {
const availableFilters = useProjectLogFilters();
return (
<Filters
availableFilters={availableFilters}
state={{}}
onChange={(v) => console.log(v)}
/>
);
};
export const GlobalLogFilters = () => {
const projectFilters = useProjectLogFilters();
const { projects } = useProjects();
const [availableFilters, setAvailableFilters] = useState<IFilterItem[]>([]);
useEffect(() => {
const projectOptions = (projects || []).map((project) => ({
label: project.name,
value: project.id,
}));
const hasMultipleProjects = projectOptions.length > 1;
const availableFilters: IFilterItem[] = [
...projectFilters,
...(hasMultipleProjects
? ([
{
label: 'Project',
icon: 'topic',
options: projectOptions,
filterKey: 'project',
singularOperators: ['IS'],
pluralOperators: ['IS_ANY_OF'],
},
] as IFilterItem[])
: []),
];
setAvailableFilters(availableFilters);
}, [JSON.stringify(projectFilters), JSON.stringify(projects)]);
return (
<Filters
availableFilters={availableFilters}
state={{}}
onChange={(v) => console.log(v)}
/>
);
};
type EventLogFiltersProps = {
logType: 'flag' | 'project' | 'global';
};
export const EventLogFilters: FC<EventLogFiltersProps> = (
{ logType },
// {state, onChange,} // these are to fill in later to make the filters work
) => {
switch (logType) {
case 'flag':
return <FlagLogFilters />;
case 'project':
return <ProjectLogFilters />;
case 'global':
return <GlobalLogFilters />;
}
};

View File

@ -1,4 +1,4 @@
import { useEffect, useState, type VFC } from 'react';
import { type FC, useEffect, useState } from 'react';
import { Box, Icon, styled } from '@mui/material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { AddFilterButton } from '../AddFilterButton';
@ -57,7 +57,7 @@ const StyledIcon = styled(Icon)(({ theme }) => ({
},
}));
export const Filters: VFC<IFilterProps> = ({
export const Filters: FC<IFilterProps> = ({
state,
onChange,
availableFilters,