Skip to content

Commit

Permalink
feat(server): add percentage deltas in table details
Browse files Browse the repository at this point in the history
  • Loading branch information
patrickhulce committed Oct 28, 2019
1 parent a6dda6b commit 2f0fb8e
Show file tree
Hide file tree
Showing 7 changed files with 39 additions and 20 deletions.
2 changes: 1 addition & 1 deletion packages/server/src/ui/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ body {
.container {
width: 100%;
max-width: 762px;
min-width: 400px;
min-width: 300px;
margin: 0 auto;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
position: fixed;
top: var(--page-header-height);
right: 0;
left: 50%;
left: 40%;
bottom: 0;
z-index: 5;
padding-bottom: 70vh;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,51 @@

import {h} from 'preact';
import './simple-details.css';
import {getDiffLabel, getDeltaStats} from '@lhci/utils/src/audit-diff-finder.js';

/** @param {{type: LH.DetailsType, baseValue: any, compareValue: any}} props */
/** @param {{type: LH.DetailsType, baseValue: any, compareValue: any, diff?: LHCI.NumericItemAuditDiff}} props */
export const SimpleDetails = props => {
let type = props.type;
const {compareValue, baseValue} = props;
const {compareValue, baseValue, diff} = props;
const value = compareValue === undefined ? baseValue : compareValue;

if (typeof value === 'object' && value.type) {
type = value.type;
}

const label = diff ? getDiffLabel(diff) : 'neutral';

const numericBase = Number.isFinite(baseValue) ? baseValue : 0;
const numericCompare = Number.isFinite(compareValue) ? compareValue : 0;

let label = 'neutral';
if (numericCompare < numericBase) label = 'improvement';
if (numericCompare > numericBase) label = 'regression';

const baseDisplay = `Base Value: ${Math.round(numericBase).toLocaleString()}`;
const compareDisplay = `Compare Value: ${Math.round(numericCompare).toLocaleString()}`;
const title = `${baseDisplay}, ${compareDisplay}`;
const numericTitle = `${baseDisplay}, ${compareDisplay}`;
const deltaPercent =
diff && getDeltaStats(diff).percentAbsoluteDelta !== 1
? ` (${(getDeltaStats(diff).percentAbsoluteDelta * 100).toLocaleString(undefined, {
maximumFractionDigits: 0,
})}%)`
: '';

switch (type) {
case 'bytes': {
const kb = Math.abs((numericCompare - numericBase) / 1024);
return (
<pre className={`simple-details--${label}`} data-tooltip={title}>
<pre className={`simple-details--${label}`} data-tooltip={numericTitle}>
{numericCompare >= numericBase ? '+' : '-'}
{kb.toLocaleString(undefined, {maximumFractionDigits: Math.abs(kb) < 1 ? 1 : 0})} KB
{deltaPercent}
</pre>
);
}
case 'ms':
case 'timespanMs': {
const ms = Math.abs(Math.round(numericCompare - numericBase));
return (
<pre className={`simple-details--${label}`} data-tooltip={title}>
<pre className={`simple-details--${label}`} data-tooltip={numericTitle}>
{numericCompare >= numericBase ? '+' : '-'}
{ms.toLocaleString()} ms
{deltaPercent}
</pre>
);
}
Expand Down Expand Up @@ -82,6 +88,7 @@ export const SimpleDetails = props => {
<pre className={`simple-details--${label}`}>
{numericCompare >= numericBase ? '+' : '-'}
{Math.abs(numericCompare - numericBase).toLocaleString()}
{deltaPercent}
</pre>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ function isNumericValueType(itemType) {

/** @param {{pair: LHCI.AuditPair}} props */
export const TableDetails = props => {
const {audit, baseAudit, diffs} = props.pair;
const {audit, baseAudit, diffs: allDiffs} = props.pair;
if (!audit.details) return <Fragment />;
const {headings: compareHeadings, items: compareItems} = audit.details;
if (!compareHeadings || !compareItems) return <Fragment />;
Expand All @@ -37,7 +37,7 @@ export const TableDetails = props => {
const baseItems = (baseAudit && baseAudit.details && baseAudit.details.items) || [];

const zippedItems = zipBaseAndCompareItems(baseItems, compareItems);
const sortedItems = sortZippedBaseAndCompareItems(diffs, zippedItems);
const sortedItems = sortZippedBaseAndCompareItems(allDiffs, zippedItems);
const headings = compareHeadings.length ? compareHeadings : baseHeadings;
// We'll insert the row label before the first numeric heading, or last if none is found.
let insertRowLabelAfterIndex =
Expand All @@ -63,25 +63,35 @@ export const TableDetails = props => {
</tr>
</thead>
<tbody>
{sortedItems.map(({base, compare}) => {
{sortedItems.map(({base, compare, diffs}) => {
const definedItem = compare || base;
// This should never be true, but make tsc happy
if (!definedItem) return null;

const key = `${base && base.index}-${compare && compare.index}`;
const state = getRowLabelForIndex(diffs, compare && compare.index, base && base.index);
const state = getRowLabelForIndex(
allDiffs,
compare && compare.index,
base && base.index
);

return (
<tr key={key}>
{headings.map((heading, j) => {
const itemType = heading.valueType || heading.itemType || 'unknown';
const diff = diffs.find(
/** @return {diff is LHCI.NumericItemAuditDiff} */
diff => diff.type === 'itemDelta' && diff.itemKey === heading.key
);

return (
<Fragment key={j}>
<td className={`table-column--${itemType}`}>
<SimpleDetails
type={itemType}
compareValue={compare && compare.item[heading.key]}
baseValue={base && base.item[heading.key]}
diff={diff}
/>
</td>
{insertRowLabelAfterIndex === j ? (
Expand Down
2 changes: 1 addition & 1 deletion packages/server/src/ui/routes/build-view/build-view.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/

.build-view--with-audit-selection {
width: 50%;
width: 40%;
}

.build-view__scores-and-url {
Expand Down
4 changes: 3 additions & 1 deletion packages/server/src/ui/routes/build-view/build-view.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ function computeAuditGroups(lhr, baseLhr, options) {
const auditPairs = intermediateGroup.audits
.map(audit => {
const baseAudit = baseLhr && baseLhr.audits[audit.id || ''];
const diffs = baseAudit ? findAuditDiffs(baseAudit, audit, options) : [];
const diffs = baseAudit
? findAuditDiffs(baseAudit, audit, {...options, synthesizeItemKeyDiffs: true})
: [];
const maxSeverity = Math.max(...diffs.map(getDiffSeverity), 0);
return {audit, baseAudit, diffs, maxSeverity, group: intermediateGroup.group};
})
Expand Down
4 changes: 2 additions & 2 deletions types/utils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ declare global {

export interface NumericItemAuditDiff extends BaseAuditDiff, BaseNumericAuditDiff {
type: 'itemDelta';
baseItemIndex: number;
compareItemIndex: number;
baseItemIndex?: number;
compareItemIndex?: number;
itemKey: string;
}

Expand Down

0 comments on commit 2f0fb8e

Please sign in to comment.