Modified: trunk/Websites/perf.webkit.org/public/v3/components/freshness-indicator.js (242932 => 242933)
--- trunk/Websites/perf.webkit.org/public/v3/components/freshness-indicator.js 2019-03-14 02:46:16 UTC (rev 242932)
+++ trunk/Websites/perf.webkit.org/public/v3/components/freshness-indicator.js 2019-03-14 03:07:40 UTC (rev 242933)
@@ -3,30 +3,37 @@
{
super('freshness-indicator');
this._lastDataPointDuration = lastDataPointDuration;
- this._summary = summary;
this._testAgeTolerance = testAgeTolerance;
this._url = url;
+ this._highlighted = false;
this._renderIndicatorLazily = new LazilyEvaluatedFunction(this._renderIndicator.bind(this));
}
- update(lastDataPointDuration, testAgeTolerance, summary, url)
+ update(lastDataPointDuration, testAgeTolerance, url, highlighted)
{
this._lastDataPointDuration = lastDataPointDuration;
- this._summary = summary;
this._testAgeTolerance = testAgeTolerance;
this._url = url;
+ this._highlighted = highlighted;
this.enqueueToRender();
}
+ didConstructShadowTree()
+ {
+ const container = this.content('container');
+ container.addEventListener('mouseenter', () => this.dispatchAction('select', this));
+ container.addEventListener('mouseleave', () => this.dispatchAction('unselect'));
+ }
+
render()
{
super.render();
- this._renderIndicatorLazily.evaluate(this._lastDataPointDuration, this._testAgeTolerance, this._summary, this._url);
+ this._renderIndicatorLazily.evaluate(this._lastDataPointDuration, this._testAgeTolerance, this._url, this._highlighted);
}
- _renderIndicator(lastDataPointDuration, testAgeTolerance, summary, url)
+ _renderIndicator(lastDataPointDuration, testAgeTolerance, url, highlighted)
{
const element = ComponentBase.createElement;
if (!lastDataPointDuration) {
@@ -39,7 +46,7 @@
const rating = 1 / (1 + Math.exp(Math.log(1.2) * (hoursSinceLastDataPoint - testAgeToleranceInHours)));
const hue = Math.round(120 * rating);
const brightness = Math.round(30 + 50 * rating);
- const indicator = element('a', {id: 'cell', title: summary, href: url});
+ const indicator = element('a', {id: 'cell', href: url, class: highlighted ? 'highlight' : ''});
indicator.style.backgroundColor = `hsl(${hue}, 100%, ${brightness}%)`;
this.renderReplace(this.content('container'), indicator);
@@ -54,23 +61,26 @@
{
return `
div {
+ margin-left: 0;
height: 1.8rem;
width: 1.8rem;
- padding-top: 0.1rem;
}
a {
display: block;
height:1.6rem;
width:1.6rem;
- margin: 0.1rem;
+ border: 0.1rem;
+ border-color: white;
+ border-style: solid;
padding: 0;
}
- a:hover {
- height: 1.8rem;
- width: 1.8rem;
- margin: 0rem;
- padding: 0;
+ a.highlight {
+ height: 1.4rem;
+ width: 1.4rem;
+ border: 0.2rem;
+ border-style: solid;
+ border-color: #0099ff;
}`;
}
}
Modified: trunk/Websites/perf.webkit.org/public/v3/pages/test-freshness-page.js (242932 => 242933)
--- trunk/Websites/perf.webkit.org/public/v3/pages/test-freshness-page.js 2019-03-14 02:46:16 UTC (rev 242932)
+++ trunk/Websites/perf.webkit.org/public/v3/pages/test-freshness-page.js 2019-03-14 03:07:40 UTC (rev 242933)
@@ -9,10 +9,27 @@
this._lastDataPointByConfiguration = null;
this._indicatorByConfiguration = null;
this._renderTableLazily = new LazilyEvaluatedFunction(this._renderTable.bind(this));
+ this._currentlyHighlightedIndicator = null;
+ this._hoveringTooltip = false;
+ this._builderByIndicator = null;
+ this._renderTooltipLazily = new LazilyEvaluatedFunction(this._renderTooltip.bind(this));
this._loadConfig(summaryPageConfiguration);
}
+ didConstructShadowTree()
+ {
+ const tooltipContainer = this.content('tooltip-container');
+ tooltipContainer.addEventListener('mouseenter', () => {
+ this._hoveringTooltip = true;
+ this.enqueueToRender();
+ });
+ tooltipContainer.addEventListener('mouseleave', () => {
+ this._hoveringTooltip = false;
+ this.enqueueToRender();
+ });
+ }
+
name() { return 'Test-Freshness'; }
_loadConfig(summaryPageConfiguration)
@@ -55,6 +72,7 @@
{
this._measurementSetFetchTime = Date.now();
this._lastDataPointByConfiguration = new Map;
+ this._builderByIndicator = new Map;
const startTime = this._measurementSetFetchTime - this._timeDuration;
@@ -71,10 +89,17 @@
const currentTimeSeries = measurementSet.fetchedTimeSeries('current', false, false);
let timeForLastDataPoint = startTime;
- if (currentTimeSeries.lastPoint())
- timeForLastDataPoint = currentTimeSeries.lastPoint().build().buildTime();
+ let lastBuildLink = null;
+ let builder = null;
+ const lastPoint = currentTimeSeries.lastPoint();
+ if (lastPoint) {
+ timeForLastDataPoint = lastPoint.build().buildTime();
+ lastBuildLink = lastPoint.build().url();
+ builder = lastPoint.build().builder();
+ }
- lastDataPointByMetric.set(metric, {time: timeForLastDataPoint, hasCurrentDataPoint: !!currentTimeSeries.lastPoint()});
+ lastDataPointByMetric.set(metric, {time: timeForLastDataPoint, hasCurrentDataPoint: !!currentTimeSeries.lastPoint(),
+ lastBuildLink, builder});
this.enqueueToRender();
});
}
@@ -87,22 +112,53 @@
this._renderTableLazily.evaluate(this._platforms, this._metrics);
+ let buildSummaryForCurrentlyHighlightedIndicator = null;
+ let buildLinkForCurrentlyHighlightedIndicator = null;
+ const builderForCurrentlyHighlightedIndicator = this._currentlyHighlightedIndicator ? this._builderByIndicator.get(this._currentlyHighlightedIndicator) : null;
for (const [platform, lastDataPointByMetric] of this._lastDataPointByConfiguration.entries()) {
for (const [metric, lastDataPoint] of lastDataPointByMetric.entries()) {
const timeDuration = this._measurementSetFetchTime - lastDataPoint.time;
const timeDurationSummaryPrefix = lastDataPoint.hasCurrentDataPoint ? '' : 'More than ';
const timeDurationSummary = BuildRequest.formatTimeInterval(timeDuration);
- const testLabel = `"${metric.test().fullName()}" for "${platform.name()}"`;
- const summary = `${timeDurationSummaryPrefix}${timeDurationSummary} since last data point on ${testLabel}`;
+ const summary = `${timeDurationSummaryPrefix}${timeDurationSummary} since latest data point.`;
const url = "" ChartsPage.createStateForDashboardItem(platform.id(), metric.id(),
this._measurementSetFetchTime - this._timeDuration));
const indicator = this._indicatorByConfiguration.get(platform).get(metric);
- indicator.update(timeDuration, this._testAgeTolerance, summary, url);
+ if (this._currentlyHighlightedIndicator && this._currentlyHighlightedIndicator === indicator) {
+ buildSummaryForCurrentlyHighlightedIndicator = summary;
+ buildLinkForCurrentlyHighlightedIndicator = lastDataPoint.lastBuildLink;
+ }
+ this._builderByIndicator.set(indicator, lastDataPoint.builder);
+ indicator.update(timeDuration, this._testAgeTolerance, url, builderForCurrentlyHighlightedIndicator && builderForCurrentlyHighlightedIndicator === lastDataPoint.builder);
}
}
+ this._renderTooltipLazily.evaluate(this._currentlyHighlightedIndicator, this._hoveringTooltip, buildSummaryForCurrentlyHighlightedIndicator, buildLinkForCurrentlyHighlightedIndicator);
}
+ _renderTooltip(indicator, hoveringTooltip, buildSummary, buildLink)
+ {
+ if (!indicator || !buildSummary) {
+ this.content('tooltip-container').style.display = hoveringTooltip ? null : 'none';
+ return;
+ }
+ const element = ComponentBase.createElement;
+
+ const rect = indicator.element().getBoundingClientRect();
+ const tooltipContainer = this.content('tooltip-container');
+ tooltipContainer.style.display = null;
+
+ const tooltipContainerComputedStyle = getComputedStyle(tooltipContainer);
+ const containerMarginTop = parseFloat(tooltipContainerComputedStyle.paddingTop);
+ const containerMarginLeft = parseFloat(tooltipContainerComputedStyle.marginLeft);
+
+ tooltipContainer.style.position = 'absolute';
+ tooltipContainer.style.top = rect.top - (tooltipContainer.offsetHeight + containerMarginTop) + 'px';
+ tooltipContainer.style.left = rect.left + rect.width / 2 - tooltipContainer.offsetWidth / 2 + containerMarginLeft + 'px';
+
+ this.renderReplace(tooltipContainer, [element('p', buildSummary), buildLink ? element('a', {href: buildLink}, 'Latest Build') : []]);
+ }
+
_renderTable(platforms, metrics)
{
const element = ComponentBase.createElement;
@@ -138,6 +194,14 @@
return element('td', {class: 'blank-cell'}, element('div'));
const indicator = new FreshnessIndicator;
+ indicator.listenToAction('select', (originator) => {
+ this._currentlyHighlightedIndicator = originator;
+ this.enqueueToRender();
+ });
+ indicator.listenToAction('unselect', () => {
+ this._currentlyHighlightedIndicator = null;
+ this.enqueueToRender();
+ });
indicatorByMetric.set(metric, indicator);
return element('td', {class: 'status-cell'}, indicator);
}
@@ -144,7 +208,7 @@
static htmlTemplate()
{
- return `<section class="page-with-heading"><table id="test-health"></table></section>`;
+ return `<section class="page-with-heading"><div id="tooltip-container"></div><table id="test-health"></table></section>`;
}
static cssTemplate()
@@ -186,7 +250,7 @@
#test-health tbody {
display: block;
overflow: auto;
- height: 75vh;
+ height: calc(100vh - 24rem);
}
#test-health td.status-cell {
margin: 0;
@@ -214,27 +278,56 @@
overflow: hidden;
}
#test-health td.blank-cell > div::before {
- content: "";
- position: absolute;
- top: -1px;
- left: -1px;
- display: block;
- width: 0px;
- height: 0px;
- border-right: calc(1.6rem + 1px) solid #ddd;
- border-top: calc(1.6rem + 1px) solid transparent;
+ content: "";
+ position: absolute;
+ top: -1px;
+ left: -1px;
+ display: block;
+ width: 0px;
+ height: 0px;
+ border-right: calc(1.6rem + 1px) solid #ddd;
+ border-top: calc(1.6rem + 1px) solid transparent;
}
#test-health td.blank-cell > div::after {
- content: "";
- display: block;
- position: absolute;
- top: 1px;
- left: 1px;
- width: 0px;
- height: 0px;
- border-right: calc(1.6rem - 1px) solid #F9F9F9;
- border-top: calc(1.6rem - 1px) solid transparent;
+ content: "";
+ display: block;
+ position: absolute;
+ top: 1px;
+ left: 1px;
+ width: 0px;
+ height: 0px;
+ border-right: calc(1.6rem - 1px) solid #F9F9F9;
+ border-top: calc(1.6rem - 1px) solid transparent;
}
+ #tooltip-container {
+ width: 22rem;
+ height: 2rem;
+ background-color: #34495E;
+ opacity: 0.9;
+ margin: 0.3rem;
+ padding: 0.3rem;
+ border-radius: 0.4rem;
+ z-index: 1;
+ text-align: center;
+ }
+ #tooltip-container::after {
+ content: " ";
+ position: absolute;
+ top: 100%;
+ left: 50%;
+ margin-left: -1rem;
+ border-width: 0.2rem;
+ border-style: solid;
+ border-color: #34495E transparent transparent transparent;
+ }
+ #tooltip-container p {
+ color: white;
+ margin: 0;
+ }
+ #tooltip-container a {
+ color: #B03A2E;
+ font-weight: bold;
+ }
`;
}