| 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: 1px 5px; |
| 21351 font-family: sans-serif; |
| 21352 } |
| 21353 .header { |
| 21354 font-size: 1.2em; |
| 21355 font-weight: bold; |
| 21356 } |
| 21357 ul { |
| 21358 list-style-type: none; |
| 21359 } |
| 21360 </style> |
| 21361 |
| 21362 <div class="header">Fleet</div> |
| 21363 |
| 21364 <ul> |
| 21365 <li><a href="/newui/botlist?alive">Bots Alive</a>: [[fleet.alive]]</li> |
| 21366 <li><a href="/newui/botlist?busy">Bots Busy</a>: [[fleet.busy]]</li> |
| 21367 <li><a href="/newui/botlist?idle">Bots Idle</a>: [[fleet.idle]]</li> |
| 21368 <li><a href="/newui/botlist?dead">Bots Dead</a>: [[fleet.dead]]</li> |
| 21369 <li><a href="/newui/botlist?quaren">Bots Quarantined</a>: [[fleet.quaranti
ned]]</li> |
| 21370 </ul> |
| 21371 |
| 21372 <div class="header">Currently Showing</div> |
| 21373 <ul> |
| 21374 <li><a href="/newui/botlist?alive2">Bots Alive</a>: [[_currently_showing.a
live]]</li> |
| 21375 <li><a href="/newui/botlist?busy2">Bots Busy</a>: [[_currently_showing.bus
y]]</li> |
| 21376 <li><a href="/newui/botlist?idle2">Bots Idle</a>: [[_currently_showing.idl
e]]</li> |
| 21377 <li><a href="/newui/botlist?dead2">Bots Dead</a>: [[_currently_showing.dea
d]]</li> |
| 21378 <li><a href="/newui/botlist?quaren2">Bots Quarantined</a>: [[_currently_sh
owing.quarantined]]</li> |
| 21379 </ul> |
| 21380 |
| 21381 </template> |
| 21382 <script> |
| 21383 Polymer({ |
| 21384 is: 'bot-list-summary', |
| 21385 |
| 21386 behaviors: [SwarmingBehaviors.BotListBehavior], |
| 21387 |
| 21388 properties: { |
| 21389 filtered_bots: { |
| 21390 type: Array, |
| 21391 }, |
| 21392 fleet: { |
| 21393 type: Object, |
| 21394 }, |
| 21395 |
| 21396 _currently_showing: { |
| 21397 type: Object, |
| 21398 value: function() { |
| 21399 return { |
| 21400 alive: -1, |
| 21401 busy: -1, |
| 21402 idle: -1, |
| 21403 dead: -1, |
| 21404 quarantined: -1, |
| 21405 }; |
| 21406 }, |
| 21407 }, |
| 21408 }, |
| 21409 |
| 21410 // Do this because Array changes in Polymer don't always trigger normal |
| 21411 // property observers |
| 21412 observers: ["_recount(filtered_bots.*)"], |
| 21413 |
| 21414 _recount: function() { |
| 21415 var curr = { |
| 21416 alive: 0, |
| 21417 busy: 0, |
| 21418 idle: 0, |
| 21419 dead: 0, |
| 21420 quarantined: 0, |
| 21421 }; |
| 21422 if (!this.filtered_bots) { |
| 21423 return curr; |
| 21424 } |
| 21425 this.filtered_bots.forEach(function(bot) { |
| 21426 if (this._taskId(bot) === "idle") { |
| 21427 curr.idle++; |
| 21428 } else { |
| 21429 curr.busy++; |
| 21430 } |
| 21431 if (bot.quarantined) { |
| 21432 curr.quarantined++; |
| 21433 } |
| 21434 if (bot.is_dead) { |
| 21435 curr.dead++; |
| 21436 } else { |
| 21437 curr.alive++; |
| 21438 } |
| 21439 }.bind(this)); |
| 21440 this.set("_currently_showing", curr); |
| 21441 } |
| 21442 }); |
| 21443 </script> |
| 21300 </dom-module><dom-module id="bot-list" assetpath="/res/imp/botlist/"> | 21444 </dom-module><dom-module id="bot-list" assetpath="/res/imp/botlist/"> |
| 21301 <template> | 21445 <template> |
| 21302 <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-
style"> | 21446 <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-
style"> |
| 21303 bot-filters { | 21447 bot-filters, bot-list-summary { |
| 21304 margin-bottom: 5px; | 21448 margin-bottom: 5px; |
| 21449 margin-right: 5px; |
| 21305 } | 21450 } |
| 21306 .bot { | 21451 .bot { |
| 21307 margin:5px; | 21452 margin:5px; |
| 21308 max-width:400px; | 21453 max-width:400px; |
| 21309 min-height:100px; | 21454 min-height:100px; |
| 21310 min-width:300px; | 21455 min-width:300px; |
| 21311 } | 21456 } |
| 21312 table { | 21457 table { |
| 21313 border-collapse: collapse; | 21458 border-collapse: collapse; |
| 21314 margin-left: 5px; | 21459 margin-left: 5px; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 21332 position: absolute; | 21477 position: absolute; |
| 21333 right: 0; | 21478 right: 0; |
| 21334 top: 0.4em; | 21479 top: 0.4em; |
| 21335 } | 21480 } |
| 21336 .bot-list th > span { | 21481 .bot-list th > span { |
| 21337 /* Leave space for sort-toggle*/ | 21482 /* Leave space for sort-toggle*/ |
| 21338 padding-right: 30px; | 21483 padding-right: 30px; |
| 21339 } | 21484 } |
| 21340 </style> | 21485 </style> |
| 21341 | 21486 |
| 21342 <swarming-app auth_headers="{{auth_headers}}" busy="[[busy]]" name="Swarming
Bot List"> | 21487 <swarming-app auth_headers="{{auth_headers}}" signed_in="{{signed_in}}" busy
="[[busy]]" name="Swarming Bot List"> |
| 21343 | 21488 |
| 21344 <bot-filters primary_map="[[primary_map]]" primary_arr="[[primary_arr]]" c
olumns="{{columns}}" filter="{{filter}}" verbose="{{verbose}}"> | 21489 <h2 hidden$="[[signed_in]]">You must sign in to see anything useful.</h2> |
| 21345 </bot-filters> | |
| 21346 | 21490 |
| 21347 <bot-list-data auth_headers="[[auth_headers]]" bots="{{bots}}" busy="{{bus
y}}" primary_map="{{primary_map}}" primary_arr="{{primary_arr}}"> | 21491 <div hidden$="[[_not(signed_in)]]"> |
| 21348 </bot-list-data> | |
| 21349 | 21492 |
| 21350 <table class="bot-list"> | 21493 <div class="horizontal layout"> |
| 21351 <thead on-sort_change="sortChange"> | 21494 |
| 21352 | 21495 <bot-filters primary_map="[[primary_map]]" primary_arr="[[primary_arr]
]" columns="{{columns}}" filter="{{filter}}" verbose="{{verbose}}"> |
| 21353 <tr><th> | 21496 </bot-filters> |
| 21354 <span>Bot Id</span> | 21497 |
| 21355 <sort-toggle name="id" current="[[sort]]"> | 21498 <bot-list-summary fleet="[[fleet]]" filtered_bots="[[filteredSortedBot
s]]"> |
| 21356 </sort-toggle> | 21499 </bot-list-summary> |
| 21357 </th> | 21500 |
| 21501 </div> |
| 21502 |
| 21503 <bot-list-data auth_headers="[[auth_headers]]" bots="{{bots}}" busy="{{b
usy}}" fleet="{{fleet}}" primary_map="{{primary_map}}" primary_arr="{{primary_ar
r}}"> |
| 21504 </bot-list-data> |
| 21505 |
| 21506 <table class="bot-list"> |
| 21507 <thead on-sort_change="sortChange"> |
| 21358 | 21508 |
| 21359 <th hidden$="[[_hide('task', columns.*)]]"> | 21509 <tr><th> |
| 21360 <span>Current Task</span> | 21510 <span>Bot Id</span> |
| 21361 <sort-toggle name="task" current="[[sort]]"> | 21511 <sort-toggle name="id" current="[[sort]]"> |
| 21362 </sort-toggle> | |
| 21363 </th> | |
| 21364 | |
| 21365 <template is="dom-repeat" items="[[plain_columns]]" as="c"> | |
| 21366 <th hidden$="[[_hide(c)]]"> | |
| 21367 <span>[[_header(c)]]</span> | |
| 21368 <sort-toggle name="[[c]]" current="[[sort]]"> | |
| 21369 </sort-toggle> | 21512 </sort-toggle> |
| 21370 </th> | 21513 </th> |
| 21371 </template> | 21514 |
| 21372 </tr></thead> | 21515 <th hidden$="[[_hide('task', columns.*)]]"> |
| 21373 <tbody> | 21516 <span>Current Task</span> |
| 21374 <template id="bot_table" is="dom-repeat" items="[[bots]]" as="bot" ini
tial-count="50" filter="_filterBotTable"> | 21517 <sort-toggle name="task" current="[[sort]]"> |
| 21518 </sort-toggle> |
| 21519 </th> |
| 21375 | 21520 |
| 21376 <tr class$="[[_botClass(bot)]]"> | 21521 <template is="dom-repeat" items="[[plain_columns]]" as="c"> |
| 21377 <td> | 21522 <th hidden$="[[_hide(c)]]"> |
| 21378 <a class="center" href$="[[_botLink(bot.bot_id)]]" target="_blan
k"> | 21523 <span>[[_header(c)]]</span> |
| 21379 [[bot.bot_id]] | 21524 <sort-toggle name="[[c]]" current="[[sort]]"> |
| 21380 </a> | 21525 </sort-toggle> |
| 21381 </td> | 21526 </th> |
| 21382 <td hidden$="[[_hide('task', columns.*)]]"> | 21527 </template> |
| 21383 <a href$="[[_taskLink(bot)]]">[[_taskId(bot)]]</a> | 21528 </tr></thead> |
| 21384 </td> | 21529 <tbody> |
| 21530 <template id="bot_table" is="dom-repeat" items="[[filteredSortedBots
]]" as="bot" initial-count="50"> |
| 21385 | 21531 |
| 21386 <template is="dom-repeat" items="[[plain_columns]]" as="c"> | 21532 <tr class$="[[_botClass(bot)]]"> |
| 21387 <td hidden$="[[_hide(c)]]"> | 21533 <td> |
| 21388 [[_column(c, bot, verbose)]] | 21534 <a class="center" href$="[[_botLink(bot.bot_id)]]" target="_bl
ank"> |
| 21535 [[bot.bot_id]] |
| 21536 </a> |
| 21389 </td> | 21537 </td> |
| 21390 </template> | 21538 <td hidden$="[[_hide('task', columns.*)]]"> |
| 21539 <a href$="[[_taskLink(bot)]]">[[_taskId(bot)]]</a> |
| 21540 </td> |
| 21391 | 21541 |
| 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"> | 21542 <template is="dom-repeat" items="[[plain_columns]]" as="c"> |
| 21398 <td hidden$="[[_hide(c)]]"> | 21543 <td hidden$="[[_hide(c)]]"> |
| 21399 [[_deviceColumn(c, device, verbose)]] | 21544 [[_column(c, bot, verbose)]] |
| 21400 </td> | 21545 </td> |
| 21401 </template> | 21546 </template> |
| 21547 |
| 21402 </tr> | 21548 </tr> |
| 21549 <template is="dom-repeat" items="[[_devices(bot)]]" as="device"> |
| 21550 <tr hidden$="[[_hide('devices', columns.*)]]" class$="[[_deviceC
lass(device)]]"> |
| 21551 <td></td> |
| 21552 <td hidden$="[[_hide('task', columns.*)]]"></td> |
| 21553 <template is="dom-repeat" items="[[plain_columns]]" as="c"> |
| 21554 <td hidden$="[[_hide(c)]]"> |
| 21555 [[_deviceColumn(c, device, verbose)]] |
| 21556 </td> |
| 21557 </template> |
| 21558 </tr> |
| 21559 </template> |
| 21403 </template> | 21560 </template> |
| 21404 </template> | 21561 </tbody> |
| 21405 </tbody> | 21562 </table> |
| 21406 </table> | 21563 </div> |
| 21407 | 21564 |
| 21408 </swarming-app> | 21565 </swarming-app> |
| 21409 | 21566 |
| 21410 </template> | 21567 </template> |
| 21411 <script> | 21568 <script> |
| 21412 (function(){ | 21569 (function(){ |
| 21413 var special_columns = ["id", "task"]; | 21570 var special_columns = ["id", "task"]; |
| 21414 | 21571 |
| 21415 var headerMap = { | 21572 var headerMap = { |
| 21416 // "id" and "task" are special, so they don't go here and have their | 21573 // "id" and "task" are special, so they don't go here and have their |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 21502 return this._taskId(bot); | 21659 return this._taskId(bot); |
| 21503 }, | 21660 }, |
| 21504 }; | 21661 }; |
| 21505 | 21662 |
| 21506 Polymer({ | 21663 Polymer({ |
| 21507 is: 'bot-list', | 21664 is: 'bot-list', |
| 21508 behaviors: [SwarmingBehaviors.BotListBehavior], | 21665 behaviors: [SwarmingBehaviors.BotListBehavior], |
| 21509 | 21666 |
| 21510 properties: { | 21667 properties: { |
| 21511 | 21668 |
| 21669 bots: { |
| 21670 type: Array, |
| 21671 }, |
| 21672 |
| 21512 columns: { | 21673 columns: { |
| 21513 type: Array, | 21674 type: Array, |
| 21514 }, | 21675 }, |
| 21515 // Should have a property "filter" which is a function. | 21676 |
| 21516 filter: { | 21677 filter: { |
| 21517 type: Object, | 21678 type: Function, |
| 21679 value: function() { |
| 21680 return true; |
| 21681 }, |
| 21682 }, |
| 21683 |
| 21684 filteredSortedBots: { |
| 21685 type: Array, |
| 21686 computed: "_filterAndSort(bots,filter.*,sort.*)" |
| 21518 }, | 21687 }, |
| 21519 | 21688 |
| 21520 plain_columns: { | 21689 plain_columns: { |
| 21521 type: Array, | 21690 type: Array, |
| 21522 computed: "_stripSpecial(columns.*)", | 21691 computed: "_stripSpecial(columns.*)", |
| 21523 }, | 21692 }, |
| 21524 | 21693 |
| 21525 // sort is an Object {name:String, direction:String}. | 21694 // sort is an Object {name:String, direction:String}. |
| 21526 sort: { | 21695 sort: { |
| 21527 type: Object, | 21696 type: Object, |
| 21697 value: function() { |
| 21698 return { |
| 21699 name: "id", |
| 21700 direction: "asc", |
| 21701 }; |
| 21702 } |
| 21528 }, | 21703 }, |
| 21529 | 21704 |
| 21530 verbose: { | 21705 verbose: { |
| 21531 type: Boolean, | 21706 type: Boolean, |
| 21532 } | 21707 } |
| 21533 }, | 21708 }, |
| 21534 | 21709 |
| 21535 observers: [ | |
| 21536 '_reRender(filter.*)', | |
| 21537 '_checkSorts(columns.*)' | |
| 21538 ], | |
| 21539 | |
| 21540 _botClass: function(bot) { | 21710 _botClass: function(bot) { |
| 21541 if (bot.is_dead) { | 21711 if (bot.is_dead) { |
| 21542 return "dead"; | 21712 return "dead"; |
| 21543 } | 21713 } |
| 21544 if (bot.quarantined) { | 21714 if (bot.quarantined) { |
| 21545 return "quarantined"; | 21715 return "quarantined"; |
| 21546 } | 21716 } |
| 21547 return ""; | 21717 return ""; |
| 21548 }, | 21718 }, |
| 21549 | 21719 |
| 21550 _botLink: function(id) { | 21720 _botLink: function(id) { |
| 21551 // TODO(kjlubick) Make this point to /newui/ when appropriate. | 21721 // TODO(kjlubick) Make this point to /newui/ when appropriate. |
| 21552 return "/restricted/bot/"+id; | 21722 return "/restricted/bot/"+id; |
| 21553 }, | 21723 }, |
| 21554 | 21724 |
| 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 | 21725 |
| 21564 _column: function(col, bot) { | 21726 _column: function(col, bot) { |
| 21565 return columnMap[col].bind(this)(bot); | 21727 return columnMap[col].bind(this)(bot); |
| 21566 }, | 21728 }, |
| 21567 | 21729 |
| 21568 _deviceColumn: function(col, device) { | 21730 _deviceColumn: function(col, device) { |
| 21569 if (col === "devices") { | 21731 if (col === "devices") { |
| 21570 var str = this._androidAlias(device); | 21732 var str = this._androidAlias(device); |
| 21571 if (device.okay) { | 21733 if (device.okay) { |
| 21572 str = this._applyAlias(this._deviceType(device), str); | 21734 str = this._applyAlias(this._deviceType(device), str); |
| 21573 } | 21735 } |
| 21574 str += " S/N:"; | 21736 str += " S/N:"; |
| 21575 str += device.serial; | 21737 str += device.serial; |
| 21576 return str; | 21738 return str; |
| 21577 } | 21739 } |
| 21578 if (col === "status") { | 21740 if (col === "status") { |
| 21579 return device.state; | 21741 return device.state; |
| 21580 } | 21742 } |
| 21581 return ""; | 21743 return ""; |
| 21582 }, | 21744 }, |
| 21583 | 21745 |
| 21584 _deviceClass: function(device) { | 21746 _deviceClass: function(device) { |
| 21585 if (!device.okay) { | 21747 if (!device.okay) { |
| 21586 return "bad-device"; | 21748 return "bad-device"; |
| 21587 } | 21749 } |
| 21588 return ""; | 21750 return ""; |
| 21589 }, | 21751 }, |
| 21590 | 21752 |
| 21591 _filterBotTable: function(bot) { | 21753 _filterAndSort: function(a,b,c) { |
| 21592 if (!this.filter || !this.filter.filter) { | 21754 // We intentionally sort this.bots (and not a copy) to allow users to |
| 21593 return true; | 21755 // "chain" sorts, that is, sort by one thing and then another, and |
| 21756 // have both orderings properly impact the list. |
| 21757 swarming.stableSort(this.bots, this._sortBotTable.bind(this)); |
| 21758 var bots = this.bots; |
| 21759 if (this.filter) { |
| 21760 bots = bots.filter(this.filter.bind(this)); |
| 21594 } | 21761 } |
| 21595 return this.filter.filter.bind(this)(bot); | 21762 |
| 21763 return bots; |
| 21596 }, | 21764 }, |
| 21597 | 21765 |
| 21598 _header: function(col){ | 21766 _header: function(col){ |
| 21599 return headerMap[col]; | 21767 return headerMap[col]; |
| 21600 }, | 21768 }, |
| 21601 | 21769 |
| 21602 _hide: function(col) { | 21770 _hide: function(col) { |
| 21603 return this.columns.indexOf(col) === -1; | 21771 return this.columns.indexOf(col) === -1; |
| 21604 }, | 21772 }, |
| 21605 | 21773 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 21620 | 21788 |
| 21621 return dir * swarming.naturalCompare(botACol, botBCol); | 21789 return dir * swarming.naturalCompare(botACol, botBCol); |
| 21622 }, | 21790 }, |
| 21623 | 21791 |
| 21624 sortChange: function(e) { | 21792 sortChange: function(e) { |
| 21625 // The event we get from sort-toggle tells us the name of what needs | 21793 // The event we get from sort-toggle tells us the name of what needs |
| 21626 // to be sorting and how to sort it. | 21794 // to be sorting and how to sort it. |
| 21627 if (!(e && e.detail && e.detail.name)) { | 21795 if (!(e && e.detail && e.detail.name)) { |
| 21628 return; | 21796 return; |
| 21629 } | 21797 } |
| 21798 // should trigger __filterAndSort |
| 21630 this.set("sort", e.detail); | 21799 this.set("sort", e.detail); |
| 21631 swarming.stableSort(this.bots, this._sortBotTable.bind(this)); | |
| 21632 this._reRender(); | |
| 21633 }, | 21800 }, |
| 21634 | 21801 |
| 21635 // _stripSpecial removes the special columns and sorts the remaining | 21802 // _stripSpecial removes the special columns and sorts the remaining |
| 21636 // columns so they always appear in the same order, regardless of | 21803 // columns so they always appear in the same order, regardless of |
| 21637 // the order they are added. | 21804 // the order they are added. |
| 21638 _stripSpecial: function(){ | 21805 _stripSpecial: function(){ |
| 21639 return this.columns.filter(function(c){ | 21806 return this.columns.filter(function(c){ |
| 21640 return special_columns.indexOf(c) === -1; | 21807 return special_columns.indexOf(c) === -1; |
| 21641 }).sort(); | 21808 }).sort(); |
| 21642 }, | 21809 }, |
| 21643 | 21810 |
| 21644 _taskLink: function(data) { | 21811 _taskLink: function(data) { |
| 21645 if (data && data.task_id) { | 21812 if (data && data.task_id) { |
| 21646 return "/user/task/" + data.task_id; | 21813 return "/user/task/" + data.task_id; |
| 21647 } | 21814 } |
| 21648 return undefined; | 21815 return undefined; |
| 21649 } | 21816 } |
| 21650 | 21817 |
| 21651 }); | 21818 }); |
| 21652 })(); | 21819 })(); |
| 21653 </script> | 21820 </script> |
| 21654 </dom-module></div></body></html> | 21821 </dom-module></div></body></html> |
| OLD | NEW |