mirror of
https://github.com/Unleash/unleash.git
synced 2025-10-09 11:14:29 +02:00
refactor: split EventLog into separate components and hook up new Event search (#7777)
Hooks up the new Event search and filtering capabilities to the new Event Log component. In doing so, it also splits the existing EventLog component into two: `LegacyEventLog` and `NewEventLog`. The naming is probably temporary, as the old EventLog isn't really legacy yet. But we can rename them later. The other half of #7768 .
This commit is contained in:
parent
d4069f26e6
commit
d70c279d3d
@ -15,6 +15,7 @@ import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
|||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
import { EventLogFilters } from './EventLogFilters';
|
import { EventLogFilters } from './EventLogFilters';
|
||||||
import type { EventSchema } from 'openapi';
|
import type { EventSchema } from 'openapi';
|
||||||
|
import { useEventLogSearch } from './useEventLogSearch';
|
||||||
|
|
||||||
interface IEventLogProps {
|
interface IEventLogProps {
|
||||||
title: string;
|
title: string;
|
||||||
@ -41,7 +42,98 @@ const EventResultWrapper = styled('div')(({ theme }) => ({
|
|||||||
gap: theme.spacing(1),
|
gap: theme.spacing(1),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export const EventLog = ({ title, project, feature }: IEventLogProps) => {
|
const NewEventLog = ({ title, project, feature }: IEventLogProps) => {
|
||||||
|
const { events, total, loading, tableState, setTableState, filterState } =
|
||||||
|
useEventLogSearch(
|
||||||
|
project
|
||||||
|
? { type: 'project', projectId: project }
|
||||||
|
: feature
|
||||||
|
? { type: 'flag', flagName: feature }
|
||||||
|
: { type: 'global' },
|
||||||
|
);
|
||||||
|
|
||||||
|
const setSearchValue = (query = '') => {
|
||||||
|
setTableState({ query });
|
||||||
|
};
|
||||||
|
const { eventSettings, setEventSettings } = useEventSettings();
|
||||||
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
|
|
||||||
|
const onShowData = () => {
|
||||||
|
setEventSettings((prev) => ({ showData: !prev.showData }));
|
||||||
|
};
|
||||||
|
|
||||||
|
const searchInputField = (
|
||||||
|
<Search
|
||||||
|
onChange={setSearchValue}
|
||||||
|
initialValue={tableState.query || ''}
|
||||||
|
debounceTime={500}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const showDataSwitch = (
|
||||||
|
<FormControlLabel
|
||||||
|
label='Full events'
|
||||||
|
control={
|
||||||
|
<Switch
|
||||||
|
checked={eventSettings.showData}
|
||||||
|
onChange={onShowData}
|
||||||
|
color='primary'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
const resultComponent = () => {
|
||||||
|
if (loading) {
|
||||||
|
return <p>Loading...</p>;
|
||||||
|
} else if (events.length === 0) {
|
||||||
|
return <p>No events found.</p>;
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<StyledEventsList>
|
||||||
|
{events.map((entry) => (
|
||||||
|
<ConditionallyRender
|
||||||
|
key={entry.id}
|
||||||
|
condition={eventSettings.showData}
|
||||||
|
show={() => <EventJson entry={entry} />}
|
||||||
|
elseShow={() => <EventCard entry={entry} />}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</StyledEventsList>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PageContent
|
||||||
|
bodyClass={'no-padding'}
|
||||||
|
header={
|
||||||
|
<PageHeader
|
||||||
|
title={`${title} (${total})`}
|
||||||
|
actions={
|
||||||
|
<>
|
||||||
|
{showDataSwitch}
|
||||||
|
{!isSmallScreen && searchInputField}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{isSmallScreen && searchInputField}
|
||||||
|
</PageHeader>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<EventResultWrapper>
|
||||||
|
<StyledFilters
|
||||||
|
logType={project ? 'project' : feature ? 'flag' : 'global'}
|
||||||
|
state={filterState}
|
||||||
|
onChange={setTableState}
|
||||||
|
/>
|
||||||
|
{resultComponent()}
|
||||||
|
</EventResultWrapper>
|
||||||
|
</PageContent>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const LegacyEventLog = ({ title, project, feature }: IEventLogProps) => {
|
||||||
const [query, setQuery] = useState('');
|
const [query, setQuery] = useState('');
|
||||||
const { events, totalEvents, fetchNextPage } = useLegacyEventSearch(
|
const { events, totalEvents, fetchNextPage } = useLegacyEventSearch(
|
||||||
project,
|
project,
|
||||||
@ -51,8 +143,6 @@ export const EventLog = ({ title, project, feature }: IEventLogProps) => {
|
|||||||
const fetchNextPageRef = useOnVisible<HTMLDivElement>(fetchNextPage);
|
const fetchNextPageRef = useOnVisible<HTMLDivElement>(fetchNextPage);
|
||||||
const { eventSettings, setEventSettings } = useEventSettings();
|
const { eventSettings, setEventSettings } = useEventSettings();
|
||||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||||
const { isEnterprise } = useUiConfig();
|
|
||||||
const showFilters = useUiFlag('newEventSearch') && isEnterprise();
|
|
||||||
|
|
||||||
// Cache the previous search results so that we can show those while
|
// Cache the previous search results so that we can show those while
|
||||||
// fetching new results for a new search query in the background.
|
// fetching new results for a new search query in the background.
|
||||||
@ -82,8 +172,22 @@ export const EventLog = ({ title, project, feature }: IEventLogProps) => {
|
|||||||
const totalCount = totalEvents || 0;
|
const totalCount = totalEvents || 0;
|
||||||
const countText = `${count} of ${totalCount}`;
|
const countText = `${count} of ${totalCount}`;
|
||||||
|
|
||||||
const EventResults = (
|
return (
|
||||||
<>
|
<PageContent
|
||||||
|
header={
|
||||||
|
<PageHeader
|
||||||
|
title={`${title} (${countText})`}
|
||||||
|
actions={
|
||||||
|
<>
|
||||||
|
{showDataSwitch}
|
||||||
|
{!isSmallScreen && searchInputField}
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{isSmallScreen && searchInputField}
|
||||||
|
</PageHeader>
|
||||||
|
}
|
||||||
|
>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(cache && cache.length === 0)}
|
condition={Boolean(cache && cache.length === 0)}
|
||||||
show={<p>No events found.</p>}
|
show={<p>No events found.</p>}
|
||||||
@ -103,46 +207,17 @@ export const EventLog = ({ title, project, feature }: IEventLogProps) => {
|
|||||||
</StyledEventsList>
|
</StyledEventsList>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PageContent
|
|
||||||
bodyClass={showFilters ? 'no-padding' : ''}
|
|
||||||
header={
|
|
||||||
<PageHeader
|
|
||||||
title={`${title} (${countText})`}
|
|
||||||
actions={
|
|
||||||
<>
|
|
||||||
{showDataSwitch}
|
|
||||||
{!isSmallScreen && searchInputField}
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{isSmallScreen && searchInputField}
|
|
||||||
</PageHeader>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={showFilters}
|
|
||||||
show={
|
|
||||||
<EventResultWrapper>
|
|
||||||
<StyledFilters
|
|
||||||
logType={
|
|
||||||
project
|
|
||||||
? 'project'
|
|
||||||
: feature
|
|
||||||
? 'flag'
|
|
||||||
: 'global'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
{EventResults}
|
|
||||||
</EventResultWrapper>
|
|
||||||
}
|
|
||||||
elseShow={EventResults}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div ref={fetchNextPageRef} />
|
<div ref={fetchNextPageRef} />
|
||||||
</PageContent>
|
</PageContent>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const EventLog = (props: IEventLogProps) => {
|
||||||
|
const { isEnterprise } = useUiConfig();
|
||||||
|
const showFilters = useUiFlag('newEventSearch') && isEnterprise();
|
||||||
|
if (showFilters) {
|
||||||
|
return <NewEventLog {...props} />;
|
||||||
|
} else {
|
||||||
|
return <LegacyEventLog {...props} />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
import { useState, useEffect, type FC } from 'react';
|
import { useState, useEffect, type FC } from 'react';
|
||||||
import { Filters, type IFilterItem } from 'component/filter/Filters/Filters';
|
import {
|
||||||
|
type FilterItemParamHolder,
|
||||||
|
Filters,
|
||||||
|
type IFilterItem,
|
||||||
|
} from 'component/filter/Filters/Filters';
|
||||||
import useProjects from 'hooks/api/getters/useProjects/useProjects';
|
import useProjects from 'hooks/api/getters/useProjects/useProjects';
|
||||||
import { useFeatureSearch } from 'hooks/api/getters/useFeatureSearch/useFeatureSearch';
|
import { useFeatureSearch } from 'hooks/api/getters/useFeatureSearch/useFeatureSearch';
|
||||||
import { EventSchemaType } from 'openapi';
|
import { EventSchemaType } from 'openapi';
|
||||||
@ -30,14 +34,13 @@ const sharedFilters: IFilterItem[] = [
|
|||||||
pluralOperators: ['IS_ANY_OF'],
|
pluralOperators: ['IS_ANY_OF'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// todo fill this in with actual values
|
|
||||||
label: 'Event type',
|
label: 'Event type',
|
||||||
icon: 'announcement',
|
icon: 'announcement',
|
||||||
options: Object.entries(EventSchemaType).map(([key, value]) => ({
|
options: Object.entries(EventSchemaType).map(([key, value]) => ({
|
||||||
label: key,
|
label: key,
|
||||||
value: value,
|
value: value,
|
||||||
})),
|
})),
|
||||||
filterKey: 'eventType',
|
filterKey: 'type',
|
||||||
singularOperators: ['IS'],
|
singularOperators: ['IS'],
|
||||||
pluralOperators: ['IS_ANY_OF'],
|
pluralOperators: ['IS_ANY_OF'],
|
||||||
},
|
},
|
||||||
@ -46,11 +49,15 @@ const sharedFilters: IFilterItem[] = [
|
|||||||
type EventLogFiltersProps = {
|
type EventLogFiltersProps = {
|
||||||
logType: 'flag' | 'project' | 'global';
|
logType: 'flag' | 'project' | 'global';
|
||||||
className?: string;
|
className?: string;
|
||||||
|
state: FilterItemParamHolder;
|
||||||
|
onChange: (value: FilterItemParamHolder) => void;
|
||||||
};
|
};
|
||||||
export const EventLogFilters: FC<EventLogFiltersProps> = (
|
export const EventLogFilters: FC<EventLogFiltersProps> = ({
|
||||||
{ logType, className },
|
logType,
|
||||||
// {state, onChange,} // these are to fill in later to make the filters work
|
className,
|
||||||
) => {
|
state,
|
||||||
|
onChange,
|
||||||
|
}) => {
|
||||||
const { projects } = useProjects();
|
const { projects } = useProjects();
|
||||||
const { features } = useFeatureSearch({});
|
const { features } = useFeatureSearch({});
|
||||||
|
|
||||||
@ -90,7 +97,7 @@ export const EventLogFilters: FC<EventLogFiltersProps> = (
|
|||||||
label: 'Feature Flag',
|
label: 'Feature Flag',
|
||||||
icon: 'flag',
|
icon: 'flag',
|
||||||
options: flagOptions,
|
options: flagOptions,
|
||||||
filterKey: 'flag',
|
filterKey: 'feature',
|
||||||
singularOperators: ['IS'],
|
singularOperators: ['IS'],
|
||||||
pluralOperators: ['IS_ANY_OF'],
|
pluralOperators: ['IS_ANY_OF'],
|
||||||
},
|
},
|
||||||
@ -105,8 +112,8 @@ export const EventLogFilters: FC<EventLogFiltersProps> = (
|
|||||||
<Filters
|
<Filters
|
||||||
className={className}
|
className={className}
|
||||||
availableFilters={availableFilters}
|
availableFilters={availableFilters}
|
||||||
state={{}}
|
state={state}
|
||||||
onChange={(v) => console.log(v)}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user