OLD | NEW |
---|---|
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 <!-- | 2 <!-- |
3 Copyright 2016 The Chromium Authors. All rights reserved. | 3 Copyright 2016 The Chromium Authors. All rights reserved. |
4 Use of this source code is governed by a BSD-style license that can be | 4 Use of this source code is governed by a BSD-style license that can be |
5 found in the LICENSE file. | 5 found in the LICENSE file. |
6 --> | 6 --> |
7 | 7 |
8 <link rel="import" href="/components/paper-button/paper-button.html"> | 8 <link rel="import" href="/components/paper-button/paper-button.html"> |
9 | 9 |
10 <link rel="import" href="/dashboard/elements/bisect-status.html"> | 10 <link rel="import" href="/dashboard/elements/bisect-status.html"> |
11 <link rel="import" href="/dashboard/elements/bug-info-span.html"> | 11 <link rel="import" href="/dashboard/elements/bug-info-span.html"> |
12 <link rel="import" href="/dashboard/elements/revision-range.html"> | 12 <link rel="import" href="/dashboard/elements/revision-range.html"> |
13 <link rel="import" href="/dashboard/elements/triage-dialog.html"> | 13 <link rel="import" href="/dashboard/elements/triage-dialog.html"> |
14 <link rel="import" href="/dashboard/static/uri.html"> | 14 <link rel="import" href="/dashboard/static/uri.html"> |
15 | 15 |
16 <polymer-element name="alerts-table" | 16 <dom-module id="alerts-table"> |
17 attributes="sortBy sortDirection | |
18 xsrfToken alertList extraColumns"> | |
19 <template> | 17 <template> |
20 <style> | 18 <style> |
21 #alerts { | 19 #alerts { |
22 border-collapse: collapse; | 20 border-collapse: collapse; |
23 border-spacing: 0; | 21 border-spacing: 0; |
24 font-size: small; | 22 font-size: small; |
25 table-layout: fixed; | 23 table-layout: fixed; |
26 width: 100%; | 24 width: 100%; |
27 } | 25 } |
28 | 26 |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
257 } | 255 } |
258 | 256 |
259 /* Triage dialog at the top level when the user clicks the triage button. */ | 257 /* Triage dialog at the top level when the user clicks the triage button. */ |
260 triage-dialog { | 258 triage-dialog { |
261 position: absolute; | 259 position: absolute; |
262 margin-top: 30px; | 260 margin-top: 30px; |
263 z-index: 1000; | 261 z-index: 1000; |
264 } | 262 } |
265 </style> | 263 </style> |
266 <div> | 264 <div> |
267 <triage-dialog id="triage" on-triaged="{{onTriaged}}" xsrfToken="{{xsrfTok en}}"> | 265 <triage-dialog id="triage" on-triaged="onTriaged" xsrfToken="{{xsrfToken}} "> |
268 </triage-dialog> | 266 </triage-dialog> |
269 <paper-button raised id="file-bug-button" on-click="{{showTriageDialog}}"> | 267 <paper-button raised id="file-bug-button" on-click="showTriageDialog"> |
270 Triage | 268 Triage |
271 </paper-button> | 269 </paper-button> |
272 <paper-button raised id="graph-button" on-click="{{showGraphs}}"> | 270 <paper-button raised id="graph-button" on-click="showGraphs"> |
273 Graph | 271 Graph |
274 </paper-button> | 272 </paper-button> |
275 </div> | 273 </div> |
276 <table id="alerts"> | 274 <table id="alerts"> |
277 <thead> | 275 <thead> |
278 <tr> | 276 <tr> |
279 <th id="groupheader"></th> | 277 <th id="groupheader"></th> |
280 <th id="checkheader"> | 278 <th id="checkheader"> |
281 <input type="checkbox" id="header-checkbox" on-change="{{onHeaderCheck boxChange}}"> | 279 <input type="checkbox" id="header-checkbox" on-change="onHeaderCheckbo xChange"> |
282 </th> | 280 </th> |
283 <th id="graphheader"></th> | 281 <th id="graphheader"></th> |
284 <th id="bug_id" on-click="{{columnHeaderClicked}}">Bug ID</th> | 282 <th id="bug_id" on-click="columnHeaderClicked">Bug ID</th> |
285 <th id="end_revision" on-click="{{columnHeaderClicked}}">Revisions</th> | 283 <th id="end_revision" on-click="columnHeaderClicked">Revisions</th> |
286 <th id="master" on-click="{{columnHeaderClicked}}">Master</th> | 284 <th id="master" on-click="columnHeaderClicked">Master</th> |
287 <th id="bot" on-click="{{columnHeaderClicked}}">Bot</th> | 285 <th id="bot" on-click="columnHeaderClicked">Bot</th> |
288 <th id="testsuite" on-click="{{columnHeaderClicked}}">Test Suite</th> | 286 <th id="testsuite" on-click="columnHeaderClicked">Test Suite</th> |
289 <th id="test" on-click="{{columnHeaderClicked}}">Test</th> | 287 <th id="test" on-click="columnHeaderClicked">Test</th> |
290 <template repeat="{{extraColumns}}"> | 288 <template is="dom-repeat" items="{{extraColumns}}"> |
291 <th id="{{key}}" on-click="{{columnHeaderClicked}}">{{label}}</th> | 289 <th id="{{item.key}}" on-click="columnHeaderClicked">{{item.label}}</t h> |
292 </template> | 290 </template> |
293 </tr> | 291 </tr> |
294 </thead> | 292 </thead> |
295 <tbody> | 293 <tbody> |
296 <template repeat="{{alertList}}"> | 294 <template is="dom-repeat" items="{{alertList}}"> |
297 <tr class="{{rowType}}" | 295 <tr class$="{{item.rowType}}" |
298 improvement?={{improvement}} | 296 improvement$="{{item.improvement}}" |
299 triaged?={{triaged}} | 297 triaged$="{{item.triaged}}" |
300 hidden?={{hideRow}} | 298 hidden$="{{item.hideRow}}" |
301 highlighted?={{highlighted}} | 299 highlighted$="{{item.highlighted}}" |
302 expanded?={{expanded}} | 300 expanded$="{{item.expanded}}" |
303 on-click="{{onRowClicked}}"> | 301 on-click="onRowClicked"> |
304 | 302 |
305 <td> | 303 <td> |
306 <a class="kd-button counter" | 304 <a class="kd-button counter" |
307 expanded?={{expanded}} | 305 expanded$="{{expanded}}" |
308 on-click="{{onExpandGroupButtonClicked}}" | 306 on-click="onExpandGroupButtonClicked" |
309 hidden?="{{!(size > 1)}}">{{size}}</a> | 307 hidden$="{{!computeIsPlural(size))}}">{{size}}</a> |
310 </td> | 308 </td> |
311 <td> | 309 <td> |
312 <input type="checkbox" | 310 <input type="checkbox" |
313 id="{{key}}" | 311 id="{{key}}" |
314 checked="{{selected}}" | 312 checked="{{selected}}" |
315 on-change="{{onCheckboxChange}}"> | 313 on-change="onCheckboxChange"> |
316 </td> | 314 </td> |
317 | 315 |
318 <td> | 316 <td> |
319 <a href="{{dashboard_link}}" class="graph-link" target="_blank"> | 317 <a href$="{{dashboard_link}}" class="graph-link" target="_blank"> |
320 📈 <!-- chart with upwards trend character U+1F4C8 --> | 318 📈 <!-- chart with upwards trend character U+1F4C8 --> |
321 </a> | 319 </a> |
322 </td> | 320 </td> |
323 | 321 |
324 <td hidden?="{{hide_bug_id}}"> | 322 <td hidden$="{{hide_bug_id}}"> |
325 <bug-info-span bugId="{{bug_id}}" | 323 <bug-info-span bugId="{{bug_id}}" |
326 key="{{key}}" | 324 key="{{key}}" |
327 recovered?="{{recovered}}" | 325 recovered?="{{recovered}}" |
328 xsrfToken="{{xsrfToken}}" | 326 xsrfToken="{{xsrfToken}}" |
329 on-untriaged="{{onUntriaged}}"> | 327 on-untriaged="onUntriaged"> |
330 </bug-info-span> | 328 </bug-info-span> |
331 <bisect-status hidden?="{{!(bug_id > 0)}}" | 329 <bisect-status hidden$="{{!computeTruthy(bug_id)}}" |
dtu
2016/04/27 17:43:54
! autocasts to bool, don't need computeTruthy
eakuefner
2016/04/28 15:54:54
Done.
| |
332 status="{{bisect_status}}"> | 330 status="{{bisect_status}}"> |
333 </bisect-status> | 331 </bisect-status> |
334 </td> | 332 </td> |
335 <td class="revision_range"> | 333 <td class="revision_range"> |
336 <revision-range start={{start_revision}} end="{{end_revision}}"></re vision-range> | 334 <revision-range start={{start_revision}} end="{{end_revision}}"></re vision-range> |
337 </td> | 335 </td> |
338 <td class="master"><label>{{master}}</label><label hidden?="{{(!additi onColumnValues.master || expanded)}}">...</label></td> | 336 <td class="master"><label>{{master}}</label><label hidden$="{{computeA bsentOrExpanded(additionColumnValues.master, expanded)}}">...</label></td> |
339 <td class="bot"><label>{{bot}}</label><label hidden?="{{(!additionColu mnValues.bot || expanded)}}">...</label></td> | 337 <td class="bot"><label>{{bot}}</label><label hidden$="{{computeAbsentO rExpanded(additionColumnValues.bot, expanded)}}">...</label></td> |
340 <td class="testsuite"><label>{{testsuite}}</label><label hidden?="{{(! additionColumnValues.testsuite || expanded)}}">...</label></td> | 338 <td class="testsuite"><label>{{testsuite}}</label><label hidden$="{{co mputeAbsentOrExpanded(additionColumnValues.testsuite, expanded)}}">...</label></ td> |
341 <td class="test"><label>{{test}}</label><label hidden?="{{(!additionCo lumnValues.test || expanded)}}">...</label></td> | 339 <td class="test"><label>{{test}}</label><label hidden$="{{computeAbsen tOrExpanded(additionColumnValues.test, expanded)}}">...</label></td> |
342 | 340 |
343 <template repeat="{{extraColumns}}"> | 341 <template is="dom-repeat" items="{{extraColumns}}"> |
344 <td class="{{key}}"><label>{{value}}</td> | 342 <td class="{{item.key}}"><label>{{item.value}}</td> |
345 </template> | 343 </template> |
346 </tr> | 344 </tr> |
347 </template> | 345 </template> |
348 </tbody> | 346 </tbody> |
349 </table> | 347 </table> |
350 </template> | 348 </template> |
351 <script> | 349 <script> |
352 'use strict'; | 350 'use strict'; |
353 | 351 |
354 (function() { | 352 (function() { |
355 | 353 |
356 /** | 354 /** |
357 * Constructs a URI for the report page for this group of alerts. | 355 * Constructs a URI for the report page for this group of alerts. |
358 * @param {Array.<Object>} group The group of alerts to graph. | 356 * @param {Array.<Object>} group The group of alerts to graph. |
359 * @return {string} The URI of the graph. | 357 * @return {string} The URI of the graph. |
360 */ | 358 */ |
361 function getGraphUri(alerts) { | 359 function getGraphUri(alerts) { |
362 var keys = []; | 360 var keys = []; |
363 for (var i = 0; i < alerts.length; i++) { | 361 for (var i = 0; i < alerts.length; i++) { |
364 keys.push(alerts[i]['key']); | 362 keys.push(alerts[i]['key']); |
365 } | 363 } |
366 return '/group_report?keys=' + keys.join(','); | 364 return '/group_report?keys=' + keys.join(','); |
367 } | 365 } |
368 | 366 |
369 Polymer('alerts-table', { | 367 Polymer('alerts-table', { |
dtu
2016/04/27 17:34:25
Don't need 'alerts-table' here.
eakuefner
2016/04/28 15:54:54
Done.
| |
370 | 368 |
371 /** | 369 is: 'alerts-table', |
372 * The field to sort by. Note that this will be both the id of a th | 370 properties: { |
373 * element in the table, and a property of an item in the alert list. | 371 /** |
374 */ | 372 * The field to sort by. Note that this will be both the id of a th |
375 sortBy: 'end_revision', | 373 * element in the table, and a property of an item in the alert list. |
374 */ | |
375 sortBy: { | |
376 type: String, | |
377 value: 'end_revision', | |
378 notify: true, | |
379 observer: 'sortByChanged' | |
380 }, | |
376 | 381 |
377 /** | 382 /** |
378 * Sort direction, either 'down' (increasing) or 'up' (decreasing). | 383 * Sort direction, either 'down' (increasing) or 'up' (decreasing). |
379 */ | 384 */ |
380 sortDirection: 'down', | 385 sortDirection: { |
386 type: String, | |
387 value: 'down', | |
388 notify: true, | |
389 observer: 'sortDirectionChanged' | |
390 }, | |
381 | 391 |
382 /** | 392 /** |
383 * Previous id of checkbox input element that was checked. | 393 * Previous id of checkbox input element that was checked. |
384 */ | 394 */ |
385 previousCheckboxId: null, | 395 previousCheckboxId: { value: null }, |
386 | 396 |
387 /** | 397 /** |
388 * Current id of checkbox input element that was checked. | 398 * Current id of checkbox input element that was checked. |
389 */ | 399 */ |
390 currentCheckboxId: null, | 400 currentCheckboxId: { value: null}, |
dtu
2016/04/27 17:34:24
nit: space.
eakuefner
2016/04/28 15:54:54
Done.
| |
391 | 401 |
392 NUM_ALERTS_TO_CHECK_ON_INIT: 10, | 402 NUM_ALERTS_TO_CHECK_ON_INIT: { |
403 type: Number, | |
404 value: 10 | |
405 } | |
406 }, | |
393 | 407 |
394 /** | 408 /** |
395 * Custom element lifecycle callback, called once this element is ready. | 409 * Custom element lifecycle callback, called once this element is ready. |
396 */ | 410 */ |
397 ready: function() { | 411 ready: function() { |
398 this.checkedAlerts = []; | 412 this.checkedAlerts = []; |
399 }, | 413 }, |
400 | 414 |
415 computeExistsOrExpanded: (prop, exanded) => !prop || expanded, | |
dtu
2016/04/27 17:43:54
computeAbsentOrExpanded
eakuefner
2016/04/28 15:54:54
Done.
| |
416 | |
417 computeIsPlural: n => n > 1, | |
418 | |
419 computeTruthy: x => Boolean(x), | |
420 | |
401 isRecursiveChange: function() { | 421 isRecursiveChange: function() { |
402 if (this.isRecursingIntoChange) { | 422 if (this.isRecursingIntoChange) { |
403 return true; | 423 return true; |
404 } | 424 } |
405 this.isRecursingIntoChange = true; | 425 this.isRecursingIntoChange = true; |
406 setTimeout(function() { | 426 setTimeout(function() { |
407 this.isRecursingIntoChange = false; | 427 this.isRecursingIntoChange = false; |
408 }.bind(this), 10); | 428 }.bind(this), 10); |
409 return false; | 429 return false; |
410 }, | 430 }, |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
524 i++; | 544 i++; |
525 } | 545 } |
526 } | 546 } |
527 } | 547 } |
528 }, | 548 }, |
529 | 549 |
530 /** | 550 /** |
531 * Toggles expansion of a group of alerts. | 551 * Toggles expansion of a group of alerts. |
532 */ | 552 */ |
533 onExpandGroupButtonClicked: function(event, detail, sender) { | 553 onExpandGroupButtonClicked: function(event, detail, sender) { |
534 var row = sender.parentNode.parentNode; | 554 var row = Polymer.dom(Polymer.dom(sender).parentNode).parentNode; |
535 var alertIndex = row.rowIndex - 1; | 555 var alertIndex = row.rowIndex - 1; |
536 var alert = this.alertList[alertIndex]; | 556 var alert = this.alertList[alertIndex]; |
537 var isExpand = !alert.expanded; | 557 var isExpand = !alert.expanded; |
538 alert.expanded = isExpand; | 558 alert.expanded = isExpand; |
539 for (var i = alertIndex + 1; i < this.alertList.length; i++) { | 559 for (var i = alertIndex + 1; i < this.alertList.length; i++) { |
540 if (this.alertList[i].group == alert.group) { | 560 if (this.alertList[i].group == alert.group) { |
541 this.alertList[i].hideRow = !isExpand; | 561 this.alertList[i].hideRow = !isExpand; |
542 } else { | 562 } else { |
543 break; | 563 break; |
544 } | 564 } |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
672 * Callback for the click event for a column header. | 692 * Callback for the click event for a column header. |
673 * @param {Event} event Clicked event. | 693 * @param {Event} event Clicked event. |
674 * @param {Object} detail Detail Object. | 694 * @param {Object} detail Detail Object. |
675 * @param {Element} sender Element that invoked the event. | 695 * @param {Element} sender Element that invoked the event. |
676 */ | 696 */ |
677 columnHeaderClicked: function(event, detail, sender) { | 697 columnHeaderClicked: function(event, detail, sender) { |
678 this.sortBy = sender.id; | 698 this.sortBy = sender.id; |
679 var newDirection = 'down'; | 699 var newDirection = 'down'; |
680 // Because the <th> element may have been added based on an entry in | 700 // Because the <th> element may have been added based on an entry in |
681 // this.extraColumns, this.$[this.sortBy] may not work. | 701 // this.extraColumns, this.$[this.sortBy] may not work. |
682 var th = this.$.alerts.querySelector('#' + this.sortBy); | 702 var th = Polymer.dom(this.$.alerts).querySelector('#' + this.sortBy); |
683 if (th.getAttribute('data-sort-direction') == 'down') { | 703 if (th.getAttribute('data-sort-direction') == 'down') { |
684 newDirection = 'up'; | 704 newDirection = 'up'; |
685 } | 705 } |
686 this.sortDirection = newDirection; | 706 this.sortDirection = newDirection; |
687 }, | 707 }, |
688 | 708 |
689 /** | 709 /** |
690 * Update the table headers to indicate the current table sorting. | 710 * Update the table headers to indicate the current table sorting. |
691 */ | 711 */ |
692 updateHeaders: function() { | 712 updateHeaders: function() { |
693 var headers = this.$.alerts.querySelectorAll('th'); | 713 var headers = Polymer.dom(this.$.alerts).querySelectorAll('th'); |
694 for (var i = 0; i < headers.length; i++) { | 714 for (var i = 0; i < headers.length; i++) { |
695 if (headers[i].id == this.sortBy) { | 715 if (headers[i].id == this.sortBy) { |
696 headers[i].setAttribute('data-sort-direction', this.sortDirection); | 716 Polymer.dom(headers[i]).setAttribute('data-sort-direction', |
717 this.sortDirection); | |
697 } else { | 718 } else { |
698 headers[i].removeAttribute('data-sort-direction'); | 719 Polymer.dom(headers[i]).removeAttribute('data-sort-direction'); |
699 } | 720 } |
700 } | 721 } |
701 }, | 722 }, |
702 | 723 |
703 /** | 724 /** |
704 * Sorts the alert list according to the current values of the properties | 725 * Sorts the alert list according to the current values of the properties |
705 * sortDirection and sortBy. | 726 * sortDirection and sortBy. |
706 */ | 727 */ |
707 sort: function() { | 728 sort: function() { |
708 var order = this.sortDirection == 'down' ? 1 : -1; | 729 var order = this.sortDirection == 'down' ? 1 : -1; |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
908 } | 929 } |
909 }, | 930 }, |
910 | 931 |
911 /** | 932 /** |
912 * Event handler for the change event of any of the checkboxes for any | 933 * Event handler for the change event of any of the checkboxes for any |
913 * alert in the table. | 934 * alert in the table. |
914 */ | 935 */ |
915 onCheckboxChange: function(event, detail, sender) { | 936 onCheckboxChange: function(event, detail, sender) { |
916 if (sender) { | 937 if (sender) { |
917 // Checks group member rows. | 938 // Checks group member rows. |
918 var alertIndex = sender.parentNode.parentNode.rowIndex - 1; | 939 var alertIndex = Polymer.dom( |
940 Polymer.dom(sender).parentNode).parentNode.rowIndex - 1; | |
919 var alert = this.alertList[alertIndex]; | 941 var alert = this.alertList[alertIndex]; |
920 this.updateGroupCheckboxes(alert, alertIndex, alert.selected); | 942 this.updateGroupCheckboxes(alert, alertIndex, alert.selected); |
921 | 943 |
922 this.previousCheckboxId = this.currentCheckboxId; | 944 this.previousCheckboxId = this.currentCheckboxId; |
923 this.currentCheckboxId = sender.id; | 945 this.currentCheckboxId = sender.id; |
924 } | 946 } |
925 // Update the list of checked alerts. | 947 // Update the list of checked alerts. |
926 this.checkedAlerts = this.alertList.filter(function(alertRow) { | 948 this.checkedAlerts = this.alertList.filter(function(alertRow) { |
927 return alertRow.selected; | 949 return alertRow.selected; |
928 }); | 950 }); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
989 alert.selected = false; | 1011 alert.selected = false; |
990 } | 1012 } |
991 } | 1013 } |
992 }); | 1014 }); |
993 this.onCheckboxChange(); | 1015 this.onCheckboxChange(); |
994 this.updateBugColumn(); | 1016 this.updateBugColumn(); |
995 } | 1017 } |
996 }); | 1018 }); |
997 })(); | 1019 })(); |
998 </script> | 1020 </script> |
999 </polymer-element> | 1021 </dom-module> |
OLD | NEW |