OLD | NEW |
| (Empty) |
1 <!-- | |
2 Copyright 2014 The Chromium Authors. All rights reserved. | |
3 Use of this source code is governed by a BSD-style license that can be | |
4 found in the LICENSE file. | |
5 --> | |
6 | |
7 <link rel="import" href="../lib/dygraph.html"> | |
8 <link rel="import" href="../lib/log.html"> | |
9 <link rel="import" href="../model/cq-graph-item.html"> | |
10 <link rel="import" href="./tom-cq-graph-item.html"> | |
11 | |
12 <polymer-element name="tom-cq-graph" attributes="graph"> | |
13 <template> | |
14 <style> | |
15 ul, .loading { | |
16 font-weight: bold; | |
17 } | |
18 tom-cq-graph-item { | |
19 font-weight: normal; | |
20 } | |
21 #graphContainer { | |
22 position: relative; | |
23 height: 200px; | |
24 } | |
25 #graphDiv { | |
26 position: absolute; | |
27 left: 0; | |
28 top: 0; | |
29 right: 0; | |
30 bottom: 0; | |
31 } | |
32 </style> | |
33 <h2>{{ graph.heading }}</h2> | |
34 <template if="{{ _hasAlerts() }}"> | |
35 Alert thresholds: {{ _alertText() }} | |
36 </template> | |
37 <div id="graphContainer"><div id="graphDiv"></div></div> | |
38 <ul> | |
39 <template if="{{ _list.length }}"> | |
40 Worst patches between {{ _listBegin }} and {{ _listEnd }}: | |
41 </template> | |
42 <template repeat="{{ item in _list }}"> | |
43 <tom-cq-graph-item item="{{ item }}"></tom-cq-graph-item> | |
44 </template> | |
45 </ul> | |
46 <template if="{{ _loading }}"><span class="loading">Loading...</span></templ
ate> | |
47 </template> | |
48 <script> | |
49 (function() { | |
50 Polymer({ | |
51 ready: function() { | |
52 this._list = []; | |
53 this._loading = true; | |
54 this._dygraph = null; | |
55 var self = this; | |
56 this.graph.data.get().then(function(data) { | |
57 self._loading = false; | |
58 self._drawGraph(data); | |
59 }).catch(log); | |
60 this.$.graphDiv.addEventListener('click', | |
61 this._onGraphClick.bind(this)); | |
62 }, | |
63 _drawGraph: function(data) { | |
64 this._dygraph = new Dygraph(this.$.graphDiv, data.rows, { | |
65 labels: data.cols, | |
66 legend: 'always', | |
67 highlightSeriesOpts: { | |
68 strokeWidth: 3, | |
69 highlightCircleSize: 4, | |
70 }, | |
71 highlightSeriesBackgroundAlpha: 1, | |
72 hideOverlayOnMouseOut: false, | |
73 ylabel: this.graph.unit, | |
74 strokeWidth: 2, | |
75 colors: ['purple', 'orange', 'lightblue', 'green', 'black'], | |
76 underlayCallback: this._onGraphDrawUnderlay.bind(this), | |
77 }); | |
78 // Overwrite default white legend background to be translucent. | |
79 var legend = this.$.graphDiv.querySelector('.dygraph-legend'); | |
80 legend.style.backgroundColor = 'rgba(255, 255, 255, 0.8)'; | |
81 }, | |
82 _onGraphClick: function() { | |
83 if (!this._dygraph || !this.graph.data.rowItemsAvailable) { | |
84 return; | |
85 } | |
86 this._list = []; | |
87 var row = this._dygraph.getSelection(); | |
88 if (row !== -1) { | |
89 this._loading = true; | |
90 var self = this; | |
91 this.graph.data.rowItems(row).then(function(rowItems) { | |
92 self._loading = false; | |
93 self._list = rowItems.items.map(function(item) { | |
94 var itemValue = item[0]; | |
95 var itemRef = item[1]; | |
96 return new CQGraphItem(itemValue, self.graph.itemUnit, | |
97 itemRef.issue, itemRef.patchset, | |
98 self.graph.itemAlertThreshold); | |
99 }); | |
100 self._listBegin = rowItems.begin; | |
101 self._listEnd = rowItems.end; | |
102 }).catch(log); | |
103 } | |
104 }, | |
105 _onGraphDrawUnderlay: function(context, area, dygraph) { | |
106 var self = this; | |
107 Object.keys(this.graph.alerts, function(col, threshold) { | |
108 self.graph.breachedItems(col, threshold).then(function(items) { | |
109 context.strokeStyle = 'red'; | |
110 context.lineWidth = 5; | |
111 context.lineCap = 'round'; | |
112 context.beginPath(); | |
113 var radius = 6; | |
114 items.forEach(function(item) { | |
115 var x = dygraph.toDomXCoord(item.timestamp); | |
116 var valueY = dygraph.toDomYCoord(item.value); | |
117 var thresholdY = Math.max( | |
118 dygraph.toDomYCoord(threshold), valueY + radius); | |
119 context.moveTo(x, thresholdY); | |
120 context.lineTo(x, valueY + radius); | |
121 context.arc(x, valueY, radius, Math.PI * 0.5, Math.PI * 2.5); | |
122 }); | |
123 context.stroke(); | |
124 }); | |
125 }); | |
126 }, | |
127 _hasAlerts: function() { | |
128 return Object.keys(this.graph.alerts).length > 0; | |
129 }, | |
130 _alertText: function() { | |
131 var items = []; | |
132 var unit = this.graph.unit; | |
133 Object.keys(this.graph.alerts, function(col, threshold) { | |
134 items.push('{1} ≥ {2} {3}'.assign(col, threshold, unit)); | |
135 }); | |
136 return items.join(', '); | |
137 }, | |
138 }); | |
139 })(); | |
140 </script> | |
141 </polymer-element> | |
OLD | NEW |