Skip to content

Commit aec51dc

Browse files
authored
Was implemented Event list for job, run and fleet (#3392)
Was implemented Event list for job, run and fleet
1 parent c391d34 commit aec51dc

16 files changed

Lines changed: 458 additions & 117 deletions

File tree

frontend/src/hooks/useInfiniteScroll.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type UseInfinityParams<DataItem, Args extends InfinityListArgs> = {
1414
useLazyQuery: UseLazyQuery<QueryDefinition<Args, any, any, ListResponse<DataItem>, any>>;
1515
args: { limit?: number } & Args;
1616
getPaginationParams: (listItem: DataItem) => Partial<Args>;
17+
skip?: boolean;
1718
// options?: UseQueryStateOptions<QueryDefinition<Args, any, any, Data[], any>, Record<string, any>>;
1819
};
1920

@@ -22,6 +23,7 @@ export const useInfiniteScroll = <DataItem, Args extends InfinityListArgs>({
2223
getPaginationParams,
2324
// options,
2425
args,
26+
skip,
2527
}: UseInfinityParams<DataItem, Args>) => {
2628
const [data, setData] = useState<ListResponse<DataItem>>([]);
2729
const scrollElement = useRef<HTMLElement>(document.documentElement);
@@ -55,14 +57,14 @@ export const useInfiniteScroll = <DataItem, Args extends InfinityListArgs>({
5557
};
5658

5759
useEffect(() => {
58-
if (!isEqual(argsProp, lastArgsProps.current)) {
60+
if (!isEqual(argsProp, lastArgsProps.current) && !skip) {
5961
getEmptyList();
6062
lastArgsProps.current = argsProp as Args;
6163
}
62-
}, [argsProp, lastArgsProps]);
64+
}, [argsProp, lastArgsProps, skip]);
6365

6466
const getMore = async () => {
65-
if (isLoadingRef.current || disabledMore) {
67+
if (isLoadingRef.current || disabledMore || skip) {
6668
return;
6769
}
6870

@@ -83,7 +85,9 @@ export const useInfiniteScroll = <DataItem, Args extends InfinityListArgs>({
8385
console.log(e);
8486
}
8587

86-
isLoadingRef.current = false;
88+
setTimeout(() => {
89+
isLoadingRef.current = false;
90+
}, 10);
8791
};
8892

8993
useLayoutEffect(() => {

frontend/src/locale/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
"refresh": "Refresh",
5353
"quickstart": "Quickstart",
5454
"ask_ai": "Ask AI",
55-
"new": "New"
55+
"new": "New",
56+
"full_view": "Full view"
5657
},
5758

5859
"auth": {

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

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,14 @@ const multipleChoiseKeys: RequestParamsKeys[] = [
5454
'actors',
5555
];
5656

57-
const targetTypes = ['project', 'user', 'fleet', 'instance', 'run', 'job'];
57+
const targetTypes = [
58+
{ label: 'Project', value: 'project' },
59+
{ label: 'User', value: 'user' },
60+
{ label: 'Fleet', value: 'fleet' },
61+
{ label: 'Instance', value: 'instance' },
62+
{ label: 'Run', value: 'run' },
63+
{ label: 'Job', value: 'job' },
64+
];
5865

5966
export const useFilters = () => {
6067
const [searchParams, setSearchParams] = useSearchParams();
@@ -100,7 +107,7 @@ export const useFilters = () => {
100107
targetTypes?.forEach((targetType) => {
101108
options.push({
102109
propertyKey: filterKeys.INCLUDE_TARGET_TYPES,
103-
value: targetType,
110+
value: targetType.label,
104111
});
105112
});
106113

@@ -117,53 +124,53 @@ export const useFilters = () => {
117124
{
118125
key: filterKeys.TARGET_PROJECTS,
119126
operators: ['='],
120-
propertyLabel: 'Target Projects',
127+
propertyLabel: 'Target projects',
121128
groupValuesLabel: 'Project ids',
122129
},
123130
{
124131
key: filterKeys.TARGET_USERS,
125132
operators: ['='],
126-
propertyLabel: 'Target Users',
133+
propertyLabel: 'Target users',
127134
groupValuesLabel: 'Project ids',
128135
},
129136
{
130137
key: filterKeys.TARGET_FLEETS,
131138
operators: ['='],
132-
propertyLabel: 'Target Fleets',
139+
propertyLabel: 'Target fleets',
133140
},
134141
{
135142
key: filterKeys.TARGET_INSTANCES,
136143
operators: ['='],
137-
propertyLabel: 'Target Instances',
144+
propertyLabel: 'Target instances',
138145
},
139146
{
140147
key: filterKeys.TARGET_RUNS,
141148
operators: ['='],
142-
propertyLabel: 'Target Runs',
149+
propertyLabel: 'Target runs',
143150
},
144151
{
145152
key: filterKeys.TARGET_JOBS,
146153
operators: ['='],
147-
propertyLabel: 'Target Jobs',
154+
propertyLabel: 'Target jobs',
148155
},
149156

150157
{
151158
key: filterKeys.WITHIN_PROJECTS,
152159
operators: ['='],
153-
propertyLabel: 'Within Projects',
160+
propertyLabel: 'Within projects',
154161
groupValuesLabel: 'Project ids',
155162
},
156163

157164
{
158165
key: filterKeys.WITHIN_FLEETS,
159166
operators: ['='],
160-
propertyLabel: 'Within Fleets',
167+
propertyLabel: 'Within fleets',
161168
},
162169

163170
{
164171
key: filterKeys.WITHIN_RUNS,
165172
operators: ['='],
166-
propertyLabel: 'Within Runs',
173+
propertyLabel: 'Within runs',
167174
},
168175

169176
{
@@ -240,6 +247,14 @@ export const useFilters = () => {
240247
),
241248
}
242249
: {}),
250+
251+
...(params[filterKeys.INCLUDE_TARGET_TYPES] && Array.isArray(params[filterKeys.INCLUDE_TARGET_TYPES])
252+
? {
253+
[filterKeys.INCLUDE_TARGET_TYPES]: params[filterKeys.INCLUDE_TARGET_TYPES]?.map(
254+
(selectedLabel: string) => targetTypes?.find(({ label }) => label === selectedLabel)?.['value'],
255+
),
256+
}
257+
: {}),
243258
};
244259

245260
return {
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import React from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import { useNavigate, useParams } from 'react-router-dom';
4+
import Button from '@cloudscape-design/components/button';
5+
6+
import { Header, Loader, Table } from 'components';
7+
8+
import { DEFAULT_TABLE_PAGE_SIZE } from 'consts';
9+
import { useCollection, useInfiniteScroll } from 'hooks';
10+
import { ROUTES } from 'routes';
11+
import { useLazyGetAllEventsQuery } from 'services/events';
12+
13+
import { useColumnsDefinitions } from 'pages/Events/List/hooks/useColumnDefinitions';
14+
15+
export const EventsList = () => {
16+
const { t } = useTranslation();
17+
const params = useParams();
18+
const paramFleetId = params.fleetId ?? '';
19+
const navigate = useNavigate();
20+
21+
const { data, isLoading, isLoadingMore } = useInfiniteScroll<IEvent, TEventListRequestParams>({
22+
useLazyQuery: useLazyGetAllEventsQuery,
23+
args: { limit: DEFAULT_TABLE_PAGE_SIZE, within_fleets: [paramFleetId] },
24+
25+
getPaginationParams: (lastEvent) => ({
26+
prev_recorded_at: lastEvent.recorded_at,
27+
prev_id: lastEvent.id,
28+
}),
29+
});
30+
31+
const { items, collectionProps } = useCollection<IEvent>(data, {
32+
selection: {},
33+
});
34+
35+
const goToFullView = () => {
36+
navigate(ROUTES.EVENTS.LIST + `?within_fleets=${paramFleetId}`);
37+
};
38+
39+
const { columns } = useColumnsDefinitions();
40+
41+
return (
42+
<Table
43+
{...collectionProps}
44+
columnDefinitions={columns}
45+
items={items}
46+
loading={isLoading}
47+
loadingText={t('common.loading')}
48+
header={
49+
<Header actions={<Button onClick={goToFullView}>{t('common.full_view')}</Button>}>
50+
{t('navigation.events')}
51+
</Header>
52+
}
53+
footer={<Loader show={isLoadingMore} padding={{ vertical: 'm' }} />}
54+
/>
55+
);
56+
};
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import React from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import { useParams } from 'react-router-dom';
4+
import { format } from 'date-fns';
5+
6+
import { Box, ColumnLayout, Container, Header, Loader, NavigateLink, StatusIndicator } from 'components';
7+
8+
import { DATE_TIME_FORMAT } from 'consts';
9+
import { getFleetInstancesLinkText, getFleetPrice, getFleetStatusIconType } from 'libs/fleet';
10+
import { ROUTES } from 'routes';
11+
import { useGetFleetDetailsQuery } from 'services/fleet';
12+
13+
export const FleetDetails = () => {
14+
const { t } = useTranslation();
15+
const params = useParams();
16+
const paramFleetId = params.fleetId ?? '';
17+
const paramProjectName = params.projectName ?? '';
18+
19+
const { data, isLoading } = useGetFleetDetailsQuery(
20+
{
21+
projectName: paramProjectName,
22+
fleetId: paramFleetId,
23+
},
24+
{
25+
refetchOnMountOrArgChange: true,
26+
},
27+
);
28+
29+
const renderPrice = (fleet: IFleet) => {
30+
const price = getFleetPrice(fleet);
31+
32+
if (typeof price === 'number') return `$${price}`;
33+
34+
return '-';
35+
};
36+
37+
return (
38+
<>
39+
{isLoading && (
40+
<Container>
41+
<Loader />
42+
</Container>
43+
)}
44+
45+
{data && (
46+
<Container header={<Header variant="h2">{t('common.general')}</Header>}>
47+
<ColumnLayout columns={4} variant="text-grid">
48+
<div>
49+
<Box variant="awsui-key-label">{t('fleets.fleet')}</Box>
50+
<div>{data.name}</div>
51+
</div>
52+
53+
<div>
54+
<Box variant="awsui-key-label">{t('fleets.instances.status')}</Box>
55+
56+
<div>
57+
<StatusIndicator type={getFleetStatusIconType(data.status)}>
58+
{t(`fleets.statuses.${data.status}`)}
59+
</StatusIndicator>
60+
</div>
61+
</div>
62+
63+
<div>
64+
<Box variant="awsui-key-label">{t('fleets.instances.project')}</Box>
65+
66+
<div>
67+
<NavigateLink href={ROUTES.PROJECT.DETAILS.FORMAT(data.project_name)}>
68+
{data.project_name}
69+
</NavigateLink>
70+
</div>
71+
</div>
72+
73+
<div>
74+
<Box variant="awsui-key-label">{t('fleets.instances.title')}</Box>
75+
76+
<div>
77+
<NavigateLink href={ROUTES.INSTANCES.LIST + `?fleet_ids=${data.id}`}>
78+
{getFleetInstancesLinkText(data)}
79+
</NavigateLink>
80+
</div>
81+
</div>
82+
83+
<div>
84+
<Box variant="awsui-key-label">{t('fleets.instances.started')}</Box>
85+
<div>{format(new Date(data.created_at), DATE_TIME_FORMAT)}</div>
86+
</div>
87+
88+
<div>
89+
<Box variant="awsui-key-label">{t('fleets.instances.price')}</Box>
90+
<div>{renderPrice(data)}</div>
91+
</div>
92+
</ColumnLayout>
93+
</Container>
94+
)}
95+
</>
96+
);
97+
};

0 commit comments

Comments
 (0)