Bug 1718047 - Reorganize alerts view to show data more compact (#7193)

* Compact data in AlertTable
*  Add sort to Magnitude of Change
* Abbreviate next/previous value, fix spacing tags&options
* Add unit tests for new/previous value
* Rename AlertTableMagnitude to Magnitude
This commit is contained in:
esanuandra 2021-07-06 22:59:34 +03:00 коммит произвёл GitHub
Родитель 8b581baa8d
Коммит f642a7fd4e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 122 добавлений и 74 удалений

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

@ -0,0 +1,31 @@
import React from 'react';
import { render, waitFor } from '@testing-library/react';
import testAlertSummaries from '../../mock/alert_summaries';
import Magnitude from '../../../../ui/perfherder/alerts/Magnitude';
const testAlertSummary = testAlertSummaries[0];
const testAlert = testAlertSummary.alerts[0];
testAlert.prev_value = 1383.38;
testAlert.new_value = 1211.78;
const magnitude = () => {
return render(<Magnitude alert={testAlert} />);
};
test('Previous value is abbreviated', async () => {
const { getByTestId } = magnitude();
const previousValue = await waitFor(() => getByTestId('previous-value'));
expect(previousValue.textContent).toBe('1.4K');
});
test('New value is abbreviated', async () => {
const { getByTestId } = magnitude();
const newValue = await waitFor(() => getByTestId('new-value'));
expect(newValue.textContent).toBe('1.2K');
});

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

@ -53,24 +53,8 @@ export default class AlertTable extends React.Component {
sortValue: 'tags',
currentSort: tableSort.default,
},
PreviousValue: {
name: 'Previous Value',
sortValue: 'prev_value',
currentSort: tableSort.default,
},
Comparison: { name: 'Comparison' },
NewValue: {
name: 'New Value',
sortValue: 'new_value',
currentSort: tableSort.default,
},
AbsoluteDifference: {
name: 'Absolute Difference',
sortValue: 'amount_pct',
currentSort: tableSort.default,
},
Magnitude: {
name: 'Magnitude of Difference',
name: 'Magnitude of Change',
sortValue: 'amount_pct',
currentSort: tableSort.default,
},
@ -364,29 +348,10 @@ export default class AlertTable extends React.Component {
onChangeSort={this.onChangeSort}
/>
</th>
<th className="align-bottom">
{tableConfig.TagsOptions.name}
<th className="align-bottom text-nowrap">
<span>{tableConfig.TagsOptions.name}</span>
<SortButtonDisabled column={tableConfig.TagsOptions} />
</th>
<th className="align-bottom">
<TableColumnHeader
column={tableConfig.PreviousValue}
onChangeSort={this.onChangeSort}
/>
</th>
<th> </th>
<th className="align-bottom">
<TableColumnHeader
column={tableConfig.NewValue}
onChangeSort={this.onChangeSort}
/>
</th>
<th className="align-bottom">
<TableColumnHeader
column={tableConfig.AbsoluteDifference}
onChangeSort={this.onChangeSort}
/>
</th>
<th className="align-bottom">
<TableColumnHeader
column={tableConfig.Magnitude}

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

@ -22,7 +22,6 @@ import {
getSplitTestTitle,
} from '../perf-helpers/helpers';
import SimpleTooltip from '../../shared/SimpleTooltip';
import ProgressBar from '../../shared/ProgressBar';
import {
alertStatusMap,
backfillRetriggeredTitle,
@ -33,6 +32,7 @@ import {
import AlertTablePlatform from './AlertTablePlatform';
import AlertTableTagsOptions from './AlertTableTagsOptions';
import Magnitude from './Magnitude';
export default class AlertTableRow extends React.Component {
constructor(props) {
@ -145,7 +145,7 @@ export default class AlertTableRow extends React.Component {
<span className={statusColor}>{alertStatus}</span>
{alert.related_summary_id && this.getReassignment(alert)}
{alert.backfill_record ? (
<span className="text-darker-info">, important</span>
<span className="text-darker-info">, important </span>
) : null}
)
</React.Fragment>
@ -186,16 +186,19 @@ export default class AlertTableRow extends React.Component {
title={alert.backfill_record ? backfillRetriggeredTitle : ''}
>
{hasDocumentation && alert.title ? (
<div className="alert-docs" data-testid={`alert ${alert.id} title`}>
<span
className="alert-docs"
data-testid={`alert ${alert.id} title`}
>
<a data-testid="docs" href={url}>
{suite}
</a>{' '}
{test}
</div>
</span>
) : (
<div data-testid={`alert ${alert.id} title`}>
<span data-testid={`alert ${alert.id} title`}>
{suite} {test}
</div>
</span>
)}
</span>{' '}
{this.renderAlertStatus(alert, alertStatus, statusColor)}{' '}
@ -307,38 +310,16 @@ export default class AlertTableRow extends React.Component {
this.getTitleText(alert, alertStatus)
)}
</td>
<td className="table-width-md">
<td className="table-width-lg">
<AlertTablePlatform
platform={alert.series_signature.machine_platform}
/>
</td>
<td className="table-width-md">
<td className="table-width-lg">
<AlertTableTagsOptions alertId={alert.id} items={items} />
</td>
<td className="table-width-md">{formatNumber(alert.prev_value)}</td>
<td className="table-width-sm">
<span
className={alert.is_regression ? 'text-danger' : 'text-success'}
>
{alert.prev_value < alert.new_value && <span>&lt;</span>}
{alert.prev_value > alert.new_value && <span>&gt;</span>}
</span>
</td>
<td className="table-width-md">{formatNumber(alert.new_value)}</td>
<td className="table-width-md">
<SimpleTooltip
textClass="detail-hint"
text={`${alert.amount_pct}%`}
tooltipText={`Absolute difference: ${alert.amount_abs}`}
autohide={false}
/>
</td>
<td className="table-width-lg">
<ProgressBar
magnitude={this.getCappedMagnitude(alert.amount_pct)}
regression={alert.is_regression}
color={!alert.is_regression ? 'success' : 'danger'}
/>
<Magnitude alert={alert} />
</td>
<td className="table-width-sm">
<SimpleTooltip

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

@ -32,7 +32,12 @@ export default class AlertTableTagsOptions extends React.Component {
};
return items.map((item) => (
<Badge color="light" key={`${item}`} data-testid={badgeId[type]}>
<Badge
className="mr-1"
color="light"
key={`${item}`}
data-testid={badgeId[type]}
>
{item}
</Badge>
));
@ -72,7 +77,9 @@ export default class AlertTableTagsOptions extends React.Component {
this.showItems(items.slice(this.visibleItems[type]), type)}
</div>
) : (
<Badge color="light">No {type}</Badge>
<Badge className="mb-1" color="light">
No {type}
</Badge>
);
};
@ -80,10 +87,10 @@ export default class AlertTableTagsOptions extends React.Component {
const { options, tags } = this.state;
return (
<React.Fragment>
<div className="d-flex flex-column align-items-start">
{this.displayItems(tags, this.itemsType.tags)}
{this.displayItems(options, this.itemsType.options)}
</React.Fragment>
</div>
);
}
}

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

@ -0,0 +1,64 @@
import React from 'react';
import PropTypes from 'prop-types';
import numeral from 'numeral';
import ProgressBar from '../../shared/ProgressBar';
import SimpleTooltip from '../../shared/SimpleTooltip';
import { formatNumber } from '../perf-helpers/helpers';
export default class Magnitude extends React.PureComponent {
// arbitrary scale from 0-20% multiplied by 5, capped
// at 100 (so 20% regression === 100% bad)
getCappedMagnitude = (percent) => Math.min(Math.abs(percent) * 5, 100);
abbreviateNumber = (num) =>
numeral(num).format('0.0a').toString().toUpperCase();
render() {
const { alert } = this.props;
return (
<div className="d-flex align-items-end justify-content-center">
<div
className="w-50 text-right text-nowrap"
data-testid="previous-value"
>
<SimpleTooltip
textClass="detail-hint"
text={this.abbreviateNumber(alert.prev_value)}
tooltipText={`Previous value: ${formatNumber(alert.prev_value)}`}
autohide={false}
/>
</div>
<div className="d-flex flex-column">
<div className="align-self-center pb-1">
<SimpleTooltip
textClass="detail-hint"
text={`${alert.amount_pct}%`}
tooltipText={`Absolute difference: ${alert.amount_abs}`}
autohide={false}
/>
</div>
<div className="px-2 table-width-lg align-self-center">
<ProgressBar
magnitude={this.getCappedMagnitude(alert.amount_pct)}
regression={alert.is_regression}
color={!alert.is_regression ? 'success' : 'danger'}
/>
</div>
</div>
<div className="w-50 text-nowrap" data-testid="new-value">
<SimpleTooltip
textClass="detail-hint"
text={this.abbreviateNumber(alert.new_value)}
tooltipText={`New value: ${formatNumber(alert.new_value)}`}
autohide={false}
/>
</div>
</div>
);
}
}
Magnitude.propTypes = {
alert: PropTypes.shape({}).isRequired,
};

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

@ -9,7 +9,7 @@ export default class TableColumnHeader extends React.Component {
const { column, onChangeSort } = this.props;
const { name } = column;
return (
<div className="d-flex align-items-end">
<div className="d-flex align-items-end pl-1 flex-nowrap">
<div>{name === 'Test name' ? '' : `${name}`}</div>
<SortButton column={column} onChangeSort={onChangeSort} />
</div>