From 7db42453b179af03a1b75c242ad74be48db69c52 Mon Sep 17 00:00:00 2001
From: Thomas Heartman
Date: Thu, 1 Aug 2024 08:23:22 +0200
Subject: [PATCH] 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)
---
.../component/events/EventLog/EventLog.tsx | 10 ++
.../events/EventLog/EventLogFilters.tsx | 148 ++++++++++++++++++
.../src/component/filter/Filters/Filters.tsx | 4 +-
3 files changed, 160 insertions(+), 2 deletions(-)
create mode 100644 frontend/src/component/events/EventLog/EventLogFilters.tsx
diff --git a/frontend/src/component/events/EventLog/EventLog.tsx b/frontend/src/component/events/EventLog/EventLog.tsx
index 41dde17000..03243d4d94 100644
--- a/frontend/src/component/events/EventLog/EventLog.tsx
+++ b/frontend/src/component/events/EventLog/EventLog.tsx
@@ -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(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) => {
}
>
+ }
+ />
No events found.
}
diff --git a/frontend/src/component/events/EventLog/EventLogFilters.tsx b/frontend/src/component/events/EventLog/EventLogFilters.tsx
new file mode 100644
index 0000000000..522dfc3632
--- /dev/null
+++ b/frontend/src/component/events/EventLog/EventLogFilters.tsx
@@ -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 (
+ console.log(v)}
+ />
+ );
+};
+
+const useProjectLogFilters = () => {
+ const [availableFilters, setAvailableFilters] = useState([]);
+
+ 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 (
+ console.log(v)}
+ />
+ );
+};
+
+export const GlobalLogFilters = () => {
+ const projectFilters = useProjectLogFilters();
+ const { projects } = useProjects();
+
+ const [availableFilters, setAvailableFilters] = useState([]);
+ 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 (
+ console.log(v)}
+ />
+ );
+};
+
+type EventLogFiltersProps = {
+ logType: 'flag' | 'project' | 'global';
+};
+export const EventLogFilters: FC = (
+ { logType },
+ // {state, onChange,} // these are to fill in later to make the filters work
+) => {
+ switch (logType) {
+ case 'flag':
+ return ;
+ case 'project':
+ return ;
+ case 'global':
+ return ;
+ }
+};
diff --git a/frontend/src/component/filter/Filters/Filters.tsx b/frontend/src/component/filter/Filters/Filters.tsx
index 02076f263c..5b41bf2a1d 100644
--- a/frontend/src/component/filter/Filters/Filters.tsx
+++ b/frontend/src/component/filter/Filters/Filters.tsx
@@ -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 = ({
+export const Filters: FC = ({
state,
onChange,
availableFilters,