| 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$="{{!bug_id}}" |
| 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({ |
| 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 }, |
| 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 computeAbsentOrExpanded: (prop, exanded) => !prop || expanded, |
| 416 |
| 417 computeIsPlural: n => n > 1, |
| 418 |
| 401 isRecursiveChange: function() { | 419 isRecursiveChange: function() { |
| 402 if (this.isRecursingIntoChange) { | 420 if (this.isRecursingIntoChange) { |
| 403 return true; | 421 return true; |
| 404 } | 422 } |
| 405 this.isRecursingIntoChange = true; | 423 this.isRecursingIntoChange = true; |
| 406 setTimeout(function() { | 424 setTimeout(function() { |
| 407 this.isRecursingIntoChange = false; | 425 this.isRecursingIntoChange = false; |
| 408 }.bind(this), 10); | 426 }.bind(this), 10); |
| 409 return false; | 427 return false; |
| 410 }, | 428 }, |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 i++; | 542 i++; |
| 525 } | 543 } |
| 526 } | 544 } |
| 527 } | 545 } |
| 528 }, | 546 }, |
| 529 | 547 |
| 530 /** | 548 /** |
| 531 * Toggles expansion of a group of alerts. | 549 * Toggles expansion of a group of alerts. |
| 532 */ | 550 */ |
| 533 onExpandGroupButtonClicked: function(event, detail, sender) { | 551 onExpandGroupButtonClicked: function(event, detail, sender) { |
| 534 var row = sender.parentNode.parentNode; | 552 var row = Polymer.dom(Polymer.dom(sender).parentNode).parentNode; |
| 535 var alertIndex = row.rowIndex - 1; | 553 var alertIndex = row.rowIndex - 1; |
| 536 var alert = this.alertList[alertIndex]; | 554 var alert = this.alertList[alertIndex]; |
| 537 var isExpand = !alert.expanded; | 555 var isExpand = !alert.expanded; |
| 538 alert.expanded = isExpand; | 556 alert.expanded = isExpand; |
| 539 for (var i = alertIndex + 1; i < this.alertList.length; i++) { | 557 for (var i = alertIndex + 1; i < this.alertList.length; i++) { |
| 540 if (this.alertList[i].group == alert.group) { | 558 if (this.alertList[i].group == alert.group) { |
| 541 this.alertList[i].hideRow = !isExpand; | 559 this.alertList[i].hideRow = !isExpand; |
| 542 } else { | 560 } else { |
| 543 break; | 561 break; |
| 544 } | 562 } |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 672 * Callback for the click event for a column header. | 690 * Callback for the click event for a column header. |
| 673 * @param {Event} event Clicked event. | 691 * @param {Event} event Clicked event. |
| 674 * @param {Object} detail Detail Object. | 692 * @param {Object} detail Detail Object. |
| 675 * @param {Element} sender Element that invoked the event. | 693 * @param {Element} sender Element that invoked the event. |
| 676 */ | 694 */ |
| 677 columnHeaderClicked: function(event, detail, sender) { | 695 columnHeaderClicked: function(event, detail, sender) { |
| 678 this.sortBy = sender.id; | 696 this.sortBy = sender.id; |
| 679 var newDirection = 'down'; | 697 var newDirection = 'down'; |
| 680 // Because the <th> element may have been added based on an entry in | 698 // Because the <th> element may have been added based on an entry in |
| 681 // this.extraColumns, this.$[this.sortBy] may not work. | 699 // this.extraColumns, this.$[this.sortBy] may not work. |
| 682 var th = this.$.alerts.querySelector('#' + this.sortBy); | 700 var th = Polymer.dom(this.$.alerts).querySelector('#' + this.sortBy); |
| 683 if (th.getAttribute('data-sort-direction') == 'down') { | 701 if (th.getAttribute('data-sort-direction') == 'down') { |
| 684 newDirection = 'up'; | 702 newDirection = 'up'; |
| 685 } | 703 } |
| 686 this.sortDirection = newDirection; | 704 this.sortDirection = newDirection; |
| 687 }, | 705 }, |
| 688 | 706 |
| 689 /** | 707 /** |
| 690 * Update the table headers to indicate the current table sorting. | 708 * Update the table headers to indicate the current table sorting. |
| 691 */ | 709 */ |
| 692 updateHeaders: function() { | 710 updateHeaders: function() { |
| 693 var headers = this.$.alerts.querySelectorAll('th'); | 711 var headers = Polymer.dom(this.$.alerts).querySelectorAll('th'); |
| 694 for (var i = 0; i < headers.length; i++) { | 712 for (var i = 0; i < headers.length; i++) { |
| 695 if (headers[i].id == this.sortBy) { | 713 if (headers[i].id == this.sortBy) { |
| 696 headers[i].setAttribute('data-sort-direction', this.sortDirection); | 714 Polymer.dom(headers[i]).setAttribute('data-sort-direction', |
| 715 this.sortDirection); |
| 697 } else { | 716 } else { |
| 698 headers[i].removeAttribute('data-sort-direction'); | 717 Polymer.dom(headers[i]).removeAttribute('data-sort-direction'); |
| 699 } | 718 } |
| 700 } | 719 } |
| 701 }, | 720 }, |
| 702 | 721 |
| 703 /** | 722 /** |
| 704 * Sorts the alert list according to the current values of the properties | 723 * Sorts the alert list according to the current values of the properties |
| 705 * sortDirection and sortBy. | 724 * sortDirection and sortBy. |
| 706 */ | 725 */ |
| 707 sort: function() { | 726 sort: function() { |
| 708 var order = this.sortDirection == 'down' ? 1 : -1; | 727 var order = this.sortDirection == 'down' ? 1 : -1; |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 } | 927 } |
| 909 }, | 928 }, |
| 910 | 929 |
| 911 /** | 930 /** |
| 912 * Event handler for the change event of any of the checkboxes for any | 931 * Event handler for the change event of any of the checkboxes for any |
| 913 * alert in the table. | 932 * alert in the table. |
| 914 */ | 933 */ |
| 915 onCheckboxChange: function(event, detail, sender) { | 934 onCheckboxChange: function(event, detail, sender) { |
| 916 if (sender) { | 935 if (sender) { |
| 917 // Checks group member rows. | 936 // Checks group member rows. |
| 918 var alertIndex = sender.parentNode.parentNode.rowIndex - 1; | 937 var alertIndex = Polymer.dom( |
| 938 Polymer.dom(sender).parentNode).parentNode.rowIndex - 1; |
| 919 var alert = this.alertList[alertIndex]; | 939 var alert = this.alertList[alertIndex]; |
| 920 this.updateGroupCheckboxes(alert, alertIndex, alert.selected); | 940 this.updateGroupCheckboxes(alert, alertIndex, alert.selected); |
| 921 | 941 |
| 922 this.previousCheckboxId = this.currentCheckboxId; | 942 this.previousCheckboxId = this.currentCheckboxId; |
| 923 this.currentCheckboxId = sender.id; | 943 this.currentCheckboxId = sender.id; |
| 924 } | 944 } |
| 925 // Update the list of checked alerts. | 945 // Update the list of checked alerts. |
| 926 this.checkedAlerts = this.alertList.filter(function(alertRow) { | 946 this.checkedAlerts = this.alertList.filter(function(alertRow) { |
| 927 return alertRow.selected; | 947 return alertRow.selected; |
| 928 }); | 948 }); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 989 alert.selected = false; | 1009 alert.selected = false; |
| 990 } | 1010 } |
| 991 } | 1011 } |
| 992 }); | 1012 }); |
| 993 this.onCheckboxChange(); | 1013 this.onCheckboxChange(); |
| 994 this.updateBugColumn(); | 1014 this.updateBugColumn(); |
| 995 } | 1015 } |
| 996 }); | 1016 }); |
| 997 })(); | 1017 })(); |
| 998 </script> | 1018 </script> |
| 999 </polymer-element> | 1019 </dom-module> |
| OLD | NEW |