Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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