| OLD | NEW |
| 1 <!DOCTYPE html><html><head><!-- | 1 <!DOCTYPE html><html><head><!-- |
| 2 @license | 2 @license |
| 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. | 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. |
| 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
| 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt | 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
| 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt | 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt |
| 7 Code distributed by Google as part of the polymer project is also | 7 Code distributed by Google as part of the polymer project is also |
| 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt | 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 9 --><!-- | 9 --><!-- |
| 10 @license | 10 @license |
| (...skipping 14478 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14489 clientId: { | 14489 clientId: { |
| 14490 type: String, | 14490 type: String, |
| 14491 }, | 14491 }, |
| 14492 profile: { | 14492 profile: { |
| 14493 type: Object, | 14493 type: Object, |
| 14494 readOnly: true | 14494 readOnly: true |
| 14495 }, | 14495 }, |
| 14496 signedIn: { | 14496 signedIn: { |
| 14497 type: Boolean, | 14497 type: Boolean, |
| 14498 readOnly: true, | 14498 readOnly: true, |
| 14499 value: false | 14499 value: false, |
| 14500 notify: true, |
| 14500 } | 14501 } |
| 14501 }, | 14502 }, |
| 14502 | 14503 |
| 14503 _onSignin: function(e) { | 14504 _onSignin: function(e) { |
| 14504 this._setSignedIn(true); | 14505 this._setSignedIn(true); |
| 14505 var user = gapi.auth2.getAuthInstance().currentUser.get(); | 14506 var user = gapi.auth2.getAuthInstance().currentUser.get(); |
| 14506 var profile = user.getBasicProfile(); | 14507 var profile = user.getBasicProfile(); |
| 14507 this._setProfile({ | 14508 this._setProfile({ |
| 14508 email: profile.getEmail(), | 14509 email: profile.getEmail(), |
| 14509 imageUrl: profile.getImageUrl() | 14510 imageUrl: profile.getImageUrl() |
| 14510 }); | 14511 }); |
| 14511 this.set("authResponse", user.getAuthResponse()); | 14512 this.set("authResponse", user.getAuthResponse()); |
| 14513 this._setSignedIn(true); |
| 14512 this.fire("auth-signin"); | 14514 this.fire("auth-signin"); |
| 14513 }, | 14515 }, |
| 14514 | 14516 |
| 14515 _onSignout: function(e) { | 14517 _onSignout: function(e) { |
| 14516 this._setSignedIn(false); | 14518 this._setSignedIn(false); |
| 14517 this._setProfile(null); | 14519 this._setProfile(null); |
| 14518 }, | 14520 }, |
| 14519 | 14521 |
| 14520 _makeHeader: function(authResponse) { | 14522 _makeHeader: function(authResponse) { |
| 14521 if (!authResponse) { | 14523 if (!authResponse) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14575 <app-header-layout> | 14577 <app-header-layout> |
| 14576 <app-header fixed=""> | 14578 <app-header fixed=""> |
| 14577 <app-toolbar> | 14579 <app-toolbar> |
| 14578 <div class="title left">[[name]]</div> | 14580 <div class="title left">[[name]]</div> |
| 14579 <paper-spinner-lite class="left" active="[[busy]]"></paper-spinner-lit
e> | 14581 <paper-spinner-lite class="left" active="[[busy]]"></paper-spinner-lit
e> |
| 14580 | 14582 |
| 14581 <a class="left" href="/newui/">Home</a> | 14583 <a class="left" href="/newui/">Home</a> |
| 14582 <a class="left" href="/newui/botlist">Bot List</a> | 14584 <a class="left" href="/newui/botlist">Bot List</a> |
| 14583 <div class="flex"></div> | 14585 <div class="flex"></div> |
| 14584 | 14586 |
| 14585 <auth-signin class="right" client-id="20770472288-t5smpbpjptka4nd888fv
0ctd23ftba2o.apps.googleusercontent.com" auth-headers="{{auth_headers}}"> | 14587 <auth-signin class="right" client-id="20770472288-t5smpbpjptka4nd888fv
0ctd23ftba2o.apps.googleusercontent.com" auth-headers="{{auth_headers}}" signed-
in="{{signed_in}}"> |
| 14586 </auth-signin> | 14588 </auth-signin> |
| 14587 </app-toolbar> | 14589 </app-toolbar> |
| 14588 </app-header> | 14590 </app-header> |
| 14589 <div class="main-content"> | 14591 <div class="main-content"> |
| 14590 <content></content> | 14592 <content></content> |
| 14591 </div> | 14593 </div> |
| 14592 </app-header-layout> | 14594 </app-header-layout> |
| 14593 | 14595 |
| 14594 </template> | 14596 </template> |
| 14595 <script> | 14597 <script> |
| 14596 Polymer({ | 14598 Polymer({ |
| 14597 is: 'swarming-app', | 14599 is: 'swarming-app', |
| 14598 properties: { | 14600 properties: { |
| 14599 auth_headers: { | 14601 auth_headers: { |
| 14600 type: Object, | 14602 type: Object, |
| 14601 notify: true, | 14603 notify: true, |
| 14602 }, | 14604 }, |
| 14605 signed_in: { |
| 14606 type: Boolean, |
| 14607 value: false, |
| 14608 notify:true, |
| 14609 }, |
| 14610 |
| 14603 busy: { | 14611 busy: { |
| 14604 type: Boolean, | 14612 type: Boolean, |
| 14605 }, | 14613 }, |
| 14606 name: { | 14614 name: { |
| 14607 type: String, | 14615 type: String, |
| 14608 }, | 14616 }, |
| 14609 }, | 14617 }, |
| 14610 | 14618 |
| 14611 }); | 14619 }); |
| 14612 </script> | 14620 </script> |
| (...skipping 962 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 15575 <iron-icon style="top:0" class$="[[_hidden(direction,'asc')]]" icon="icons
:arrow-drop-down"> | 15583 <iron-icon style="top:0" class$="[[_hidden(direction,'asc')]]" icon="icons
:arrow-drop-down"> |
| 15576 </iron-icon> | 15584 </iron-icon> |
| 15577 <iron-icon style="bottom:0" class$="[[_hidden(direction,'desc')]]" icon="i
cons:arrow-drop-up"> | 15585 <iron-icon style="bottom:0" class$="[[_hidden(direction,'desc')]]" icon="i
cons:arrow-drop-up"> |
| 15578 </iron-icon> | 15586 </iron-icon> |
| 15579 </span> | 15587 </span> |
| 15580 | 15588 |
| 15581 </template> | 15589 </template> |
| 15582 <script> | 15590 <script> |
| 15583 Polymer({ | 15591 Polymer({ |
| 15584 is: "sort-toggle", | 15592 is: "sort-toggle", |
| 15593 |
| 15585 properties: { | 15594 properties: { |
| 15586 current: { | 15595 current: { |
| 15587 type: Object, | 15596 type: Object, |
| 15588 observer: "_resetSort", | 15597 observer: "_resetSort", |
| 15589 }, | 15598 }, |
| 15590 name: { | 15599 name: { |
| 15591 type: String, | 15600 type: String, |
| 15592 observer: "_resetSort", | 15601 observer: "_resetSort", |
| 15593 }, | 15602 }, |
| 15594 | 15603 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 15619 // Because of how Polymer inserts and moves elements around, we need to | 15628 // Because of how Polymer inserts and moves elements around, we need to |
| 15620 // update the direction value if the name changes so the ascending sort | 15629 // update the direction value if the name changes so the ascending sort |
| 15621 // by "os" doesn't become the ascending sort by "gpu" if a column gets | 15630 // by "os" doesn't become the ascending sort by "gpu" if a column gets |
| 15622 // added before "os", for example. Additionally, this makes sure that | 15631 // added before "os", for example. Additionally, this makes sure that |
| 15623 // only one sort-toggle is active at a given time. | 15632 // only one sort-toggle is active at a given time. |
| 15624 if (this.current && this.current.name === this.name) { | 15633 if (this.current && this.current.name === this.name) { |
| 15625 this.set("direction", this.current.direction); | 15634 this.set("direction", this.current.direction); |
| 15626 } else { | 15635 } else { |
| 15627 this.set("direction", ""); | 15636 this.set("direction", ""); |
| 15628 } | 15637 } |
| 15629 | |
| 15630 }, | 15638 }, |
| 15631 }); | 15639 }); |
| 15632 </script> | 15640 </script> |
| 15633 </dom-module><script> | 15641 </dom-module><script> |
| 15634 | 15642 |
| 15635 /** | 15643 /** |
| 15636 * @param {!Function} selectCallback | 15644 * @param {!Function} selectCallback |
| 15637 * @constructor | 15645 * @constructor |
| 15638 */ | 15646 */ |
| 15639 Polymer.IronSelection = function(selectCallback) { | 15647 Polymer.IronSelection = function(selectCallback) { |
| (...skipping 5272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 20912 // Since they will be or'd together, order doesn't matter. | 20920 // Since they will be or'd together, order doesn't matter. |
| 20913 var filterGroups = {}; | 20921 var filterGroups = {}; |
| 20914 this._filters.forEach(function(filterString){ | 20922 this._filters.forEach(function(filterString){ |
| 20915 var idx = filterString.indexOf(FILTER_SEP); | 20923 var idx = filterString.indexOf(FILTER_SEP); |
| 20916 var primary = filterString.slice(0, idx); | 20924 var primary = filterString.slice(0, idx); |
| 20917 var param = filterString.slice(idx + FILTER_SEP.length); | 20925 var param = filterString.slice(idx + FILTER_SEP.length); |
| 20918 var arr = filterGroups[primary] || []; | 20926 var arr = filterGroups[primary] || []; |
| 20919 arr.push(param); | 20927 arr.push(param); |
| 20920 filterGroups[primary] = arr; | 20928 filterGroups[primary] = arr; |
| 20921 }); | 20929 }); |
| 20922 return { | 20930 return function(bot){ |
| 20923 filter: function(bot){ | 20931 var retVal = true; |
| 20924 var retVal = true; | 20932 // Look up all the primary keys we are filter by, then look up how |
| 20925 // Look up all the primary keys we are filter by, then look up how | 20933 // to filter (in filterMap) and apply the filter for each filter |
| 20926 // to filter (in filterMap) and apply the filter for each filter | 20934 // option. |
| 20927 // option. | 20935 for (primary in filterGroups){ |
| 20928 for (primary in filterGroups){ | 20936 var params = filterGroups[primary]; |
| 20929 var params = filterGroups[primary]; | 20937 var filter = filterMap[primary]; |
| 20930 var filter = filterMap[primary]; | 20938 var groupResult = false; |
| 20931 var groupResult = false; | 20939 if (filter) { |
| 20932 if (filter) { | 20940 params.forEach(function(param){ |
| 20933 params.forEach(function(param){ | 20941 groupResult = groupResult || filter.bind(this)(bot,param); |
| 20934 groupResult = groupResult || filter.bind(this)(bot,param); | 20942 }.bind(this)); |
| 20935 }.bind(this)); | |
| 20936 } | |
| 20937 retVal = retVal && groupResult; | |
| 20938 } | 20943 } |
| 20939 return retVal; | 20944 retVal = retVal && groupResult; |
| 20940 } | 20945 } |
| 20946 return retVal; |
| 20941 } | 20947 } |
| 20942 }, | 20948 }, |
| 20943 | 20949 |
| 20944 _primary: function(query, primary_map, primary_arr) { | 20950 _primary: function(query, primary_map, primary_arr) { |
| 20945 // If the user has typed in a query, only show those primary keys that | 20951 // If the user has typed in a query, only show those primary keys that |
| 20946 // partially match the query or that have secondary values which | 20952 // partially match the query or that have secondary values which |
| 20947 // partially match. | 20953 // partially match. |
| 20948 var arr = this.primary_arr.filter(function(s){ | 20954 var arr = this.primary_arr.filter(function(s){ |
| 20949 if (matchPartCaseInsensitive(s, query).idx !== -1) { | 20955 if (matchPartCaseInsensitive(s, query).idx !== -1) { |
| 20950 return true; | 20956 return true; |
| (...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21144 | 21150 |
| 21145 _gpuAlias: function(gpu) { | 21151 _gpuAlias: function(gpu) { |
| 21146 var a = GPU_ALIASES[gpu]; | 21152 var a = GPU_ALIASES[gpu]; |
| 21147 if (!a) { | 21153 if (!a) { |
| 21148 return "UNKNOWN"; | 21154 return "UNKNOWN"; |
| 21149 } | 21155 } |
| 21150 return a; | 21156 return a; |
| 21151 }, | 21157 }, |
| 21152 | 21158 |
| 21153 _not: function(a) { | 21159 _not: function(a) { |
| 21154 return a; | 21160 return !a; |
| 21161 }, |
| 21162 |
| 21163 _or: function() { |
| 21164 var result = false; |
| 21165 // can't use .foreach, as arguments isn't really a function. |
| 21166 for (var i = 0; i < arguments.length; i++) { |
| 21167 result = result || arguments[i]; |
| 21168 } |
| 21169 return result; |
| 21155 }, | 21170 }, |
| 21156 | 21171 |
| 21157 _taskId: function(bot) { | 21172 _taskId: function(bot) { |
| 21158 if (bot && bot.task_id) { | 21173 if (bot && bot.task_id) { |
| 21159 return bot.task_id; | 21174 return bot.task_id; |
| 21160 } | 21175 } |
| 21161 return "idle"; | 21176 return "idle"; |
| 21162 }, | 21177 }, |
| 21163 | 21178 |
| 21164 // _unalias will return the base dimension/state with its alias removed | 21179 // _unalias will return the base dimension/state with its alias removed |
| 21165 // if it had one. This is handy for sorting and filtering. | 21180 // if it had one. This is handy for sorting and filtering. |
| 21166 _unalias: function(str) { | 21181 _unalias: function(str) { |
| 21167 var match = ALIAS_REGEXP.exec(str); | 21182 var match = ALIAS_REGEXP.exec(str); |
| 21168 if (match) { | 21183 if (match) { |
| 21169 return match[1]; | 21184 return match[1]; |
| 21170 } | 21185 } |
| 21171 return str; | 21186 return str; |
| 21172 }, | 21187 }, |
| 21173 } | 21188 } |
| 21174 })() | 21189 })() |
| 21175 </script> | 21190 </script> |
| 21176 <dom-module id="bot-list-data" assetpath="/res/imp/botlist/"> | 21191 <dom-module id="bot-list-data" assetpath="/res/imp/botlist/"> |
| 21177 <template> | 21192 <template> |
| 21178 <iron-ajax id="request" url="/_ah/api/swarming/v1/bots/list" headers="[[auth
_headers]]" handle-as="json" last-response="{{_data}}" loading="{{busy}}"> | 21193 <iron-ajax id="botlist" url="/_ah/api/swarming/v1/bots/list" headers="[[auth
_headers]]" handle-as="json" last-response="{{_list}}" loading="{{_busy1}}"> |
| 21194 </iron-ajax> |
| 21195 |
| 21196 <iron-ajax id="fleet" url="/_ah/api/swarming/v1/bots/count" headers="[[auth_
headers]]" handle-as="json" last-response="{{_count}}" loading="{{_busy2}}"> |
| 21179 </iron-ajax> | 21197 </iron-ajax> |
| 21180 </template> | 21198 </template> |
| 21181 <script> | 21199 <script> |
| 21182 (function(){ | 21200 (function(){ |
| 21183 // TODO(kjlubick): Add more of these as well as things from state | 21201 // TODO(kjlubick): Add more of these as well as things from state |
| 21184 // i.e. disk space remaining. | 21202 // i.e. disk space remaining. |
| 21185 var DIMENSIONS = ["cores", "cpu", "id", "os", "pool"]; | 21203 var DIMENSIONS = ["cores", "cpu", "id", "os", "pool"]; |
| 21186 // "gpu" and "devices" are added separately because we need to | 21204 // "gpu" and "devices" are added separately because we need to |
| 21187 // deal with aliases. | 21205 // deal with aliases. |
| 21188 var BOT_PROPERTIES = ["gpu", "devices", "task", "status"]; | 21206 var BOT_PROPERTIES = ["gpu", "devices", "task", "status"]; |
| 21189 Polymer({ | 21207 Polymer({ |
| 21190 is: 'bot-list-data', | 21208 is: 'bot-list-data', |
| 21209 |
| 21210 behaviors: [SwarmingBehaviors.BotListBehavior], |
| 21211 |
| 21191 properties: { | 21212 properties: { |
| 21192 // inputs | 21213 // inputs |
| 21193 auth_headers: { | 21214 auth_headers: { |
| 21194 type: Object, | 21215 type: Object, |
| 21195 observer: "signIn", | 21216 observer: "signIn", |
| 21196 }, | 21217 }, |
| 21197 | 21218 |
| 21198 //outputs | 21219 //outputs |
| 21199 bots: { | 21220 bots: { |
| 21200 type: Array, | 21221 type: Array, |
| 21201 computed: "_bots(_data)", | 21222 computed: "_bots(_list)", |
| 21202 notify: true, | 21223 notify: true, |
| 21203 }, | 21224 }, |
| 21204 busy: { | 21225 busy: { |
| 21205 type: Boolean, | 21226 type: Boolean, |
| 21227 computed: "_or(_busy1,_busy2)", |
| 21228 notify: true, |
| 21229 }, |
| 21230 fleet: { |
| 21231 type: Object, |
| 21232 computed: "_fleet(_count)", |
| 21206 notify: true, | 21233 notify: true, |
| 21207 }, | 21234 }, |
| 21208 primary_map: { | 21235 primary_map: { |
| 21209 type:Object, | 21236 type:Object, |
| 21210 computed: "_primaryMap(bots)", | 21237 computed: "_primaryMap(bots)", |
| 21211 notify: true, | 21238 notify: true, |
| 21212 }, | 21239 }, |
| 21213 primary_arr: { | 21240 primary_arr: { |
| 21214 type:Array, | 21241 type:Array, |
| 21215 value: function() { | 21242 value: function() { |
| 21216 return DIMENSIONS.concat(BOT_PROPERTIES); | 21243 return DIMENSIONS.concat(BOT_PROPERTIES); |
| 21217 }, | 21244 }, |
| 21218 notify: true, | 21245 notify: true, |
| 21219 }, | 21246 }, |
| 21220 | 21247 |
| 21221 // private | 21248 // private |
| 21222 _data: { | 21249 _count: { |
| 21250 type: Object, |
| 21251 }, |
| 21252 _list: { |
| 21223 type: Object, | 21253 type: Object, |
| 21224 }, | 21254 }, |
| 21225 }, | 21255 }, |
| 21226 behaviors: [SwarmingBehaviors.BotListBehavior], | |
| 21227 | 21256 |
| 21228 signIn: function(){ | 21257 signIn: function(){ |
| 21229 this.$.request.generateRequest(); | 21258 this.$.botlist.generateRequest(); |
| 21259 this.$.fleet.generateRequest(); |
| 21230 }, | 21260 }, |
| 21231 | 21261 |
| 21232 _bots: function(){ | 21262 _bots: function(){ |
| 21233 if (!this._data || !this._data.items) { | 21263 if (!this._list || !this._list.items) { |
| 21234 return []; | 21264 return []; |
| 21235 } | 21265 } |
| 21236 this._data.items.forEach(function(o){ | 21266 this._list.items.forEach(function(o){ |
| 21237 o.state = JSON.parse(o.state); | 21267 o.state = JSON.parse(o.state); |
| 21238 }); | 21268 }); |
| 21239 return this._data.items; | 21269 return this._list.items; |
| 21270 }, |
| 21271 |
| 21272 _fleet: function() { |
| 21273 if (!this._count) { |
| 21274 return {}; |
| 21275 } |
| 21276 return { |
| 21277 alive: this._count.count || -1, |
| 21278 busy: this._count.busy || -1, |
| 21279 idle: this._count.count && this._count.busy && |
| 21280 this._count.count - this._count.busy, |
| 21281 dead: this._count.dead || -1, |
| 21282 quarantined: this._count.quarantined || -1, |
| 21283 } |
| 21240 }, | 21284 }, |
| 21241 | 21285 |
| 21242 _primaryMap: function(bots){ | 21286 _primaryMap: function(bots){ |
| 21243 // map will keep track of dimensions that we have seen at least once. | 21287 // map will keep track of dimensions that we have seen at least once. |
| 21244 // This will then basically get turned into an array to be used for | 21288 // This will then basically get turned into an array to be used for |
| 21245 // filtering. | 21289 // filtering. |
| 21246 var map = {}; | 21290 var map = {}; |
| 21247 DIMENSIONS.forEach(function(p){ | 21291 DIMENSIONS.forEach(function(p){ |
| 21248 map[p] = {}; | 21292 map[p] = {}; |
| 21249 }); | 21293 }); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21290 | 21334 |
| 21291 // Create custom filter options | 21335 // Create custom filter options |
| 21292 pMap["task"] = ["busy", "idle"]; | 21336 pMap["task"] = ["busy", "idle"]; |
| 21293 pMap["status"] = ["available", "dead", "quarantined"]; | 21337 pMap["status"] = ["available", "dead", "quarantined"]; |
| 21294 return pMap; | 21338 return pMap; |
| 21295 }, | 21339 }, |
| 21296 | 21340 |
| 21297 }); | 21341 }); |
| 21298 })(); | 21342 })(); |
| 21299 </script> | 21343 </script> |
| 21344 </dom-module><dom-module id="bot-list-summary" assetpath="/res/imp/botlist/"> |
| 21345 <template> |
| 21346 <style include="swarming-app-style"> |
| 21347 :host { |
| 21348 display: block; |
| 21349 border-left: 1px solid black; |
| 21350 padding: 5px 5px; |
| 21351 font-family: sans-serif; |
| 21352 } |
| 21353 .header { |
| 21354 font-size: 1.2em; |
| 21355 font-weight: bold; |
| 21356 } |
| 21357 .right { |
| 21358 text-align: right; |
| 21359 } |
| 21360 .left { |
| 21361 text-align: left; |
| 21362 } |
| 21363 </style> |
| 21364 |
| 21365 <div class="header">Fleet</div> |
| 21366 |
| 21367 <table> |
| 21368 <tbody><tr> |
| 21369 <td class="right"><a href="/newui/botlist?alive">Alive</a>:</td> |
| 21370 <td class="left">[[fleet.alive]]</td> |
| 21371 </tr> |
| 21372 <tr> |
| 21373 <td class="right"><a href="/newui/botlist?busy">Busy</a>:</td> |
| 21374 <td class="left">[[fleet.busy]]</td> |
| 21375 </tr> |
| 21376 <tr> |
| 21377 <td class="right"><a href="/newui/botlist?idle">Idle</a>:</td> |
| 21378 <td class="left">[[fleet.idle]]</td> |
| 21379 </tr> |
| 21380 <tr> |
| 21381 <td class="right"><a href="/newui/botlist?dead">Dead</a>:</td> |
| 21382 <td class="left">[[fleet.dead]]</td> |
| 21383 </tr> |
| 21384 <tr> |
| 21385 <td class="right"><a href="/newui/botlist?quaren">Quarantined</a>:</td> |
| 21386 <td class="left">[[fleet.quarantined]]</td> |
| 21387 </tr> |
| 21388 </tbody></table> |
| 21389 |
| 21390 <div class="header">Displayed</div> |
| 21391 <table> |
| 21392 <tbody><tr> |
| 21393 <td class="right"><a href="/newui/botlist?alive2">Alive</a>:</td> |
| 21394 <td class="left">[[_currently_showing.alive]]</td> |
| 21395 </tr> |
| 21396 <tr> |
| 21397 <td class="right"><a href="/newui/botlist?busy2">Busy</a>:</td> |
| 21398 <td class="left">[[_currently_showing.busy]]</td> |
| 21399 </tr> |
| 21400 <tr> |
| 21401 <td class="right"><a href="/newui/botlist?idle2">Idle</a>:</td> |
| 21402 <td class="left">[[_currently_showing.idle]]</td> |
| 21403 </tr> |
| 21404 <tr> |
| 21405 <td class="right"><a href="/newui/botlist?dead2">Dead</a>:</td> |
| 21406 <td class="left">[[_currently_showing.dead]]</td> |
| 21407 </tr> |
| 21408 <tr> |
| 21409 <td class="right"><a href="/newui/botlist?quaren2">Quarantined</a>:</td> |
| 21410 <td class="left">[[_currently_showing.quarantined]]</td> |
| 21411 </tr> |
| 21412 </tbody></table> |
| 21413 |
| 21414 </template> |
| 21415 <script> |
| 21416 Polymer({ |
| 21417 is: 'bot-list-summary', |
| 21418 |
| 21419 behaviors: [SwarmingBehaviors.BotListBehavior], |
| 21420 |
| 21421 properties: { |
| 21422 filtered_bots: { |
| 21423 type: Array, |
| 21424 }, |
| 21425 fleet: { |
| 21426 type: Object, |
| 21427 }, |
| 21428 |
| 21429 _currently_showing: { |
| 21430 type: Object, |
| 21431 value: function() { |
| 21432 return { |
| 21433 alive: -1, |
| 21434 busy: -1, |
| 21435 idle: -1, |
| 21436 dead: -1, |
| 21437 quarantined: -1, |
| 21438 }; |
| 21439 }, |
| 21440 }, |
| 21441 }, |
| 21442 |
| 21443 // Do this because Array changes in Polymer don't always trigger normal |
| 21444 // property observers |
| 21445 observers: ["_recount(filtered_bots.*)"], |
| 21446 |
| 21447 _recount: function() { |
| 21448 var curr = { |
| 21449 alive: 0, |
| 21450 busy: 0, |
| 21451 idle: 0, |
| 21452 dead: 0, |
| 21453 quarantined: 0, |
| 21454 }; |
| 21455 if (!this.filtered_bots) { |
| 21456 return curr; |
| 21457 } |
| 21458 this.filtered_bots.forEach(function(bot) { |
| 21459 if (this._taskId(bot) === "idle") { |
| 21460 curr.idle++; |
| 21461 } else { |
| 21462 curr.busy++; |
| 21463 } |
| 21464 if (bot.quarantined) { |
| 21465 curr.quarantined++; |
| 21466 } |
| 21467 if (bot.is_dead) { |
| 21468 curr.dead++; |
| 21469 } else { |
| 21470 curr.alive++; |
| 21471 } |
| 21472 }.bind(this)); |
| 21473 this.set("_currently_showing", curr); |
| 21474 } |
| 21475 }); |
| 21476 </script> |
| 21300 </dom-module><dom-module id="bot-list" assetpath="/res/imp/botlist/"> | 21477 </dom-module><dom-module id="bot-list" assetpath="/res/imp/botlist/"> |
| 21301 <template> | 21478 <template> |
| 21302 <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-
style"> | 21479 <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-
style"> |
| 21303 bot-filters { | 21480 bot-filters, bot-list-summary { |
| 21304 margin-bottom: 5px; | 21481 margin-bottom: 8px; |
| 21482 margin-right: 10px; |
| 21305 } | 21483 } |
| 21306 .bot { | 21484 .bot { |
| 21307 margin:5px; | 21485 margin:5px; |
| 21308 max-width:400px; | 21486 max-width:400px; |
| 21309 min-height:100px; | 21487 min-height:100px; |
| 21310 min-width:300px; | 21488 min-width:300px; |
| 21311 } | 21489 } |
| 21312 table { | 21490 table { |
| 21313 border-collapse: collapse; | 21491 border-collapse: collapse; |
| 21314 margin-left: 5px; | 21492 margin-left: 5px; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 21332 position: absolute; | 21510 position: absolute; |
| 21333 right: 0; | 21511 right: 0; |
| 21334 top: 0.4em; | 21512 top: 0.4em; |
| 21335 } | 21513 } |
| 21336 .bot-list th > span { | 21514 .bot-list th > span { |
| 21337 /* Leave space for sort-toggle*/ | 21515 /* Leave space for sort-toggle*/ |
| 21338 padding-right: 30px; | 21516 padding-right: 30px; |
| 21339 } | 21517 } |
| 21340 </style> | 21518 </style> |
| 21341 | 21519 |
| 21342 <swarming-app auth_headers="{{auth_headers}}" busy="[[busy]]" name="Swarming
Bot List"> | 21520 <swarming-app auth_headers="{{_auth_headers}}" signed_in="{{_signed_in}}" bu
sy="[[_busy]]" name="Swarming Bot List"> |
| 21343 | 21521 |
| 21344 <bot-filters primary_map="[[primary_map]]" primary_arr="[[primary_arr]]" c
olumns="{{columns}}" filter="{{filter}}" verbose="{{verbose}}"> | 21522 <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2> |
| 21345 </bot-filters> | |
| 21346 | 21523 |
| 21347 <bot-list-data auth_headers="[[auth_headers]]" bots="{{bots}}" busy="{{bus
y}}" primary_map="{{primary_map}}" primary_arr="{{primary_arr}}"> | 21524 <div hidden$="[[_not(_signed_in)]]"> |
| 21348 </bot-list-data> | |
| 21349 | 21525 |
| 21350 <table class="bot-list"> | 21526 <div class="horizontal layout"> |
| 21351 <thead on-sort_change="sortChange"> | 21527 |
| 21352 | 21528 <bot-filters primary_map="[[_primary_map]]" primary_arr="[[_primary_ar
r]]" columns="{{_columns}}" filter="{{_filter}}" verbose="{{_verbose}}"> |
| 21353 <tr><th> | 21529 </bot-filters> |
| 21354 <span>Bot Id</span> | 21530 |
| 21355 <sort-toggle name="id" current="[[sort]]"> | 21531 <bot-list-summary fleet="[[_fleet]]" filtered_bots="[[_filteredSortedB
ots]]"> |
| 21356 </sort-toggle> | 21532 </bot-list-summary> |
| 21357 </th> | 21533 |
| 21534 </div> |
| 21535 |
| 21536 <bot-list-data auth_headers="[[_auth_headers]]" bots="{{_bots}}" busy="{
{_busy}}" fleet="{{_fleet}}" primary_map="{{_primary_map}}" primary_arr="{{_prim
ary_arr}}"> |
| 21537 </bot-list-data> |
| 21538 |
| 21539 <table class="bot-list"> |
| 21540 <thead on-sort_change="_sortChange"> |
| 21358 | 21541 |
| 21359 <th hidden$="[[_hide('task', columns.*)]]"> | 21542 <tr> |
| 21360 <span>Current Task</span> | 21543 <th> |
| 21361 <sort-toggle name="task" current="[[sort]]"> | 21544 <span>Bot Id</span> |
| 21362 </sort-toggle> | 21545 <sort-toggle name="id" current="[[_sort]]"> |
| 21363 </th> | 21546 </sort-toggle> |
| 21547 </th> |
| 21548 |
| 21549 <th hidden$="[[_hide('task', _columns.*)]]"> |
| 21550 <span>Current Task</span> |
| 21551 <sort-toggle name="task" current="[[_sort]]"> |
| 21552 </sort-toggle> |
| 21553 </th> |
| 21364 | 21554 |
| 21365 <template is="dom-repeat" items="[[plain_columns]]" as="c"> | 21555 <template is="dom-repeat" items="[[_plain_columns]]" as="c"> |
| 21366 <th hidden$="[[_hide(c)]]"> | 21556 <th hidden$="[[_hide(c)]]"> |
| 21367 <span>[[_header(c)]]</span> | 21557 <span>[[_header(c)]]</span> |
| 21368 <sort-toggle name="[[c]]" current="[[sort]]"> | 21558 <sort-toggle name="[[c]]" current="[[_sort]]"> |
| 21369 </sort-toggle> | 21559 </sort-toggle> |
| 21370 </th> | 21560 </th> |
| 21371 </template> | 21561 </template> |
| 21372 </tr></thead> | 21562 </tr> |
| 21373 <tbody> | 21563 </thead> |
| 21374 <template id="bot_table" is="dom-repeat" items="[[bots]]" as="bot" ini
tial-count="50" filter="_filterBotTable"> | 21564 <tbody> |
| 21565 <template id="bot_table" is="dom-repeat" items="[[_filteredSortedBot
s]]" as="bot" initial-count="50"> |
| 21375 | 21566 |
| 21376 <tr class$="[[_botClass(bot)]]"> | 21567 <tr class$="[[_botClass(bot)]]"> |
| 21377 <td> | 21568 <td> |
| 21378 <a class="center" href$="[[_botLink(bot.bot_id)]]" target="_blan
k"> | 21569 <a class="center" href$="[[_botLink(bot.bot_id)]]" target="_bl
ank"> |
| 21379 [[bot.bot_id]] | 21570 [[bot.bot_id]] |
| 21380 </a> | 21571 </a> |
| 21381 </td> | 21572 </td> |
| 21382 <td hidden$="[[_hide('task', columns.*)]]"> | 21573 <td hidden$="[[_hide('task', _columns.*)]]"> |
| 21383 <a href$="[[_taskLink(bot)]]">[[_taskId(bot)]]</a> | 21574 <a href$="[[_taskLink(bot)]]">[[_taskId(bot)]]</a> |
| 21384 </td> | 21575 </td> |
| 21385 | 21576 |
| 21386 <template is="dom-repeat" items="[[plain_columns]]" as="c"> | 21577 <template is="dom-repeat" items="[[_plain_columns]]" as="c"> |
| 21387 <td hidden$="[[_hide(c)]]"> | |
| 21388 [[_column(c, bot, verbose)]] | |
| 21389 </td> | |
| 21390 </template> | |
| 21391 | |
| 21392 </tr> | |
| 21393 <template is="dom-repeat" items="[[_devices(bot)]]" as="device"> | |
| 21394 <tr hidden$="[[_hide('devices', columns.*)]]" class$="[[_deviceCla
ss(device)]]"> | |
| 21395 <td></td> | |
| 21396 <td hidden$="[[_hide('task', columns.*)]]"></td> | |
| 21397 <template is="dom-repeat" items="[[plain_columns]]" as="c"> | |
| 21398 <td hidden$="[[_hide(c)]]"> | 21578 <td hidden$="[[_hide(c)]]"> |
| 21399 [[_deviceColumn(c, device, verbose)]] | 21579 [[_column(c, bot, _verbose)]] |
| 21400 </td> | 21580 </td> |
| 21401 </template> | 21581 </template> |
| 21582 |
| 21402 </tr> | 21583 </tr> |
| 21584 <template is="dom-repeat" items="[[_devices(bot)]]" as="device"> |
| 21585 <tr hidden$="[[_hide('devices', _columns.*)]]" class$="[[_device
Class(device)]]"> |
| 21586 <td></td> |
| 21587 <td hidden$="[[_hide('task', _columns.*)]]"></td> |
| 21588 <template is="dom-repeat" items="[[_plain_columns]]" as="c"> |
| 21589 <td hidden$="[[_hide(c)]]"> |
| 21590 [[_deviceColumn(c, device, _verbose)]] |
| 21591 </td> |
| 21592 </template> |
| 21593 </tr> |
| 21594 </template> |
| 21403 </template> | 21595 </template> |
| 21404 </template> | 21596 </tbody> |
| 21405 </tbody> | 21597 </table> |
| 21406 </table> | 21598 </div> |
| 21407 | 21599 |
| 21408 </swarming-app> | 21600 </swarming-app> |
| 21409 | 21601 |
| 21410 </template> | 21602 </template> |
| 21411 <script> | 21603 <script> |
| 21412 (function(){ | 21604 (function(){ |
| 21413 var special_columns = ["id", "task"]; | 21605 var special_columns = ["id", "task"]; |
| 21414 | 21606 |
| 21415 var headerMap = { | 21607 var headerMap = { |
| 21416 // "id" and "task" are special, so they don't go here and have their | 21608 // "id" and "task" are special, so they don't go here and have their |
| 21417 // headers hard-coded below. | 21609 // headers hard-coded below. |
| 21418 "cores": "Cores", | 21610 "cores": "Cores", |
| 21419 "cpu": "CPU", | 21611 "cpu": "CPU", |
| 21420 "devices": "Devices", | 21612 "devices": "Devices", |
| 21421 "gpu": "GPU", | 21613 "gpu": "GPU", |
| 21422 "os": "OS", | 21614 "os": "OS", |
| 21423 "pool": "Pool", | 21615 "pool": "Pool", |
| 21424 "status": "Status", | 21616 "status": "Status", |
| 21425 }; | 21617 }; |
| 21426 | 21618 |
| 21427 // This maps column name to a function that will return the content for a | 21619 // This maps column name to a function that will return the content for a |
| 21428 // given bot. These functions are bound to this element, and have access | 21620 // given bot. These functions are bound to this element, and have access |
| 21429 // to all functions defined here and in bot-list-shared. | 21621 // to all functions defined here and in bot-list-shared. |
| 21430 var columnMap = { | 21622 var columnMap = { |
| 21431 cores: function(bot){ | 21623 cores: function(bot){ |
| 21432 var cores = this._cores(bot); | 21624 var cores = this._cores(bot); |
| 21433 if (this.verbose){ | 21625 if (this._verbose){ |
| 21434 return cores.join(" | "); | 21626 return cores.join(" | "); |
| 21435 } | 21627 } |
| 21436 return cores[0]; | 21628 return cores[0]; |
| 21437 }, | 21629 }, |
| 21438 cpu: function(bot){ | 21630 cpu: function(bot){ |
| 21439 var cpus = this._dimension(bot, 'cpu') || ['Unknown']; | 21631 var cpus = this._dimension(bot, 'cpu') || ['Unknown']; |
| 21440 if (this.verbose){ | 21632 if (this._verbose){ |
| 21441 return cpus.join(" | "); | 21633 return cpus.join(" | "); |
| 21442 } | 21634 } |
| 21443 return cpus[0]; | 21635 return cpus[0]; |
| 21444 }, | 21636 }, |
| 21445 devices: function(bot){ | 21637 devices: function(bot){ |
| 21446 return this._devices(bot).length + " devices attached"; | 21638 return this._devices(bot).length + " devices attached"; |
| 21447 }, | 21639 }, |
| 21448 gpu: function(bot){ | 21640 gpu: function(bot){ |
| 21449 var gpus = this._dimension(bot, 'gpu') | 21641 var gpus = this._dimension(bot, 'gpu') |
| 21450 if (!gpus) { | 21642 if (!gpus) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21461 if (g.indexOf(":") === -1) { | 21653 if (g.indexOf(":") === -1) { |
| 21462 named.push(g); | 21654 named.push(g); |
| 21463 } | 21655 } |
| 21464 return; | 21656 return; |
| 21465 } | 21657 } |
| 21466 verbose.push(this._applyAlias(g, alias)); | 21658 verbose.push(this._applyAlias(g, alias)); |
| 21467 if (g.indexOf(":") === -1) { | 21659 if (g.indexOf(":") === -1) { |
| 21468 named.push(this._applyAlias(g, alias)); | 21660 named.push(this._applyAlias(g, alias)); |
| 21469 } | 21661 } |
| 21470 }.bind(this)) | 21662 }.bind(this)) |
| 21471 if (this.verbose) { | 21663 if (this._verbose) { |
| 21472 return verbose.join(" | "); | 21664 return verbose.join(" | "); |
| 21473 } | 21665 } |
| 21474 return named.join(" | "); | 21666 return named.join(" | "); |
| 21475 }, | 21667 }, |
| 21476 id: function(bot) { | 21668 id: function(bot) { |
| 21477 return bot.bot_id; | 21669 return bot.bot_id; |
| 21478 }, | 21670 }, |
| 21479 os: function(bot) { | 21671 os: function(bot) { |
| 21480 var os = this._dimension(bot, 'os') || ['Unknown']; | 21672 var os = this._dimension(bot, 'os') || ['Unknown']; |
| 21481 if (this.verbose){ | 21673 if (this._verbose){ |
| 21482 return os.join(" | "); | 21674 return os.join(" | "); |
| 21483 } | 21675 } |
| 21484 return os[0]; | 21676 return os[0]; |
| 21485 }, | 21677 }, |
| 21486 pool: function(bot) { | 21678 pool: function(bot) { |
| 21487 var pool = this._dimension(bot, 'pool') || ['Unknown']; | 21679 var pool = this._dimension(bot, 'pool') || ['Unknown']; |
| 21488 return pool.join(" | "); | 21680 return pool.join(" | "); |
| 21489 }, | 21681 }, |
| 21490 status: function(bot) { | 21682 status: function(bot) { |
| 21491 // If a bot is both dead and quarantined, show the deadness over the | 21683 // If a bot is both dead and quarantined, show the deadness over the |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21502 return this._taskId(bot); | 21694 return this._taskId(bot); |
| 21503 }, | 21695 }, |
| 21504 }; | 21696 }; |
| 21505 | 21697 |
| 21506 Polymer({ | 21698 Polymer({ |
| 21507 is: 'bot-list', | 21699 is: 'bot-list', |
| 21508 behaviors: [SwarmingBehaviors.BotListBehavior], | 21700 behaviors: [SwarmingBehaviors.BotListBehavior], |
| 21509 | 21701 |
| 21510 properties: { | 21702 properties: { |
| 21511 | 21703 |
| 21512 columns: { | 21704 _bots: { |
| 21513 type: Array, | 21705 type: Array, |
| 21514 }, | 21706 }, |
| 21515 // Should have a property "filter" which is a function. | 21707 |
| 21516 filter: { | 21708 _columns: { |
| 21517 type: Object, | 21709 type: Array, |
| 21518 }, | 21710 }, |
| 21519 | 21711 |
| 21520 plain_columns: { | 21712 _filter: { |
| 21521 type: Array, | 21713 type: Function, |
| 21522 computed: "_stripSpecial(columns.*)", | 21714 value: function() { |
| 21715 return true; |
| 21716 }, |
| 21523 }, | 21717 }, |
| 21524 | 21718 |
| 21525 // sort is an Object {name:String, direction:String}. | 21719 _filteredSortedBots: { |
| 21526 sort: { | 21720 type: Array, |
| 21527 type: Object, | 21721 computed: "_filterAndSort(_bots,_filter.*,_sort.*)" |
| 21528 }, | 21722 }, |
| 21529 | 21723 |
| 21530 verbose: { | 21724 _plain_columns: { |
| 21725 type: Array, |
| 21726 computed: "_stripSpecial(_columns.*)", |
| 21727 }, |
| 21728 |
| 21729 // _sort is an Object {name:String, direction:String}. |
| 21730 _sort: { |
| 21731 type: Object, |
| 21732 value: function() { |
| 21733 return { |
| 21734 name: "id", |
| 21735 direction: "asc", |
| 21736 }; |
| 21737 } |
| 21738 }, |
| 21739 |
| 21740 _verbose: { |
| 21531 type: Boolean, | 21741 type: Boolean, |
| 21532 } | 21742 } |
| 21533 }, | 21743 }, |
| 21534 | 21744 |
| 21535 observers: [ | |
| 21536 '_reRender(filter.*)', | |
| 21537 '_checkSorts(columns.*)' | |
| 21538 ], | |
| 21539 | |
| 21540 _botClass: function(bot) { | 21745 _botClass: function(bot) { |
| 21541 if (bot.is_dead) { | 21746 if (bot.is_dead) { |
| 21542 return "dead"; | 21747 return "dead"; |
| 21543 } | 21748 } |
| 21544 if (bot.quarantined) { | 21749 if (bot.quarantined) { |
| 21545 return "quarantined"; | 21750 return "quarantined"; |
| 21546 } | 21751 } |
| 21547 return ""; | 21752 return ""; |
| 21548 }, | 21753 }, |
| 21549 | 21754 |
| 21550 _botLink: function(id) { | 21755 _botLink: function(id) { |
| 21551 // TODO(kjlubick) Make this point to /newui/ when appropriate. | 21756 // TODO(kjlubick) Make this point to /newui/ when appropriate. |
| 21552 return "/restricted/bot/"+id; | 21757 return "/restricted/bot/"+id; |
| 21553 }, | 21758 }, |
| 21554 | 21759 |
| 21555 // _checkSorts makes sure that if a column has been removed, the related | |
| 21556 // sort is also removed. | |
| 21557 _checkSorts: function() { | |
| 21558 if (!this.sort) { | |
| 21559 return; | |
| 21560 } | |
| 21561 this._reRender(); | |
| 21562 }, | |
| 21563 | 21760 |
| 21564 _column: function(col, bot) { | 21761 _column: function(col, bot) { |
| 21565 return columnMap[col].bind(this)(bot); | 21762 return columnMap[col].bind(this)(bot); |
| 21566 }, | 21763 }, |
| 21567 | 21764 |
| 21568 _deviceColumn: function(col, device) { | 21765 _deviceColumn: function(col, device) { |
| 21569 if (col === "devices") { | 21766 if (col === "devices") { |
| 21570 var str = this._androidAlias(device); | 21767 var str = this._androidAlias(device); |
| 21571 if (device.okay) { | 21768 if (device.okay) { |
| 21572 str = this._applyAlias(this._deviceType(device), str); | 21769 str = this._applyAlias(this._deviceType(device), str); |
| 21573 } | 21770 } |
| 21574 str += " S/N:"; | 21771 str += " S/N:"; |
| 21575 str += device.serial; | 21772 str += device.serial; |
| 21576 return str; | 21773 return str; |
| 21577 } | 21774 } |
| 21578 if (col === "status") { | 21775 if (col === "status") { |
| 21579 return device.state; | 21776 return device.state; |
| 21580 } | 21777 } |
| 21581 return ""; | 21778 return ""; |
| 21582 }, | 21779 }, |
| 21583 | 21780 |
| 21584 _deviceClass: function(device) { | 21781 _deviceClass: function(device) { |
| 21585 if (!device.okay) { | 21782 if (!device.okay) { |
| 21586 return "bad-device"; | 21783 return "bad-device"; |
| 21587 } | 21784 } |
| 21588 return ""; | 21785 return ""; |
| 21589 }, | 21786 }, |
| 21590 | 21787 |
| 21591 _filterBotTable: function(bot) { | 21788 _filterAndSort: function(a,b,c) { |
| 21592 if (!this.filter || !this.filter.filter) { | 21789 // We intentionally sort this._bots (and not a copy) to allow users to |
| 21593 return true; | 21790 // "chain" sorts, that is, sort by one thing and then another, and |
| 21791 // have both orderings properly impact the list. |
| 21792 swarming.stableSort(this._bots, this._sortBotTable.bind(this)); |
| 21793 var bots = this._bots; |
| 21794 if (this._filter) { |
| 21795 bots = bots.filter(this._filter.bind(this)); |
| 21594 } | 21796 } |
| 21595 return this.filter.filter.bind(this)(bot); | 21797 |
| 21798 return bots; |
| 21596 }, | 21799 }, |
| 21597 | 21800 |
| 21598 _header: function(col){ | 21801 _header: function(col){ |
| 21599 return headerMap[col]; | 21802 return headerMap[col]; |
| 21600 }, | 21803 }, |
| 21601 | 21804 |
| 21602 _hide: function(col) { | 21805 _hide: function(col) { |
| 21603 return this.columns.indexOf(col) === -1; | 21806 return this._columns.indexOf(col) === -1; |
| 21604 }, | 21807 }, |
| 21605 | 21808 |
| 21606 _reRender: function(filter, sort) { | 21809 _reRender: function(filter, sort) { |
| 21607 this.$.bot_table.render(); | 21810 this.$.bot_table.render(); |
| 21608 }, | 21811 }, |
| 21609 | 21812 |
| 21610 _sortBotTable: function(botA, botB) { | 21813 _sortBotTable: function(botA, botB) { |
| 21611 if (!this.sort) { | 21814 if (!this._sort) { |
| 21612 return 0; | 21815 return 0; |
| 21613 } | 21816 } |
| 21614 var dir = 1; | 21817 var dir = 1; |
| 21615 if (this.sort.direction === "desc") { | 21818 if (this._sort.direction === "desc") { |
| 21616 dir = -1; | 21819 dir = -1; |
| 21617 } | 21820 } |
| 21618 var botACol = this._column(this.sort.name, botA); | 21821 var botACol = this._column(this._sort.name, botA); |
| 21619 var botBCol = this._column(this.sort.name, botB); | 21822 var botBCol = this._column(this._sort.name, botB); |
| 21620 | 21823 |
| 21621 return dir * swarming.naturalCompare(botACol, botBCol); | 21824 return dir * swarming.naturalCompare(botACol, botBCol); |
| 21622 }, | 21825 }, |
| 21623 | 21826 |
| 21624 sortChange: function(e) { | 21827 _sortChange: function(e) { |
| 21625 // The event we get from sort-toggle tells us the name of what needs | 21828 // The event we get from sort-toggle tells us the name of what needs |
| 21626 // to be sorting and how to sort it. | 21829 // to be sorting and how to sort it. |
| 21627 if (!(e && e.detail && e.detail.name)) { | 21830 if (!(e && e.detail && e.detail.name)) { |
| 21628 return; | 21831 return; |
| 21629 } | 21832 } |
| 21630 this.set("sort", e.detail); | 21833 // should trigger __filterAndSort |
| 21631 swarming.stableSort(this.bots, this._sortBotTable.bind(this)); | 21834 this.set("_sort", e.detail); |
| 21632 this._reRender(); | |
| 21633 }, | 21835 }, |
| 21634 | 21836 |
| 21635 // _stripSpecial removes the special columns and sorts the remaining | 21837 // _stripSpecial removes the special columns and sorts the remaining |
| 21636 // columns so they always appear in the same order, regardless of | 21838 // columns so they always appear in the same order, regardless of |
| 21637 // the order they are added. | 21839 // the order they are added. |
| 21638 _stripSpecial: function(){ | 21840 _stripSpecial: function(){ |
| 21639 return this.columns.filter(function(c){ | 21841 return this._columns.filter(function(c){ |
| 21640 return special_columns.indexOf(c) === -1; | 21842 return special_columns.indexOf(c) === -1; |
| 21641 }).sort(); | 21843 }).sort(); |
| 21642 }, | 21844 }, |
| 21643 | 21845 |
| 21644 _taskLink: function(data) { | 21846 _taskLink: function(data) { |
| 21645 if (data && data.task_id) { | 21847 if (data && data.task_id) { |
| 21646 return "/user/task/" + data.task_id; | 21848 return "/user/task/" + data.task_id; |
| 21647 } | 21849 } |
| 21648 return undefined; | 21850 return undefined; |
| 21649 } | 21851 } |
| 21650 | 21852 |
| 21651 }); | 21853 }); |
| 21652 })(); | 21854 })(); |
| 21653 </script> | 21855 </script> |
| 21654 </dom-module></div></body></html> | 21856 </dom-module></div></body></html> |
| OLD | NEW |