Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(277)

Side by Side Diff: appengine/swarming/elements/res/imp/botlist/bot-list.html

Issue 2359993002: Medium sized improvements to bot-list and task-list (Closed) Base URL: git@github.com:luci/luci-py@master
Patch Set: condense loop Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 <!-- 1 <!--
2 Copyright 2016 The LUCI Authors. All rights reserved. 2 Copyright 2016 The LUCI Authors. All rights reserved.
3 Use of this source code is governed under the Apache License, Version 2.0 3 Use of this source code is governed under the Apache License, Version 2.0
4 that can be found in the LICENSE file. 4 that can be found in the LICENSE file.
5 5
6 This in an HTML Import-able file that contains the definition 6 This in an HTML Import-able file that contains the definition
7 of the following elements: 7 of the following elements:
8 8
9 <bot-list> 9 <bot-list>
10 10
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 } 49 }
50 .dead { 50 .dead {
51 background-color: #cccccc; 51 background-color: #cccccc;
52 } 52 }
53 .bot-list th > span { 53 .bot-list th > span {
54 /* Leave space for sort-toggle*/ 54 /* Leave space for sort-toggle*/
55 padding-right: 30px; 55 padding-right: 30px;
56 } 56 }
57 </style> 57 </style>
58 58
59 <url-param name="sort" 59 <url-param name="s"
60 value="{{_sortstr}}" 60 value="{{_sortstr}}"
61 default_value="id:asc"> 61 default_value="id:asc">
62 </url-param> 62 </url-param>
63 63
64 <swarming-app 64 <swarming-app
65 client_id="[[client_id]]" 65 client_id="[[client_id]]"
66 auth_headers="{{_auth_headers}}" 66 auth_headers="{{_auth_headers}}"
67 signed_in="{{_signed_in}}" 67 signed_in="{{_signed_in}}"
68 68
69 busy="[[_busy]]" 69 busy="[[_busy]]"
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 </template> <!--bot-table repeat--> 205 </template> <!--bot-table repeat-->
206 </tbody> 206 </tbody>
207 </table> 207 </table>
208 </div> 208 </div>
209 209
210 </swarming-app> 210 </swarming-app>
211 211
212 </template> 212 </template>
213 <script> 213 <script>
214 (function(){ 214 (function(){
215 var UNKNOWN = "unknown";
215 // see dynamic-table for more information on specialColumns, headerMap, 216 // see dynamic-table for more information on specialColumns, headerMap,
216 // columnMap, and specialSort 217 // columnMap, and specialSort
217 var specialColumns = ["id", "task"]; 218 var specialColumns = ["id", "task"];
218 219
219 var headerMap = { 220 var headerMap = {
220 // "id" and "task" are special, so they don't go here. They have their 221 // "id" and "task" are special, so they don't go here. They have their
221 // headers hard-coded above. 222 // headers hard-coded above.
222 "android_devices": "Android Devices", 223 "android_devices": "Android Devices",
223 "cores": "Cores", 224 "cores": "Cores",
224 "cpu": "CPU", 225 "cpu": "CPU",
225 "device": "Non-android Device", 226 "device": "Non-android Device",
226 "device_os": "Device OS", 227 "device_os": "Device OS",
227 "device_type": "Device Type", 228 "device_type": "Device Type",
228 "disk_space": "Free Space (MB)", 229 "disk_space": "Free Space (MB)",
229 "gpu": "GPU", 230 "gpu": "GPU",
230 "os": "OS", 231 "os": "OS",
231 "pool": "Pool", 232 "pool": "Pool",
232 "status": "Status", 233 "status": "Status",
233 "xcode_version": "XCode Version", 234 "xcode_version": "XCode Version",
235 "battery_health": "Battery Health",
236 "battery_level": "Battery Level (%)",
237 "battery_status": "Battery Status",
238 "battery_temperature": "Battery Temp (°C)",
239 "battery_voltage": "Battery Voltage (mV)",
240 "bot_temperature": "Bot Temp (°C)",
241 "device_temperature": "Device Temp (°C)",
234 }; 242 };
235 243
236 var columnMap = { 244 var columnMap = {
237 android_devices: function(bot) { 245 android_devices: function(bot) {
238 var devs = this._attribute(bot, "android_devices", "0"); 246 var devs = this._attribute(bot, "android_devices", "0");
239 if (this._verbose) { 247 if (this._verbose) {
240 return devs.join(" | ") + " devices available"; 248 return devs.join(" | ") + " devices available";
241 } 249 }
242 // max() works on strings as long as they can be coerced to Number. 250 // max() works on strings as long as they can be coerced to Number.
243 return Math.max(...devs) + " devices available"; 251 return Math.max(...devs) + " devices available";
244 }, 252 },
253 battery_health: function(){
254 return "";
255 },
256 battery_level: function(){
257 return "";
258 },
259 battery_status: function(){
260 return "";
261 },
262 battery_temperature: function(){
263 return "";
264 },
265 battery_voltage: function(){
266 return "";
267 },
268 bot_temperature: function(bot){
269 if (this._verbose) {
270 return bot.state.temp.zones || UNKNOWN;
271 }
272 return bot.state.temp.average || UNKNOWN;
273 },
274 device_temperature: function(){
275 return "";
276 },
245 disk_space: function(bot) { 277 disk_space: function(bot) {
246 var aliased = []; 278 var aliased = [];
247 bot.disks.forEach(function(disk){ 279 bot.disks.forEach(function(disk){
248 var alias = sk.human.bytes(disk.mb, swarming.MB); 280 var alias = sk.human.bytes(disk.mb, swarming.MB);
249 aliased.push(swarming.alias.apply(disk.mb, disk.id + " "+ alias)); 281 aliased.push(swarming.alias.apply(disk.mb, disk.id + " "+ alias));
250 }.bind(this)); 282 }.bind(this));
251 if (this._verbose) { 283 if (this._verbose) {
252 return aliased.join(" | "); 284 return aliased.join(" | ");
253 } 285 }
254 return aliased[0]; 286 return aliased[0];
255 }, 287 },
288
289 external_ip: function(bot) {
290 return bot.external_ip || "none";
291 },
292 first_seen: function(bot) {
293 return sk.human.localeTime(bot.first_seen_ts)
294 },
256 id: function(bot) { 295 id: function(bot) {
257 return bot.bot_id; 296 return bot.bot_id;
258 }, 297 },
298 last_seen: function(bot) {
299 if (this._verbose) {
300 return sk.human.localeTime(bot.last_seen_ts);
301 }
302 return this._timeDiffApprox(bot.last_seen_ts) + " ago";
303 },
259 status: function(bot) { 304 status: function(bot) {
260 // If a bot is both dead and quarantined, show the deadness over the 305 // If a bot is both dead and quarantined, show the deadness over the
261 // quarentinedness. 306 // quarentinedness.
262 if (bot.is_dead) { 307 if (bot.is_dead) {
263 return "Dead. Last seen " + sk.human.diffDate(bot.last_seen_ts) + 308 return "Dead. Last seen " + sk.human.diffDate(bot.last_seen_ts) +
264 " ago"; 309 " ago";
265 } 310 }
266 if (bot.quarantined) { 311 if (bot.quarantined) {
267 var msg = this._state(bot, "quarantined")[0]; 312 var msg = this._state(bot, "quarantined")[0];
268 // Sometimes, the quarantined message is actually in "error". This 313 // Sometimes, the quarantined message is actually in "error". This
269 // happens when the bot code has thrown an exception. 314 // happens when the bot code has thrown an exception.
270 if (msg === "unknown" || msg === "true" || msg === true) { 315 if (msg === UNKNOWN || msg === "true" || msg === true) {
271 msg = this._attribute(bot, "error"); 316 msg = this._attribute(bot, "error");
272 } 317 }
273 return "Quarantined: " + msg; 318 return "Quarantined: " + msg;
274 } 319 }
275 return "Alive"; 320 return "Alive";
276 }, 321 },
277 task: function(bot){ 322 task: function(bot) {
278 return this._taskId(bot); 323 return this._taskId(bot);
279 }, 324 },
325 version: function(bot) {
326 var v = bot.version || UNKNOWN
327 return v.substring(0, 10);
328 }
280 }; 329 };
281 330
282 var deviceColumnMap = { 331 var deviceColumnMap = {
283 android_devices: function(device) { 332 android_devices: function(device) {
284 var str = this._androidAliasDevice(device); 333 var str = this._androidAliasDevice(device);
285 if (device.okay) { 334 if (device.okay) {
286 str = swarming.alias.apply(this._deviceType(device), str); 335 str = swarming.alias.apply(this._deviceType(device), str);
287 } 336 }
288 str += " S/N:"; 337 str += " S/N:";
289 str += device.serial; 338 str += device.serial;
290 return str; 339 return str;
291 }, 340 },
341 battery_health: function(device){
342 var h = (device.battery && device.battery.health) || UNKNOWN;
343 return swarming.alias.apply(h, "battery_health");
344 },
345 battery_level: function(device){
346 return (device.battery && device.battery.level) || UNKNOWN;
347 },
348 battery_status: function(device){
349 var s = (device.battery && device.battery.status) || UNKNOWN;
350 return swarming.alias.apply(s, "battery_status");
351 },
352 battery_temperature: function(device){
353 // Battery temps are in tenths of degrees C - convert to more human rang e.
354 return (device.battery && device.battery.temperature / 10) || UNKNOWN
355 },
356 battery_voltage: function(device){
357 return (device.battery && device.battery.voltage) || UNKNOWN;
358 },
359 device_temperature: function(device){
360 if (this._verbose) {
361 return device.temp.zones || UNKNOWN;
362 }
363 return device.temp.average || UNKNOWN;
364 },
292 device_os: function(device) { 365 device_os: function(device) {
293 if (device.build) { 366 if (device.build) {
294 return device.build["build.id"]; 367 return device.build["build.id"];
295 } 368 }
296 return "unknown"; 369 return UNKNOWN;
297 }, 370 },
298 status: function(device) { 371 status: function(device) {
299 return device.state; 372 return device.state;
300 } 373 }
301 } 374 }
302 375
376
377 function deviceAverage(col) {
378 return function(dir, botA, botB) {
379 // sort by average of all devices or 0 if no devices.
380 var avgA = 0;
381 var avgB = 0;
382 var devsA = this._devices(botA);
383 devsA.forEach(function(device) {
384 var v = deviceColumnMap[col](device);
385 v = parseFloat(swarming.alias.unapply(v)) || 0;
386 avgA += v / devsA.length;
387 }.bind(this));
388 var devsB = this._devices(botB);
389 devsB.forEach(function(device) {
390 var v = deviceColumnMap[col](device);
391 v = parseFloat(swarming.alias.unapply(v)) || 0;
392 avgB += v / devsB.length;
393 }.bind(this));
394 return dir * swarming.naturalCompare(avgA, avgB);
395 };
396 }
397
303 var specialSort = { 398 var specialSort = {
304 android_devices: function(dir, botA, botB) { 399 android_devices: function(dir, botA, botB) {
305 // We sort on the number of attached devices. Note that this 400 // We sort on the number of attached devices. Note that this
306 // may not be the same as android_devices, because _devices().length 401 // may not be the same as android_devices, because _devices().length
307 // counts all devices plugged into the bot, whereas android_devices 402 // counts all devices plugged into the bot, whereas android_devices
308 // counts just devices ready for work. 403 // counts just devices ready for work.
309 var botACol = this._devices(botA).length; 404 var botACol = this._devices(botA).length;
310 var botBCol = this._devices(botB).length; 405 var botBCol = this._devices(botB).length;
311 return dir * swarming.naturalCompare(botACol, botBCol); 406 return dir * swarming.naturalCompare(botACol, botBCol);
312 }, 407 },
408
409 battery_health: deviceAverage("battery_health"),
410 battery_level: deviceAverage("battery_level"),
411 battery_status: deviceAverage("battery_status"),
412 battery_temperature: deviceAverage("battery_temperature"),
413 battery_voltage: deviceAverage("battery_voltage"),
414 device_temperature: deviceAverage("device_temperature"),
415
416 bot_temperature: function(dir, botA, botB) {
417 // Sort by average temperature.
418 var botACol = botA.state.temp.average || 0;
419 var botBCol = botB.state.temp.average || 0;
420 return dir * swarming.naturalCompare(botACol, botBCol);
421 },
313 disk_space: function(dir, botA, botB) { 422 disk_space: function(dir, botA, botB) {
314 // We sort based on the raw number of MB of the first disk. 423 // We sort based on the raw number of MB of the first disk.
315 var botACol = botA.disks[0].mb; 424 var botACol = botA.disks[0].mb;
316 var botBCol = botB.disks[0].mb;; 425 var botBCol = botB.disks[0].mb;
317 return dir * swarming.naturalCompare(botACol, botBCol); 426 return dir * swarming.naturalCompare(botACol, botBCol);
318 }, 427 },
428 first_seen: function(dir, botA, botB) {
429 var botACol = botA.first_seen_ts;
430 var botBCol = botB.first_seen_ts;
431 return dir * swarming.naturalCompare(botACol, botBCol)
432 },
433 last_seen: function(dir, botA, botB) {
434 var botACol = botA.last_seen_ts;
435 var botBCol = botB.last_seen_ts;
436 return dir * swarming.naturalCompare(botACol, botBCol)
437 }
319 }; 438 };
320 439
321 Polymer({ 440 Polymer({
322 is: 'bot-list', 441 is: 'bot-list',
323 442
324 // The order behaviors are applied in matters - later ones overwrite 443 // The order behaviors are applied in matters - later ones overwrite
325 // attributes of earlier ones 444 // attributes of earlier ones
326 behaviors: [ 445 behaviors: [
327 SwarmingBehaviors.BotListBehavior, 446 SwarmingBehaviors.BotListBehavior,
328 SwarmingBehaviors.DynamicTableBehavior, 447 SwarmingBehaviors.DynamicTableBehavior,
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 if (!device.okay) { 507 if (!device.okay) {
389 return "bad-device"; 508 return "bad-device";
390 } 509 }
391 return ""; 510 return "";
392 }, 511 },
393 512
394 }); 513 });
395 })(); 514 })();
396 </script> 515 </script>
397 </dom-module> 516 </dom-module>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698