mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-02 01:17:58 +02:00
feat: event log environment filter (#9979)
Add Environment Filter to Event Log
This commit is contained in:
parent
c0c7005859
commit
94c73bbc5d
@ -9,13 +9,16 @@ import { useFeatureSearch } from 'hooks/api/getters/useFeatureSearch/useFeatureS
|
||||
import { EventSchemaType, type FeatureSearchResponseSchema } from 'openapi';
|
||||
import type { ProjectSchema } from 'openapi';
|
||||
import { useEventCreators } from 'hooks/api/getters/useEventCreators/useEventCreators';
|
||||
import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironments';
|
||||
|
||||
export const useEventLogFilters = (
|
||||
projects: ProjectSchema[],
|
||||
features: FeatureSearchResponseSchema[],
|
||||
) => {
|
||||
const { environments } = useEnvironments();
|
||||
const { eventCreators } = useEventCreators();
|
||||
const [availableFilters, setAvailableFilters] = useState<IFilterItem[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const projectOptions =
|
||||
projects?.map((project: ProjectSchema) => ({
|
||||
@ -41,6 +44,12 @@ export const useEventLogFilters = (
|
||||
}),
|
||||
);
|
||||
|
||||
const environmentOptions =
|
||||
environments?.map((env) => ({
|
||||
label: env.name,
|
||||
value: env.name,
|
||||
})) ?? [];
|
||||
|
||||
const availableFilters: IFilterItem[] = [
|
||||
{
|
||||
label: 'Date From',
|
||||
@ -102,6 +111,18 @@ export const useEventLogFilters = (
|
||||
},
|
||||
] as IFilterItem[])
|
||||
: []),
|
||||
...(environmentOptions.length > 0
|
||||
? ([
|
||||
{
|
||||
label: 'Environment',
|
||||
icon: 'cloud',
|
||||
options: environmentOptions,
|
||||
filterKey: 'environment',
|
||||
singularOperators: ['IS'],
|
||||
pluralOperators: ['IS_ANY_OF'],
|
||||
},
|
||||
] as IFilterItem[])
|
||||
: []),
|
||||
];
|
||||
|
||||
setAvailableFilters(availableFilters);
|
||||
@ -109,6 +130,7 @@ export const useEventLogFilters = (
|
||||
JSON.stringify(features),
|
||||
JSON.stringify(projects),
|
||||
JSON.stringify(eventCreators),
|
||||
JSON.stringify(environments),
|
||||
]);
|
||||
|
||||
return availableFilters;
|
||||
|
@ -71,6 +71,7 @@ export const useEventLogSearch = (
|
||||
}),
|
||||
createdBy: FilterItemParam,
|
||||
type: FilterItemParam,
|
||||
environment: FilterItemParam,
|
||||
...extraParameters(logType),
|
||||
};
|
||||
|
||||
|
@ -213,7 +213,6 @@ export default class EventService {
|
||||
representation: 'date',
|
||||
}),
|
||||
);
|
||||
|
||||
queryParams.push({
|
||||
field: parsed.field,
|
||||
operator: 'IS_BEFORE',
|
||||
@ -238,7 +237,7 @@ export default class EventService {
|
||||
if (parsed) queryParams.push(parsed);
|
||||
}
|
||||
|
||||
['project', 'type'].forEach((field) => {
|
||||
['project', 'type', 'environment'].forEach((field) => {
|
||||
if (params[field]) {
|
||||
const parsed = parseSearchOperatorValue(field, params[field]);
|
||||
if (parsed) queryParams.push(parsed);
|
||||
|
@ -100,6 +100,17 @@ export const eventSearchQueryParameters = [
|
||||
'The number of feature environments to return in a page. By default it is set to 50. The maximum is 1000.',
|
||||
in: 'query',
|
||||
},
|
||||
{
|
||||
name: 'environment',
|
||||
schema: {
|
||||
type: 'string',
|
||||
example: 'IS:production',
|
||||
pattern: '^(IS|IS_ANY_OF):(.*?)(,([a-zA-Z0-9_]+))*$',
|
||||
},
|
||||
description:
|
||||
'Filter by environment name using supported operators: IS, IS_ANY_OF.',
|
||||
in: 'query',
|
||||
},
|
||||
] as const;
|
||||
|
||||
export type EventSearchQueryParameters = Partial<
|
||||
|
@ -16,6 +16,7 @@ export interface IEventSearchParams {
|
||||
to?: string;
|
||||
createdBy?: string;
|
||||
type?: string;
|
||||
environment?: string;
|
||||
offset: number;
|
||||
limit: number;
|
||||
}
|
||||
|
@ -575,3 +575,82 @@ test('should show user creation events for admins', async () => {
|
||||
total: 2,
|
||||
});
|
||||
});
|
||||
|
||||
test('should filter events by environment', async () => {
|
||||
await eventService.storeEvent({
|
||||
type: FEATURE_CREATED,
|
||||
project: 'default',
|
||||
environment: 'production',
|
||||
createdBy: 'test-user',
|
||||
createdByUserId: TEST_USER_ID,
|
||||
ip: '127.0.0.1',
|
||||
});
|
||||
|
||||
await eventService.storeEvent({
|
||||
type: FEATURE_CREATED,
|
||||
project: 'default',
|
||||
environment: 'staging',
|
||||
createdBy: 'test-user',
|
||||
createdByUserId: TEST_USER_ID,
|
||||
ip: '127.0.0.1',
|
||||
});
|
||||
|
||||
const { body } = await searchEvents({ environment: 'IS:production' });
|
||||
|
||||
expect(body).toMatchObject({
|
||||
events: [
|
||||
{
|
||||
type: 'feature-created',
|
||||
environment: 'production',
|
||||
},
|
||||
],
|
||||
total: 1,
|
||||
});
|
||||
});
|
||||
|
||||
test('should filter events by environment using IS_ANY_OF', async () => {
|
||||
await eventService.storeEvent({
|
||||
type: FEATURE_CREATED,
|
||||
project: 'default',
|
||||
environment: 'production',
|
||||
createdBy: 'test-user',
|
||||
createdByUserId: TEST_USER_ID,
|
||||
ip: '127.0.0.1',
|
||||
});
|
||||
|
||||
await eventService.storeEvent({
|
||||
type: FEATURE_CREATED,
|
||||
project: 'default',
|
||||
environment: 'staging',
|
||||
createdBy: 'test-user',
|
||||
createdByUserId: TEST_USER_ID,
|
||||
ip: '127.0.0.1',
|
||||
});
|
||||
|
||||
await eventService.storeEvent({
|
||||
type: FEATURE_CREATED,
|
||||
project: 'default',
|
||||
environment: 'development',
|
||||
createdBy: 'test-user',
|
||||
createdByUserId: TEST_USER_ID,
|
||||
ip: '127.0.0.1',
|
||||
});
|
||||
|
||||
const { body } = await searchEvents({
|
||||
environment: 'IS_ANY_OF:production,staging',
|
||||
});
|
||||
|
||||
expect(body).toMatchObject({
|
||||
events: [
|
||||
{
|
||||
type: 'feature-created',
|
||||
environment: 'staging',
|
||||
},
|
||||
{
|
||||
type: 'feature-created',
|
||||
environment: 'production',
|
||||
},
|
||||
],
|
||||
total: 2,
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user