| Index: dashboard/dashboard/elements/chart-sparkline.html
|
| diff --git a/dashboard/dashboard/elements/chart-sparkline.html b/dashboard/dashboard/elements/chart-sparkline.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..85705f8ff21d66017a67fb6aab63efa71b7da239
|
| --- /dev/null
|
| +++ b/dashboard/dashboard/elements/chart-sparkline.html
|
| @@ -0,0 +1,224 @@
|
| +<!DOCTYPE html>
|
| +<!--
|
| +Copyright 2017 The Chromium Authors. All rights reserved.
|
| +Use of this source code is governed by a BSD-style license that can be
|
| +found in the LICENSE file.
|
| +-->
|
| +
|
| +<link rel="import" href="/dashboard/static/async_map.html">
|
| +<link rel="import" href="/dashboard/static/simple_xhr.html">
|
| +
|
| +<dom-module name="chart-sparkline">
|
| + <template>
|
| + <style>
|
| + :host {
|
| + display: inline-flex;
|
| + flex-direction: column;
|
| + cursor: pointer;
|
| + border: 1px solid #ddd;
|
| + }
|
| + #plot {
|
| + flex-grow: 1;
|
| + height: 120px;
|
| + min-width: 200px;
|
| + }
|
| + #legend {
|
| + width: 340px;
|
| + display: flex;
|
| + justify-content: center;
|
| + }
|
| + #name {
|
| + margin-left: 1em;
|
| + }
|
| + #vline-container {
|
| + display: flex;
|
| + }
|
| + #vline {
|
| + width: 0;
|
| + height: 110px;
|
| + position: relative;
|
| + top: 8px;
|
| + border-left: 1px solid black;
|
| + display: none;
|
| + }
|
| + #loading-div {
|
| + height: 100%;
|
| + display: flex;
|
| + align-items: center;
|
| + justify-content: center;
|
| + }
|
| + </style>
|
| +
|
| + <div id="legend">
|
| + <div id="name">[[name]]</div>
|
| + </div>
|
| + <div id="vline-container">
|
| + <div id="vline"> </div>
|
| + <div id="plot">
|
| + <div id="loading-div">
|
| + <!-- TODO(#3803): Use paper spinner. -->
|
| + <img src="//www.google.com/images/loading.gif">
|
| + </div>
|
| + </div>
|
| + </div>
|
| + </template>
|
| +</dom-module>
|
| +
|
| +<script>
|
| +'use strict';
|
| +(function() {
|
| + class GraphJsonCache extends d.AsyncMap {
|
| + async process_(graphs) {
|
| + return await simple_xhr.asPromise('/graph_json', {graphs});
|
| + }
|
| + }
|
| + const GRAPH_JSON_CACHE = new GraphJsonCache();
|
| +
|
| + Polymer({
|
| + is: 'chart-sparkline',
|
| + properties: {
|
| + graphJsonCache: {
|
| + type: Object,
|
| + value: () => GRAPH_JSON_CACHE,
|
| + },
|
| + name: {
|
| + type: String,
|
| + },
|
| + testpaths: {
|
| + type: Array, // of {testpath: String, color: String}
|
| + },
|
| + vlinePointId: {
|
| + type: Number,
|
| + observer: 'onVlinePointIdSet_'
|
| + },
|
| + rev: {
|
| + type: String,
|
| + },
|
| + startRev: {
|
| + type: String,
|
| + observer: 'updatePlot_',
|
| + },
|
| + endRev: {
|
| + type: String,
|
| + observer: 'updatePlot_',
|
| + },
|
| + chartOptions: {
|
| + type: Object,
|
| + value: () => {
|
| + return {
|
| + };
|
| + },
|
| + observer: 'updatePlot_',
|
| + },
|
| + revisionMap: {
|
| + type: Object,
|
| + observer: 'updatePlot_',
|
| + },
|
| + },
|
| +
|
| + created() {
|
| + this.plot_ = undefined;
|
| + },
|
| +
|
| + ready() {
|
| + this.addEventListener('click', event => {
|
| + this.fire('promoteSparkLine', {
|
| + testpaths: this.testpaths,
|
| + startRev: this.startRev,
|
| + endRev: this.endRev,
|
| + });
|
| + });
|
| + },
|
| +
|
| + attached() {
|
| + this.updatePlot_();
|
| + },
|
| +
|
| + async updatePlot_() {
|
| + if (!this.testpaths) return;
|
| + if (this.style.display === 'none') return;
|
| +
|
| + const params = JSON.stringify({
|
| + test_path_list: this.testpaths.map(e => e.testpath),
|
| + start_rev: parseInt(this.startRev),
|
| + end_rev: parseInt(this.endRev),
|
| + is_selected: true,
|
| + });
|
| +
|
| + let json;
|
| + try {
|
| + json = await this.graphJsonCache.get(params);
|
| + } catch (e) {
|
| + this.style.display = 'none';
|
| + return;
|
| + }
|
| +
|
| + // Re-check style.display in case it was changed by another user gesture
|
| + // while waiting for the XHR in graphJsonCache to return.
|
| + if (this.style.display === 'none') return;
|
| +
|
| + if (!('data' in json) || Object.keys(json.data).length === 0) {
|
| + this.style.display = 'none';
|
| + return;
|
| + }
|
| +
|
| + const numPoints = Object.keys(this.revisionMap).length;
|
| + this.revisionToIndexMap = {};
|
| + for (let i = 0; i < numPoints; ++i) {
|
| + this.revisionToIndexMap[this.revisionMap[i][0]] = i;
|
| + }
|
| +
|
| + const foundTestPaths = [];
|
| + this.plotData_ = [];
|
| + for (let seriesi = 0; seriesi < this.testpaths.length; ++seriesi) {
|
| + if (!json.data[seriesi] || !json.data[seriesi].data) continue;
|
| + const series = json.data[seriesi];
|
| + const plotData = {
|
| + shadowSize: 0,
|
| + data: [],
|
| + };
|
| +
|
| + for (const testpath of this.testpaths) {
|
| + if (testpath.testpath === series.testpath) {
|
| + plotData.color = testpath.color;
|
| + foundTestPaths.push(testpath);
|
| + }
|
| + }
|
| +
|
| + this.plotData_.push(plotData);
|
| + for (let pairi = 0; pairi < series.data.length; ++pairi) {
|
| + const [rev, y] = series.data[pairi];
|
| +
|
| + plotData.data.push([this.revisionToIndexMap[rev], y]);
|
| +
|
| + this.chartOptions.yaxis.max = Math.max(
|
| + y, this.chartOptions.yaxis.max);
|
| + this.chartOptions.yaxis.min = Math.min(
|
| + y, this.chartOptions.yaxis.min);
|
| + }
|
| + }
|
| + this.set('testpaths', foundTestPaths);
|
| +
|
| + if (this.plot_) {
|
| + const rect = this.plot_.getCanvas().getBoundingClientRect();
|
| + if (rect.width === 0 || rect.height === 0) return;
|
| + }
|
| + this.plot_ = $.plot(this.$.plot, this.plotData_, this.chartOptions);
|
| + this.onVlinePointIdSet_();
|
| + },
|
| +
|
| + onVlinePointIdSet_() {
|
| + this.$.vline.style.display = 'none';
|
| + if (!this.vlinePointId || !this.revisionToIndexMap) return;
|
| + const i = this.revisionToIndexMap[this.vlinePointId];
|
| + if (i === undefined) return;
|
| + let left = this.plot_.getData()[0].xaxis.p2c(i);
|
| + if (left < 0) return;
|
| + if (left > this.getBoundingClientRect().width) return;
|
| + left += 8;
|
| + this.$.vline.style.display = 'block';
|
| + this.$.vline.style.left = left + 'px';
|
| + },
|
| + });
|
| +})();
|
| +</script>
|
|
|