Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frontend/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { useConfirmationDialog } from './useConfirmationDialog';
export { useHelpPanel } from './useHelpPanel';
export { usePermissionGuard } from './usePermissionGuard';
export { useInfiniteScroll } from './useInfiniteScroll';
export { useLocalStorageState } from './useLocalStorageState';

// cloudscape
export { useCollection } from '@cloudscape-design/collection-hooks';
117 changes: 69 additions & 48 deletions frontend/src/pages/Events/List/hooks/useFilters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { omit } from 'lodash';
import type { PropertyFilterProps } from 'components';

import { EMPTY_QUERY, requestParamsToTokens, tokensToRequestParams, tokensToSearchParams } from 'libs/filters';
import { useGetProjectsQuery } from 'services/project';
import { useGetUserListQuery } from 'services/user';
import { useLazyGetProjectsQuery } from 'services/project';
import { useLazyGetUserListQuery } from 'services/user';

import { filterLastElementByPrefix } from '../helpers';

Expand Down Expand Up @@ -71,42 +71,49 @@ const baseFilteringProperties = [
key: filterKeys.TARGET_USERS,
operators: ['='],
propertyLabel: 'Target users',
groupValuesLabel: 'Project ids',
groupValuesLabel: 'User ids',
},
{
key: filterKeys.TARGET_FLEETS,
operators: ['='],
propertyLabel: 'Target fleet IDs',
groupValuesLabel: 'Fleet ids',
},
{
key: filterKeys.TARGET_INSTANCES,
operators: ['='],
propertyLabel: 'Target instance IDs',
groupValuesLabel: 'Instance ids',
},
{
key: filterKeys.TARGET_RUNS,
operators: ['='],
propertyLabel: 'Target run IDs',
groupValuesLabel: 'Run ids',
},
{
key: filterKeys.TARGET_JOBS,
operators: ['='],
propertyLabel: 'Target job IDs',
groupValuesLabel: 'Job ids',
},
{
key: filterKeys.TARGET_VOLUMES,
operators: ['='],
propertyLabel: 'Target volume IDs',
groupValuesLabel: 'Volume ids',
},
{
key: filterKeys.TARGET_GATEWAYS,
operators: ['='],
propertyLabel: 'Target gateway IDs',
groupValuesLabel: 'Gateway ids',
},
{
key: filterKeys.TARGET_SECRETS,
operators: ['='],
propertyLabel: 'Target secret IDs',
groupValuesLabel: 'Secret ids',
},

{
Expand All @@ -120,12 +127,14 @@ const baseFilteringProperties = [
key: filterKeys.WITHIN_FLEETS,
operators: ['='],
propertyLabel: 'Within fleet IDs',
groupValuesLabel: 'Fleet ids',
},

{
key: filterKeys.WITHIN_RUNS,
operators: ['='],
propertyLabel: 'Within run IDs',
groupValuesLabel: 'Run ids',
},

{
Expand All @@ -139,9 +148,12 @@ const baseFilteringProperties = [
key: filterKeys.ACTORS,
operators: ['='],
propertyLabel: 'Actors',
groupValuesLabel: 'User names',
},
];

const limit = 100;

export const useFilters = ({
permanentFilters,
withSearchParams,
Expand All @@ -150,8 +162,10 @@ export const useFilters = ({
withSearchParams?: boolean;
}) => {
const [searchParams, setSearchParams] = useSearchParams();
const { data: projectsData, isLoading: isLoadingProjects } = useGetProjectsQuery({});
const { data: usersData, isLoading: isLoadingUsers } = useGetUserListQuery({});
const [dynamicFilteringOptions, setDynamicFilteringOptions] = useState<PropertyFilterProps.FilteringOption[]>([]);
const [filteringStatusType, setFilteringStatusType] = useState<PropertyFilterProps.StatusType | undefined>();
const [getProjects] = useLazyGetProjectsQuery();
const [getUsers] = useLazyGetUserListQuery();

const [propertyFilterQuery, setPropertyFilterQuery] = useState<PropertyFilterProps.Query>(() =>
requestParamsToTokens<RequestParamsKeys>({ searchParams, filterKeys }),
Expand All @@ -165,31 +179,7 @@ export const useFilters = ({
};

const filteringOptions = useMemo(() => {
const options: PropertyFilterProps.FilteringOption[] = [];

projectsData?.data?.forEach(({ project_name }) => {
options.push({
propertyKey: filterKeys.TARGET_PROJECTS,
value: project_name,
});

options.push({
propertyKey: filterKeys.WITHIN_PROJECTS,
value: project_name,
});
});

usersData?.data?.forEach(({ username }) => {
options.push({
propertyKey: filterKeys.TARGET_USERS,
value: username,
});

options.push({
propertyKey: filterKeys.ACTORS,
value: username,
});
});
const options: PropertyFilterProps.FilteringOption[] = [...dynamicFilteringOptions];

targetTypes?.forEach((targetType) => {
options.push({
Expand All @@ -199,7 +189,7 @@ export const useFilters = ({
});

return options;
}, [projectsData, usersData]);
}, [dynamicFilteringOptions]);

const setSearchParamsHandle = ({ tokens }: { tokens: PropertyFilterProps.Query['tokens'] }) => {
const searchParams = tokensToSearchParams<RequestParamsKeys>(tokens);
Expand Down Expand Up @@ -293,25 +283,15 @@ export const useFilters = ({
return [paramsFilter, permanentFilter];
};

const targetProjects = filterParamsWithPermanentFitters(filterKeys.TARGET_PROJECTS)
.map((name: string) => projectsData?.data?.find(({ project_name }) => project_name === name)?.['project_id'])
.filter(Boolean);
const targetProjects = filterParamsWithPermanentFitters(filterKeys.TARGET_PROJECTS).filter(Boolean);

const withInProjects = filterParamsWithPermanentFitters(filterKeys.WITHIN_PROJECTS)
.map((name: string) => projectsData?.data?.find(({ project_name }) => project_name === name)?.['project_id'])
.filter(Boolean);
const withInProjects = filterParamsWithPermanentFitters(filterKeys.WITHIN_PROJECTS).filter(Boolean);

const targetUsers = filterParamsWithPermanentFitters(filterKeys.TARGET_USERS)
.map((name: string) => usersData?.data?.find(({ username }) => username === name)?.['id'])
.filter(Boolean);
const targetUsers = filterParamsWithPermanentFitters(filterKeys.TARGET_USERS).filter(Boolean);

const actors = filterParamsWithPermanentFitters(filterKeys.ACTORS)
.map((name: string) => usersData?.data?.find(({ username }) => username === name)?.['id'])
.filter(Boolean);
const actors = filterParamsWithPermanentFitters(filterKeys.ACTORS).filter(Boolean);

const includeTargetTypes = filterParamsWithPermanentFitters(filterKeys.INCLUDE_TARGET_TYPES)
.map((selectedLabel: string) => targetTypes?.find(({ label }) => label === selectedLabel)?.['value'])
.filter(Boolean);
const includeTargetTypes = filterParamsWithPermanentFitters(filterKeys.INCLUDE_TARGET_TYPES).filter(Boolean);

const mappedFields = {
...(targetProjects?.length
Expand Down Expand Up @@ -355,7 +335,47 @@ export const useFilters = ({
...permanentFilters,
...mappedFields,
} as TEventListFilters;
}, [propertyFilterQuery, usersData, projectsData, permanentFilters]);
}, [propertyFilterQuery, permanentFilters]);

const handleLoadItems: PropertyFilterProps['onLoadItems'] = async ({ detail: { filteringProperty, filteringText } }) => {
setDynamicFilteringOptions([]);

if (!filteringText.length) {
return Promise.resolve();
}

setFilteringStatusType('loading');

if (filteringProperty?.key === filterKeys.TARGET_PROJECTS || filteringProperty?.key === filterKeys.WITHIN_PROJECTS) {
await getProjects({ name_pattern: filteringText, limit })
.unwrap()
.then(({ data }) =>
data.map(({ project_name, project_id }) => ({
propertyKey: filteringProperty?.key,
label: project_name,
value: project_id,
hiddenValue: 'test',
})),
)
.then(setDynamicFilteringOptions);
}

if (filteringProperty?.key === filterKeys.TARGET_USERS || filteringProperty?.key === filterKeys.ACTORS) {
await getUsers({ name_pattern: filteringText, limit })
.unwrap()
.then(({ data }) =>
data.map(({ username, id }) => ({
propertyKey: filteringProperty?.key,
label: username,
value: id,
hiddenValue: 'test2',
})),
)
.then(setDynamicFilteringOptions);
}

setFilteringStatusType(undefined);
};

return {
filteringRequestParams,
Expand All @@ -364,6 +384,7 @@ export const useFilters = ({
onChangePropertyFilter,
filteringOptions,
filteringProperties,
isLoadingFilters: isLoadingProjects || isLoadingUsers,
filteringStatusType,
handleLoadItems,
} as const;
};
11 changes: 7 additions & 4 deletions frontend/src/pages/Events/List/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { useLazyGetAllEventsQuery } from 'services/events';
import { useColumnsDefinitions } from './hooks/useColumnDefinitions';
import { useFilters } from './hooks/useFilters';

import styles from '../../Runs/List/styles.module.scss';
import styles from 'pages/Runs/List/styles.module.scss';

type RenderHeaderArgs = {
refreshAction?: () => void;
Expand Down Expand Up @@ -49,13 +49,13 @@ export const EventList: React.FC<EventListProps> = ({
onChangePropertyFilter,
filteringOptions,
filteringProperties,
isLoadingFilters,
filteringStatusType,
handleLoadItems,
} = useFilters({ permanentFilters, withSearchParams });

const { data, isLoading, refreshList, isLoadingMore } = useInfiniteScroll<IEvent, TEventListRequestParams>({
useLazyQuery: useLazyGetAllEventsQuery,
args: { ...filteringRequestParams, limit: DEFAULT_TABLE_PAGE_SIZE },
skip: isLoadingFilters,

getPaginationParams: (lastEvent) => ({
prev_recorded_at: lastEvent.recorded_at,
Expand All @@ -73,7 +73,7 @@ export const EventList: React.FC<EventListProps> = ({

const { columns } = useColumnsDefinitions();

const loading = isLoadingFilters || isLoading;
const loading = isLoading;

return (
<Table
Expand All @@ -99,9 +99,12 @@ export const EventList: React.FC<EventListProps> = ({
filteringAriaLabel: t('projects.run.filter_property_placeholder'),
filteringPlaceholder: t('projects.run.filter_property_placeholder'),
operationAndText: 'and',
enteredTextLabel: (value) => `Use: ${value}`,
}}
filteringOptions={filteringOptions}
filteringProperties={filteringProperties}
filteringStatusType={filteringStatusType}
onLoadItems={handleLoadItems}
/>
</div>
</div>
Expand Down
Loading