OLD | NEW |
(Empty) | |
| 1 <!DOCTYPE html> |
| 2 <!-- |
| 3 Copyright 2017 The Chromium Authors. All rights reserved. |
| 4 Use of this source code is governed by a BSD-style license that can be |
| 5 found in the LICENSE file. |
| 6 --> |
| 7 |
| 8 <link rel="import" href="/dashboard/static/async_map.html"> |
| 9 <link rel="import" href="/dashboard/static/simple_xhr.html"> |
| 10 |
| 11 <dom-module name="chart-sparkline"> |
| 12 <template> |
| 13 <style> |
| 14 :host { |
| 15 display: inline-flex; |
| 16 flex-direction: column; |
| 17 cursor: pointer; |
| 18 border: 1px solid #ddd; |
| 19 } |
| 20 #plot { |
| 21 flex-grow: 1; |
| 22 height: 120px; |
| 23 min-width: 200px; |
| 24 } |
| 25 #legend { |
| 26 width: 340px; |
| 27 display: flex; |
| 28 justify-content: center; |
| 29 } |
| 30 #name { |
| 31 margin-left: 1em; |
| 32 } |
| 33 #vline-container { |
| 34 display: flex; |
| 35 } |
| 36 #vline { |
| 37 width: 0; |
| 38 height: 110px; |
| 39 position: relative; |
| 40 top: 8px; |
| 41 border-left: 1px solid black; |
| 42 display: none; |
| 43 } |
| 44 #loading-div { |
| 45 height: 100%; |
| 46 display: flex; |
| 47 align-items: center; |
| 48 justify-content: center; |
| 49 } |
| 50 </style> |
| 51 |
| 52 <div id="legend"> |
| 53 <div id="name">[[name]]</div> |
| 54 </div> |
| 55 <div id="vline-container"> |
| 56 <div id="vline"> </div> |
| 57 <div id="plot"> |
| 58 <div id="loading-div"> |
| 59 <!-- TODO(#3803): Use paper spinner. --> |
| 60 <img src="//www.google.com/images/loading.gif"> |
| 61 </div> |
| 62 </div> |
| 63 </div> |
| 64 </template> |
| 65 </dom-module> |
| 66 |
| 67 <script> |
| 68 'use strict'; |
| 69 (function() { |
| 70 class GraphJsonCache extends d.AsyncMap { |
| 71 async process_(graphs) { |
| 72 return await simple_xhr.asPromise('/graph_json', {graphs}); |
| 73 } |
| 74 } |
| 75 const GRAPH_JSON_CACHE = new GraphJsonCache(); |
| 76 |
| 77 Polymer({ |
| 78 is: 'chart-sparkline', |
| 79 properties: { |
| 80 graphJsonCache: { |
| 81 type: Object, |
| 82 value: () => GRAPH_JSON_CACHE, |
| 83 }, |
| 84 name: { |
| 85 type: String, |
| 86 }, |
| 87 testpaths: { |
| 88 type: Array, // of {testpath: String, color: String} |
| 89 }, |
| 90 vlinePointId: { |
| 91 type: Number, |
| 92 observer: 'onVlinePointIdSet_' |
| 93 }, |
| 94 rev: { |
| 95 type: String, |
| 96 }, |
| 97 startRev: { |
| 98 type: String, |
| 99 observer: 'updatePlot_', |
| 100 }, |
| 101 endRev: { |
| 102 type: String, |
| 103 observer: 'updatePlot_', |
| 104 }, |
| 105 chartOptions: { |
| 106 type: Object, |
| 107 value: () => { |
| 108 return { |
| 109 }; |
| 110 }, |
| 111 observer: 'updatePlot_', |
| 112 }, |
| 113 revisionMap: { |
| 114 type: Object, |
| 115 observer: 'updatePlot_', |
| 116 }, |
| 117 }, |
| 118 |
| 119 created() { |
| 120 this.plot_ = undefined; |
| 121 }, |
| 122 |
| 123 ready() { |
| 124 this.addEventListener('click', event => { |
| 125 this.fire('promoteSparkLine', { |
| 126 testpaths: this.testpaths, |
| 127 startRev: this.startRev, |
| 128 endRev: this.endRev, |
| 129 }); |
| 130 }); |
| 131 }, |
| 132 |
| 133 attached() { |
| 134 this.updatePlot_(); |
| 135 }, |
| 136 |
| 137 async updatePlot_() { |
| 138 if (!this.testpaths) return; |
| 139 if (this.style.display === 'none') return; |
| 140 |
| 141 const params = JSON.stringify({ |
| 142 test_path_list: this.testpaths.map(e => e.testpath), |
| 143 start_rev: parseInt(this.startRev), |
| 144 end_rev: parseInt(this.endRev), |
| 145 is_selected: true, |
| 146 }); |
| 147 |
| 148 let json; |
| 149 try { |
| 150 json = await this.graphJsonCache.get(params); |
| 151 } catch (e) { |
| 152 this.style.display = 'none'; |
| 153 return; |
| 154 } |
| 155 |
| 156 // Re-check style.display in case it was changed by another user gesture |
| 157 // while waiting for the XHR in graphJsonCache to return. |
| 158 if (this.style.display === 'none') return; |
| 159 |
| 160 if (!('data' in json) || Object.keys(json.data).length === 0) { |
| 161 this.style.display = 'none'; |
| 162 return; |
| 163 } |
| 164 |
| 165 const numPoints = Object.keys(this.revisionMap).length; |
| 166 this.revisionToIndexMap = {}; |
| 167 for (let i = 0; i < numPoints; ++i) { |
| 168 this.revisionToIndexMap[this.revisionMap[i][0]] = i; |
| 169 } |
| 170 |
| 171 const foundTestPaths = []; |
| 172 this.plotData_ = []; |
| 173 for (let seriesi = 0; seriesi < this.testpaths.length; ++seriesi) { |
| 174 if (!json.data[seriesi] || !json.data[seriesi].data) continue; |
| 175 const series = json.data[seriesi]; |
| 176 const plotData = { |
| 177 shadowSize: 0, |
| 178 data: [], |
| 179 }; |
| 180 |
| 181 for (const testpath of this.testpaths) { |
| 182 if (testpath.testpath === series.testpath) { |
| 183 plotData.color = testpath.color; |
| 184 foundTestPaths.push(testpath); |
| 185 } |
| 186 } |
| 187 |
| 188 this.plotData_.push(plotData); |
| 189 for (let pairi = 0; pairi < series.data.length; ++pairi) { |
| 190 const [rev, y] = series.data[pairi]; |
| 191 |
| 192 plotData.data.push([this.revisionToIndexMap[rev], y]); |
| 193 |
| 194 this.chartOptions.yaxis.max = Math.max( |
| 195 y, this.chartOptions.yaxis.max); |
| 196 this.chartOptions.yaxis.min = Math.min( |
| 197 y, this.chartOptions.yaxis.min); |
| 198 } |
| 199 } |
| 200 this.set('testpaths', foundTestPaths); |
| 201 |
| 202 if (this.plot_) { |
| 203 const rect = this.plot_.getCanvas().getBoundingClientRect(); |
| 204 if (rect.width === 0 || rect.height === 0) return; |
| 205 } |
| 206 this.plot_ = $.plot(this.$.plot, this.plotData_, this.chartOptions); |
| 207 this.onVlinePointIdSet_(); |
| 208 }, |
| 209 |
| 210 onVlinePointIdSet_() { |
| 211 this.$.vline.style.display = 'none'; |
| 212 if (!this.vlinePointId || !this.revisionToIndexMap) return; |
| 213 const i = this.revisionToIndexMap[this.vlinePointId]; |
| 214 if (i === undefined) return; |
| 215 let left = this.plot_.getData()[0].xaxis.p2c(i); |
| 216 if (left < 0) return; |
| 217 if (left > this.getBoundingClientRect().width) return; |
| 218 left += 8; |
| 219 this.$.vline.style.display = 'block'; |
| 220 this.$.vline.style.left = left + 'px'; |
| 221 }, |
| 222 }); |
| 223 })(); |
| 224 </script> |
OLD | NEW |