Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 <!-- | |
| 2 This in an HTML Import-able file that contains the definition | |
| 3 of the following elements: | |
| 4 | |
| 5 <task-list-summary> | |
| 6 | |
| 7 Usage: | |
| 8 | |
| 9 <task-list-summary></task-list-summary> | |
| 10 | |
| 11 This element summarizes and displays the results of the current query. | |
| 12 It links to some global queries (e.g. all running tasks) and some | |
| 13 sub queries (e.g. all pending tasks that match the rest of the | |
| 14 specified tags.) | |
| 15 | |
| 16 Properties: | |
| 17 // inputs | |
| 18 auth_headers: Object, the OAuth2 header to include in the request. This | |
| 19 should come from swarming-app. | |
| 20 columns: Array<String>, the columns the user has selected. Used to create | |
| 21 the links. | |
| 22 count_params: Object, representing the query params sent to the server based | |
| 23 on all the filterable items (e.g. tags). See task-filters for the | |
| 24 schema. | |
| 25 num_tasks: Number, The number of tasks shown (after filtering). | |
| 26 sort: String, the user's current sort string. Used to create the links. | |
| 27 | |
| 28 // outputs | |
| 29 busy: Boolean, if there are any network requests pending. | |
| 30 | |
| 31 Methods: | |
| 32 None. | |
| 33 | |
| 34 Events: | |
| 35 None. | |
| 36 --> | |
| 37 | |
| 38 <link rel="import" href="/res/imp/bower_components/iron-flex-layout/iron-flex-la yout-classes.html"> | |
| 39 | |
| 40 <link rel="import" href="/res/imp/common/swarming-app.html"> | |
| 41 <link rel="import" href="/res/imp/common/common-behavior.html"> | |
| 42 | |
| 43 <dom-module id="task-list-summary"> | |
| 44 <template> | |
| 45 <style include="swarming-app-style iron-flex"> | |
| 46 :host { | |
| 47 display: block; | |
| 48 border-left: 1px solid black; | |
| 49 padding: 5px 5px; | |
| 50 font-family: sans-serif; | |
| 51 } | |
| 52 .header { | |
| 53 font-size: 1.2em; | |
| 54 font-weight: bold; | |
| 55 } | |
| 56 .column.left { | |
| 57 margin-left: 10px; | |
| 58 } | |
| 59 .right { | |
| 60 text-align: right; | |
| 61 } | |
| 62 .left { | |
| 63 text-align: left; | |
| 64 } | |
| 65 </style> | |
| 66 | |
| 67 <div class="horizontal layout"> | |
| 68 | |
| 69 <div class="column"> | |
| 70 <table> | |
| 71 <thead> | |
| 72 <th class="header right" colspan=2>Selected</th> | |
| 73 </thead> | |
| 74 <tr> | |
| 75 <td class="right"> | |
| 76 Displayed: | |
| 77 </td> | |
| 78 <td class="left">[[num_tasks]]</td> | |
| 79 </tr> | |
| 80 <tr title="By default, these counts are from the last 24 hours"> | |
| 81 <td class="right" > | |
| 82 Total: | |
| 83 </td> | |
| 84 <td class="left">[[_selected_exact.count]]</td> | |
| 85 </tr> | |
| 86 <template is="dom-repeat" items="[[_selected_summary]]" as="item" inde x-as="idx"> | |
| 87 <tr title="By default, these counts are from the last 24 hours"> | |
| 88 <td class="right"> | |
| 89 <a href$="[[_makeURL(item.name,'true',columns.*,sort)]]">[[item. human]]</a>: | |
| 90 </td> | |
| 91 <td class="left">[[_idx(_selected_counts, idx, _selected_counts.*) ]]</td> | |
| 92 </tr> | |
| 93 </template> | |
| 94 </table> | |
| 95 </div> | |
| 96 | |
| 97 <div class="left column"> | |
| 98 <table> | |
| 99 <thead> | |
| 100 <!-- TODO(kjlubick) when user can update time, use the human readabl e value instead of 12h--> | |
| 101 <th class="header right" colspan=2>All Tasks in last 24h</th> | |
| 102 </thead> | |
| 103 <template is="dom-repeat" items="[[_all_summary]]" as="item" index-as= "idx"> | |
| 104 <tr title="By default, this is the last 24 hours"> | |
| 105 <td class="right"> | |
| 106 <a href$="[[_makeURL(item.name,'',columns.*,sort)]]">[[item.huma n]]</a>: | |
| 107 </td> | |
| 108 <td class="left">[[_idx(_all_counts, idx, _all_counts.*)]]</td> | |
| 109 </tr> | |
| 110 </template> | |
| 111 </table> | |
| 112 </div> | |
| 113 | |
| 114 </div> | |
| 115 | |
| 116 </template> | |
| 117 <script> | |
| 118 (function(){ | |
| 119 var ALL_TASKS_SUMMARY = [ | |
| 120 {name:"ALL", human:"All"}, | |
| 121 {name:"BOT_DIED", human:"Bot Died"}, | |
| 122 {name:"CANCELED", human:"Canceled"}, | |
| 123 {name:"COMPLETED_SUCCESS", human:"Completed (Success)"}, | |
| 124 {name:"COMPLETED_FAILURE", human:"Completed (Failure)"}, | |
| 125 {name:"DEDUPED", human:"Deduplicated"}, | |
| 126 {name:"EXPIRED", human:"Expired"}, | |
| 127 {name:"PENDING", human:"Pending"}, | |
| 128 {name:"RUNNING", human:"Running"}, | |
| 129 {name:"TIMED_OUT", human:"Timed Out"}, | |
| 130 ]; | |
| 131 var SELECTED_TASKS_SUMMARY = [ | |
| 132 {name:"BOT_DIED", human:"Bot Died"}, | |
| 133 {name:"CANCELED", human:"Canceled"}, | |
| 134 {name:"COMPLETED_SUCCESS", human:"Completed (Success)"}, | |
| 135 {name:"COMPLETED_FAILURE", human:"Completed (Failure)"}, | |
| 136 {name:"DEDUPED", human:"Deduplicated"}, | |
| 137 {name:"EXPIRED", human:"Expired"}, | |
| 138 {name:"PENDING", human:"Pending"}, | |
| 139 {name:"RUNNING", human:"Running"}, | |
| 140 {name:"TIMED_OUT", human:"Timed Out"}, | |
| 141 ]; | |
| 142 Polymer({ | |
| 143 is: 'task-list-summary', | |
| 144 | |
| 145 behaviors: [SwarmingBehaviors.CommonBehavior], | |
| 146 | |
| 147 properties: { | |
| 148 auth_headers: { | |
| 149 type: Object, | |
| 150 }, | |
| 151 busy: { | |
| 152 type: Boolean, | |
| 153 computed: "_anyBusy(_busyArr1.*,_busyArr2.*,_busy3)", | |
| 154 notify: true, | |
| 155 }, | |
| 156 count_params: { | |
| 157 type: Object, | |
| 158 }, | |
| 159 columns: { | |
| 160 type: Array, | |
| 161 }, | |
| 162 num_tasks: { | |
| 163 type: Number, | |
| 164 }, | |
| 165 sort: { | |
| 166 type: String, | |
| 167 }, | |
| 168 | |
| 169 _busyArr1: { | |
| 170 type:Array, | |
| 171 value: function() { | |
| 172 return []; | |
| 173 } | |
| 174 }, | |
| 175 _busyArr2: { | |
| 176 type:Array, | |
| 177 value: function() { | |
| 178 return []; | |
| 179 } | |
| 180 }, | |
| 181 _busy3: { | |
| 182 type: Boolean, | |
| 183 value: false, | |
| 184 }, | |
| 185 _all_counts: { | |
| 186 type: Array, | |
| 187 value: function() { | |
| 188 return []; | |
| 189 } | |
| 190 }, | |
| 191 _all_summary: { | |
| 192 type: Array, | |
| 193 value: function() { | |
| 194 return ALL_TASKS_SUMMARY; | |
| 195 } | |
| 196 }, | |
| 197 _selected_counts: { | |
| 198 type: Array, | |
| 199 value: function() { | |
| 200 return []; | |
| 201 } | |
| 202 }, | |
| 203 _selected_exact: { | |
| 204 type: Object, | |
| 205 }, | |
| 206 _selected_summary: { | |
| 207 type: Array, | |
| 208 value: function() { | |
| 209 return SELECTED_TASKS_SUMMARY; | |
| 210 } | |
| 211 }, | |
| 212 | |
| 213 }, | |
| 214 | |
| 215 observers: [ | |
| 216 "_recountEverything(auth_headers.*,count_params.*)" | |
| 217 ], | |
| 218 | |
| 219 _anyBusy: function() { | |
|
stephana
2017/02/07 19:26:18
nit: It would be useful if the methods had a short
| |
| 220 for (var i = 0; i<this._busyArr1.length; i++) { | |
| 221 if (this._busyArr1[i].status) { | |
| 222 return true; | |
| 223 } | |
| 224 } | |
| 225 for (var i = 0; i<this._busyArr2.length; i++) { | |
| 226 if (this._busyArr2[i].status) { | |
| 227 return true; | |
| 228 } | |
| 229 } | |
| 230 return this._busy3; | |
| 231 }, | |
| 232 | |
| 233 _idx: function(obj, idx) { | |
| 234 return obj && obj[idx] && obj[idx].count; | |
| 235 }, | |
| 236 | |
| 237 _recountEverything: function() { | |
| 238 if (!this.auth_headers || !this.count_params) { | |
| 239 return; | |
| 240 } | |
| 241 // convert to seconds because API uses seconds. | |
| 242 var now = (new Date()).getTime()/1000; | |
| 243 var last2Days = now - 24 * 60 * 60; | |
| 244 | |
| 245 // TODO(kjlubick): Once users can specify their own times, respect those limits here. | |
| 246 | |
| 247 var queryObj = { | |
| 248 start: [last2Days], | |
| 249 }; | |
| 250 | |
| 251 for (var i = 0; i < ALL_TASKS_SUMMARY.length; i++) { | |
| 252 if (this._all_counts.length < ALL_TASKS_SUMMARY.length) { | |
| 253 this.push("_all_counts", {}); | |
| 254 } | |
| 255 queryObj.state = [ALL_TASKS_SUMMARY[i].name]; | |
| 256 this._getJsonAsyncArr(i, "_all_counts","/api/swarming/v1/tasks/count", "_busyArr1", | |
| 257 this.auth_headers, queryObj); | |
| 258 } | |
| 259 | |
| 260 queryObj = JSON.parse(JSON.stringify(this.count_params)); | |
| 261 queryObj.start = [last2Days]; | |
| 262 this._getJsonAsync("_selected_exact","/api/swarming/v1/tasks/count","_bu sy3", | |
| 263 this.auth_headers, queryObj); | |
| 264 | |
| 265 for (var j = 0; j < SELECTED_TASKS_SUMMARY.length; j++) { | |
| 266 if (this._selected_counts.length < SELECTED_TASKS_SUMMARY.length) { | |
| 267 this.push("_selected_counts", {}); | |
| 268 } | |
| 269 queryObj.state = [SELECTED_TASKS_SUMMARY[j].name]; | |
| 270 this._getJsonAsyncArr(j, "_selected_counts","/api/swarming/v1/tasks/co unt","_busyArr2", | |
| 271 this.auth_headers, queryObj); | |
| 272 } | |
| 273 }, | |
| 274 | |
| 275 // _makeURL creates a task-list url that keeps the columns and sort requir ements the same | |
| 276 // while changing which state is represented. The preserveOthers signifies if other | |
| 277 // filtering parameters (e.g. tags) should be kept as well. | |
| 278 _makeURL: function(state, preserveOthers) { | |
| 279 var fstr = "state:"+state; | |
| 280 if (preserveOthers) { | |
| 281 var fstr = encodeURIComponent(fstr); | |
| 282 var url = window.location.href; | |
| 283 if (url.indexOf(fstr+"&") !== -1) { | |
| 284 // The state filter is already on the list. | |
| 285 return undefined; | |
| 286 } | |
| 287 if (url.indexOf("f=state") === -1) { | |
| 288 return url + "&f=" + fstr; | |
| 289 } | |
| 290 // Things can't be in multiple states at once - so replace it. | |
| 291 // %3A is url encoded colon (:) | |
| 292 return url.replace(/f=state%3A[A-Z_]+/, `f=state%3A${fstr}`); | |
| 293 } | |
| 294 var params = { | |
| 295 s: [this.sort], | |
| 296 c: this.columns, | |
| 297 } | |
| 298 if (state) { | |
| 299 params["f"] = [fstr]; | |
| 300 } | |
| 301 | |
| 302 return window.location.href.split('?')[0] + '?' + sk.query.fromParamSet( params); | |
| 303 }, | |
| 304 | |
| 305 }); | |
| 306 })(); | |
| 307 </script> | |
| 308 </dom-module> | |
| OLD | NEW |