Skip to content

Commit

Permalink
Events pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
jgyselov committed Apr 19, 2023
1 parent 7786c56 commit 6eebb7c
Show file tree
Hide file tree
Showing 11 changed files with 330 additions and 297 deletions.
5 changes: 2 additions & 3 deletions locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
"ai:{{count}} control plane node failed_plural": "{{count}} control plane nodes failed",
"ai:{{count}} control plane node installed": "{{count}} control plane node installed",
"ai:{{count}} control plane node installed_plural": "{{count}} control plane nodes installed",
"ai:{{count}} filter applied": "{{count}} filter applied",
"ai:{{count}} filter applied_plural": "{{count}} filters applied",
"ai:{{count}} filtering label": "{{count}} filtering label",
"ai:{{count}} filtering label_plural": "{{count}} filtering labels",
"ai:{{count}} host has problems": "{{count}} host has problems",
Expand Down Expand Up @@ -490,7 +492,6 @@
"ai:Next": "Next",
"ai:NMState": "NMState",
"ai:No available hosts with {{cpuArchitecture}} architecture were found": "No available hosts with {{cpuArchitecture}} architecture were found",
"ai:No events found": "No events found",
"ai:No host is selected.": "No host is selected.",
"ai:No host matches provided labels/locations": "No host matches provided labels/locations",
"ai:No hosts found": "No hosts found",
Expand Down Expand Up @@ -610,7 +611,6 @@
"ai:See cluster details": "See cluster details",
"ai:Select a state": "Select a state",
"ai:Select all": "Select all",
"ai:Select All": "Select All",
"ai:Select none": "Select none",
"ai:Select one or more locations to view hosts": "Select one or more locations to view hosts",
"ai:Select one or multiple locations to choose the hosts from.": "Select one or multiple locations to choose the hosts from.",
Expand Down Expand Up @@ -686,7 +686,6 @@
"ai:The use of Tang encryption mode to encrypt your disks is only supported for bare metal or vSphere installations on user-provisioned infrastructure.": "The use of Tang encryption mode to encrypt your disks is only supported for bare metal or vSphere installations on user-provisioned infrastructure.",
"ai:The Value is not valid BMC address, supported protocols are redfish-virtualmedia or idrac-virtualmedia.": "The Value is not valid BMC address, supported protocols are redfish-virtualmedia or idrac-virtualmedia.",
"ai:The YAML file might not be formatted correctly. Use the template to format and try again.": "The YAML file might not be formatted correctly. Use the template to format and try again.",
"ai:There are no events found.": "There are no events found.",
"ai:There are no events that match the current filters. Adjust or clear the filters to view events.": "There are no events that match the current filters. Adjust or clear the filters to view events.",
"ai:There is still {{count}} pending check": "There is still {{count}} pending check",
"ai:There is still {{count}} pending check_plural": "There are still {{count}} pending checks",
Expand Down
140 changes: 118 additions & 22 deletions src/common/components/fetching/EventListFetch.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,150 @@
import React, { useEffect, useState } from 'react';
import React from 'react';
import { EventList } from '../../api';
import { EVENTS_POLLING_INTERVAL } from '../../config';
import { EventListFetchProps } from '../../types';
import { EVENTS_POLLING_INTERVAL, EVENT_SEVERITIES } from '../../config';
import { ClusterEventsFiltersType, EventListFetchProps } from '../../types';

// avoid circular dep
import { ErrorState, LoadingState } from '../ui/uiState';
import EventsList from '../ui/EventsList';
import ClusterEventsList from '../ui/ClusterEventsList';
import { Pagination, PaginationVariant } from '@patternfly/react-core';
import ClusterEventsToolbar, {
getInitialClusterEventsFilters,
SeverityCountsType,
} from '../ui/ClusterEventsToolbar';
import { AxiosResponseHeaders } from 'axios';
import omit from 'lodash/omit';

export const EventListFetch: React.FC<EventListFetchProps> = ({ onFetchEvents, ...props }) => {
const [events, setEvents] = useState<EventList>();
const [lastPolling, setLastPolling] = useState(0);
const [error, setError] = useState('');
const initialSeverityCounts = {
critical: 0,
error: 0,
info: 0,
warning: 0,
};

export const EventListFetch = ({ onFetchEvents, ...props }: EventListFetchProps) => {
const { cluster, hostId, className, entityKind } = props;

const [lastPolling, setLastPolling] = React.useState(0);
const [error, setError] = React.useState('');
const [isLoading, setLoading] = React.useState(true);
const [events, setEvents] = React.useState<EventList>();

const [pageNum, setPageNum] = React.useState(1);
const [perPage, setPerPage] = React.useState(10);
const [totalEvents, setTotalEvents] = React.useState<number>();
const [filters, setFilters] = React.useState<ClusterEventsFiltersType>(() =>
getInitialClusterEventsFilters(entityKind, hostId),
);
const [severityCounts, setSeverityCount] =
React.useState<SeverityCountsType>(initialSeverityCounts);

const onSetPage = (
_event: React.MouseEvent | React.KeyboardEvent | MouseEvent,
newPage: number,
) => {
setPageNum(newPage);
};

const { cluster, hostId, entityKind, className } = props;
const onPerPageSelect = (
_event: React.MouseEvent | React.KeyboardEvent | MouseEvent,
newPerPage: number,
newPage: number,
) => {
setPerPage(newPerPage);
setPageNum(newPage);
};

useEffect(() => {
const parseHeaders = React.useCallback((headers: AxiosResponseHeaders) => {
let total = 0;
const severities = {};
EVENT_SEVERITIES.forEach((severity) => {
const count = Number(headers[`severity-count-${severity}`]);
severities[severity] = count;
total += count;
});
setTotalEvents(total);
setSeverityCount(severities as SeverityCountsType);
}, []);

React.useEffect(() => {
let timer: ReturnType<typeof setTimeout>;
setLoading(true);

void onFetchEvents(
{
clusterId: cluster.id,
hostId,
...omit(filters, 'selectAll'),
offset: perPage * (pageNum - 1),
limit: perPage,
},
(events: EventList) => {
setEvents(events);
({ data: newEvents, headers }) => {
setError('');
setEvents(newEvents);
setLoading(false);
parseHeaders(headers);
timer = setTimeout(() => setLastPolling(Date.now()), EVENTS_POLLING_INTERVAL);
},
setError,
);

return () => clearTimeout(timer);
}, [lastPolling, cluster.id, hostId, onFetchEvents]);
}, [
lastPolling,
cluster.id,
hostId,
onFetchEvents,
perPage,
pageNum,
parseHeaders,
totalEvents,
filters,
]);

const forceRefetch = React.useCallback(() => {
setLastPolling(Date.now());
}, [setLastPolling]);

if (error) {
return <ErrorState title={error} fetchData={forceRefetch} />;
}
let eventList = (
<EventsList
events={events || []}
className={className}
resetFilters={() => setFilters(getInitialClusterEventsFilters(entityKind, hostId))}
/>
);

if (!events) {
return <LoadingState />;
if (error) {
eventList = <ErrorState title={error} fetchData={forceRefetch} />;
}

if (entityKind === 'cluster') {
return <ClusterEventsList events={events} cluster={cluster} className={className} />;
if (isLoading || !events) {
eventList = <LoadingState />;
}

return <EventsList events={events} className={className} />;
return (
<>
<ClusterEventsToolbar
filters={filters}
setFilters={(filters) => {
setFilters(filters);
setPageNum(1);
}}
cluster={cluster}
hostId={hostId}
entityKind={entityKind}
events={events || []}
severityCounts={severityCounts}
/>
{eventList}
<Pagination
perPageComponent="button"
itemCount={totalEvents}
widgetId="events-pagination"
perPage={perPage}
page={pageNum}
variant={PaginationVariant.bottom}
onSetPage={onSetPage}
onPerPageSelect={onPerPageSelect}
/>
</>
);
};
81 changes: 0 additions & 81 deletions src/common/components/ui/ClusterEventsList.tsx

This file was deleted.

0 comments on commit 6eebb7c

Please sign in to comment.