Bug 1713303 - Provide link to next/previous alert (#7170)

* Add next/previous button to Perfherder alerts page
* Add ref alert summaries and scroll behavior
* Add unit tests
This commit is contained in:
esanuandra 2021-06-23 20:54:05 +03:00 коммит произвёл GitHub
Родитель 091d422ca0
Коммит 8ed849ce10
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 144 добавлений и 16 удалений

Просмотреть файл

@ -738,3 +738,29 @@ test('test data can be sorted only by one column', async () => {
expect(alertTableRows[1]).toContainElement(alert1);
expect(alertTableRows[2]).toContainElement(alert3);
});
test('test previous alert button should be disable at first', async () => {
const { getByTestId } = alertsViewControls();
const prevScrollButton = await waitFor(() =>
getByTestId('scroll-prev-alert'),
);
expect(prevScrollButton).toBeDisabled();
});
test('test next alert button should be disable when reaching the last alert', async () => {
const { getByTestId } = alertsViewControls();
Element.prototype.scrollIntoView = jest.fn();
let nextScrollButton = await waitFor(() => getByTestId('scroll-next-alert'));
expect(nextScrollButton).not.toBeDisabled();
fireEvent.click(nextScrollButton);
fireEvent.click(nextScrollButton);
nextScrollButton = await waitFor(() => getByTestId('scroll-next-alert'));
expect(nextScrollButton).toBeDisabled();
});

Просмотреть файл

@ -338,6 +338,13 @@ th {
z-index: 900;
}
.sticky-scroll-nav-top {
position: -webkit-sticky;
position: sticky;
top: 0;
z-index: 998;
}
.alerts-container {
padding-left: 90px;
padding-right: 90px;

Просмотреть файл

@ -1,14 +1,49 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Row } from 'reactstrap';
import { Row, Button, Container } from 'reactstrap';
import FilterControls from '../../shared/FilterControls';
import { summaryStatusMap } from '../perf-helpers/constants';
import { summaryStatusMap, scrollTypes } from '../perf-helpers/constants';
import AlertTable from './AlertTable';
import PaginationGroup from './Pagination';
export default class AlertsViewControls extends React.Component {
constructor(props) {
super(props);
this.alertsRef = new Array(this.props.alertSummaries.length)
.fill(null)
.map(() => React.createRef());
this.state = {
currentAlert: -1,
alertsLength: this.props.alertSummaries.length,
disableButtons: {
prev: true,
next: false,
},
};
}
componentDidUpdate(prevProps) {
const { alertSummaries } = this.props;
const alertsLength = alertSummaries.length;
if (alertSummaries !== prevProps.alertSummaries) {
this.alertsRef = new Array(alertsLength)
.fill(null)
.map(() => React.createRef());
// eslint-disable-next-line react/no-did-update-set-state
this.setState({
currentAlert: -1,
alertsLength,
disableButtons: {
prev: true,
next: false,
},
});
}
}
updateFilterText = (filterText) => {
this.props.setFiltersState({ filterText });
};
@ -35,7 +70,36 @@ export default class AlertsViewControls extends React.Component {
setFiltersState({ framework }, this.fetchAlertSummaries);
};
updateCurrentAlert = async (currentAlert) => {
const { disableButtons, alertsLength } = this.state;
disableButtons.next = currentAlert === alertsLength - 1;
disableButtons.prev = currentAlert === 0;
this.setState({ currentAlert, disableButtons }, () => {
this.alertsRef[currentAlert].current.scrollIntoView({
behavior: 'smooth',
block: 'start',
});
});
};
onScrollAlert = (type) => {
const { alertsLength } = this.state;
let { currentAlert } = this.state;
if (type === scrollTypes.next && currentAlert !== alertsLength - 1) {
currentAlert += 1;
}
if (type === scrollTypes.prev && currentAlert !== 0) {
currentAlert -= 1;
}
this.updateCurrentAlert(currentAlert);
};
render() {
const { disableButtons } = this.state;
const {
alertSummaries,
fetchAlertSummaries,
@ -102,6 +166,31 @@ export default class AlertsViewControls extends React.Component {
return (
<React.Fragment>
{alertSummaries.length > 1 && (
<Container className="sticky-scroll-nav-top max-width-default position-fixed mb-4 p-0 pr-4">
<Container className="bg-white max-width-default p-0 pt-5 pb-1">
<div className="d-flex justify-content-end mb-1 mr-2">
<Button
className="mr-2"
color="info"
onClick={() => this.onScrollAlert(scrollTypes.prev)}
disabled={disableButtons.prev}
data-testid="scroll-prev-alert"
>
Previous alert
</Button>
<Button
color="info"
onClick={() => this.onScrollAlert(scrollTypes.next)}
disabled={disableButtons.next}
data-testid="scroll-next-alert"
>
Next alert
</Button>
</div>
</Container>
</Container>
)}
<FilterControls
dropdownOptions={isListMode ? alertDropdowns : []}
filterOptions={alertCheckboxes}
@ -123,20 +212,21 @@ export default class AlertsViewControls extends React.Component {
)
: null}
{alertSummaries.length > 0 &&
alertSummaries.map((alertSummary) => (
<AlertTable
filters={{
filterText,
hideImprovements,
hideDownstream,
hideAssignedToOthers,
}}
key={alertSummary.id}
alertSummary={alertSummary}
fetchAlertSummaries={fetchAlertSummaries}
user={user}
{...this.props}
/>
alertSummaries.map((alertSummary, index) => (
<div key={alertSummary.id} ref={this.alertsRef[index]}>
<AlertTable
filters={{
filterText,
hideImprovements,
hideDownstream,
hideAssignedToOthers,
}}
alertSummary={alertSummary}
fetchAlertSummaries={fetchAlertSummaries}
user={user}
{...this.props}
/>
</div>
))}
{pageNums
? hasMorePages() && (

Просмотреть файл

@ -130,3 +130,8 @@ export const visualMetrics = [
];
export const testDocumentationFrameworks = ['talos', 'awsy'];
export const scrollTypes = {
prev: 'prev',
next: 'next',
};