Skip to content

Commit 9c82e48

Browse files
committed
Events UI #3309 Added links to event list from project and user details pages
1 parent dbdbf4d commit 9c82e48

5 files changed

Lines changed: 86 additions & 32 deletions

File tree

frontend/src/locale/en.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@
182182
"repositories": "Repositories",
183183
"runs": "Runs",
184184
"tags": "Tags",
185+
"events": "Project events",
185186
"settings": "Settings",
186187
"join": "Join",
187188
"leave_confirm_title": "Leave project",
@@ -695,6 +696,8 @@
695696
"account_settings": "User settings",
696697
"settings": "Settings",
697698
"projects": "Projects",
699+
"events": "User events",
700+
"activity": "User activity",
698701
"create": {
699702
"page_title": "Create user",
700703
"error_notification": "Create user error",

frontend/src/pages/Events/List/hooks/useFilters.ts

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { useMemo, useState } from 'react';
22
import { useSearchParams } from 'react-router-dom';
3+
import { omit } from 'lodash';
34

45
import type { PropertyFilterProps } from 'components';
56

@@ -77,8 +78,8 @@ const targetTypes = [
7778

7879
export const useFilters = () => {
7980
const [searchParams, setSearchParams] = useSearchParams();
80-
const { data: projectsData } = useGetProjectsQuery({});
81-
const { data: usersData } = useGetUserListQuery({});
81+
const { data: projectsData, isLoading: isLoadingProjects } = useGetProjectsQuery({});
82+
const { data: usersData, isLoading: isLoadingUsers } = useGetUserListQuery({});
8283

8384
const [propertyFilterQuery, setPropertyFilterQuery] = useState<PropertyFilterProps.Query>(() =>
8485
requestParamsToTokens<RequestParamsKeys>({ searchParams, filterKeys }),
@@ -243,51 +244,65 @@ export const useFilters = () => {
243244
arrayFieldKeys: multipleChoiseKeys,
244245
});
245246

247+
const targetProjects = params[filterKeys.TARGET_PROJECTS]
248+
?.map((name: string) => projectsData?.data?.find(({ project_name }) => project_name === name)?.['project_id'])
249+
.filter(Boolean);
250+
251+
const withInProjects = params[filterKeys.WITHIN_PROJECTS]
252+
?.map((name: string) => projectsData?.data?.find(({ project_name }) => project_name === name)?.['project_id'])
253+
.filter(Boolean);
254+
255+
const targetUsers = params[filterKeys.TARGET_USERS]
256+
?.map((name: string) => usersData?.data?.find(({ username }) => username === name)?.['id'])
257+
.filter(Boolean);
258+
259+
const actors = params[filterKeys.ACTORS]
260+
?.map((name: string) => usersData?.data?.find(({ username }) => username === name)?.['id'])
261+
.filter(Boolean);
262+
263+
const includeTargetTypes = params[filterKeys.INCLUDE_TARGET_TYPES]
264+
?.map((selectedLabel: string) => targetTypes?.find(({ label }) => label === selectedLabel)?.['value'])
265+
.filter(Boolean);
266+
246267
const mappedFields = {
247-
...(params[filterKeys.TARGET_PROJECTS] && Array.isArray(params[filterKeys.TARGET_PROJECTS])
268+
...(targetProjects?.length
248269
? {
249-
[filterKeys.TARGET_PROJECTS]: params[filterKeys.TARGET_PROJECTS]?.map(
250-
(name: string) =>
251-
projectsData?.data?.find(({ project_name }) => project_name === name)?.['project_id'],
252-
),
270+
[filterKeys.TARGET_PROJECTS]: targetProjects,
253271
}
254272
: {}),
255-
...(params[filterKeys.WITHIN_PROJECTS] && Array.isArray(params[filterKeys.WITHIN_PROJECTS])
273+
...(withInProjects?.length
256274
? {
257-
[filterKeys.WITHIN_PROJECTS]: params[filterKeys.WITHIN_PROJECTS]?.map(
258-
(name: string) =>
259-
projectsData?.data?.find(({ project_name }) => project_name === name)?.['project_id'],
260-
),
275+
[filterKeys.WITHIN_PROJECTS]: withInProjects,
261276
}
262277
: {}),
263278

264-
...(params[filterKeys.TARGET_USERS] && Array.isArray(params[filterKeys.TARGET_USERS])
279+
...(targetUsers?.length
265280
? {
266-
[filterKeys.TARGET_USERS]: params[filterKeys.TARGET_USERS]?.map(
267-
(name: string) => usersData?.data?.find(({ username }) => username === name)?.['id'],
268-
),
281+
[filterKeys.TARGET_USERS]: targetUsers,
269282
}
270283
: {}),
271284

272-
...(params[filterKeys.ACTORS] && Array.isArray(params[filterKeys.ACTORS])
285+
...(actors?.length
273286
? {
274-
[filterKeys.ACTORS]: params[filterKeys.ACTORS]?.map(
275-
(name: string) => usersData?.data?.find(({ username }) => username === name)?.['id'],
276-
),
287+
[filterKeys.ACTORS]: actors,
277288
}
278289
: {}),
279290

280-
...(params[filterKeys.INCLUDE_TARGET_TYPES] && Array.isArray(params[filterKeys.INCLUDE_TARGET_TYPES])
291+
...(includeTargetTypes?.length
281292
? {
282-
[filterKeys.INCLUDE_TARGET_TYPES]: params[filterKeys.INCLUDE_TARGET_TYPES]?.map(
283-
(selectedLabel: string) => targetTypes?.find(({ label }) => label === selectedLabel)?.['value'],
284-
),
293+
[filterKeys.INCLUDE_TARGET_TYPES]: includeTargetTypes,
285294
}
286295
: {}),
287296
};
288297

289298
return {
290-
...params,
299+
...omit(params, [
300+
filterKeys.TARGET_PROJECTS,
301+
filterKeys.WITHIN_PROJECTS,
302+
filterKeys.TARGET_USERS,
303+
filterKeys.ACTORS,
304+
filterKeys.INCLUDE_TARGET_TYPES,
305+
]),
291306
...mappedFields,
292307
} as Partial<TRunsRequestParams>;
293308
}, [propertyFilterQuery, usersData, projectsData]);
@@ -299,5 +314,6 @@ export const useFilters = () => {
299314
onChangePropertyFilter,
300315
filteringOptions,
301316
filteringProperties,
317+
isLoadingFilters: isLoadingProjects || isLoadingUsers,
302318
} as const;
303319
};

frontend/src/pages/Events/List/index.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,19 @@ export const EventList = () => {
2424
},
2525
]);
2626

27-
const { filteringRequestParams, propertyFilterQuery, onChangePropertyFilter, filteringOptions, filteringProperties } =
28-
useFilters();
27+
const {
28+
filteringRequestParams,
29+
propertyFilterQuery,
30+
onChangePropertyFilter,
31+
filteringOptions,
32+
filteringProperties,
33+
isLoadingFilters,
34+
} = useFilters();
2935

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

3441
getPaginationParams: (lastEvent) => ({
3542
prev_recorded_at: lastEvent.recorded_at,
@@ -47,13 +54,15 @@ export const EventList = () => {
4754

4855
const { columns } = useColumnsDefinitions();
4956

57+
const loading = isLoadingFilters || isLoading;
58+
5059
return (
5160
<Table
5261
{...collectionProps}
5362
variant="full-page"
5463
columnDefinitions={columns}
5564
items={items}
56-
loading={isLoading}
65+
loading={loading}
5766
loadingText={t('common.loading')}
5867
stickyHeader={true}
5968
selectionType="multi"
@@ -64,7 +73,7 @@ export const EventList = () => {
6473
<SpaceBetween size="xs" direction="horizontal">
6574
<Button
6675
iconName="refresh"
67-
disabled={isLoading}
76+
disabled={loading}
6877
ariaLabel={t('common.refresh')}
6978
onClick={refreshList}
7079
/>

frontend/src/pages/Project/Details/index.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
11
import React from 'react';
2+
import { useTranslation } from 'react-i18next';
23
import { Outlet, useParams } from 'react-router-dom';
34

4-
import { ContentLayout, DetailsHeader } from 'components';
5+
import { ContentLayout, DetailsHeader, NavigateLink } from 'components';
6+
7+
import { ROUTES } from 'routes';
58

69
export const ProjectDetails: React.FC = () => {
710
const params = useParams();
811
const paramProjectName = params.projectName ?? '';
12+
const { t } = useTranslation();
913

1014
return (
11-
<ContentLayout header={<DetailsHeader title={paramProjectName} />}>
15+
<ContentLayout
16+
header={
17+
<DetailsHeader
18+
title={paramProjectName}
19+
actionButtons={
20+
<NavigateLink href={ROUTES.EVENTS.LIST + `?within_projects=${paramProjectName}`}>
21+
{t('projects.events')}
22+
</NavigateLink>
23+
}
24+
/>
25+
}
26+
>
1227
<Outlet />
1328
</ContentLayout>
1429
);

frontend/src/pages/User/Details/index.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
22
import { useTranslation } from 'react-i18next';
33
import { Outlet, useNavigate, useParams } from 'react-router-dom';
44

5-
import { Box, ConfirmationDialog, ContentLayout, SpaceBetween, Tabs } from 'components';
5+
import { Box, ConfirmationDialog, ContentLayout, NavigateLink, SpaceBetween, Tabs } from 'components';
66
import { DetailsHeader } from 'components';
77

88
import { useNotifications /* usePermissionGuard*/ } from 'hooks';
@@ -87,6 +87,17 @@ export const UserDetails: React.FC = () => {
8787
title={paramUserName}
8888
// deleteAction={isAvailableDeleteUser ? toggleDeleteConfirm : undefined}
8989
// deleteDisabled={isDeleting}
90+
actionButtons={
91+
<>
92+
<NavigateLink href={ROUTES.EVENTS.LIST + `?target_users=${paramUserName}`}>
93+
{t('users.events')}
94+
</NavigateLink>
95+
96+
<NavigateLink href={ROUTES.EVENTS.LIST + `?actors=${paramUserName}`}>
97+
{t('users.activity')}
98+
</NavigateLink>
99+
</>
100+
}
90101
/>
91102
}
92103
>

0 commit comments

Comments
 (0)