| OLD | NEW |
| 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 |
| 11 bot-list creats a dynamic table for viewing swarming bots. Columns can be | 11 bot-list creats a dynamic table for viewing swarming bots. Columns can be |
| 12 dynamically filtered and it supports client-side filtering. | 12 dynamically filtered and it supports client-side filtering. |
| 13 | 13 |
| 14 This is a top-level element. | 14 This is a top-level element. |
| 15 | 15 |
| 16 Properties: | 16 Properties: |
| 17 client_id: String, Oauth 2.0 client id. It will be set by server-side | 17 client_id: String, Oauth 2.0 client id. It will be set by server-side |
| 18 template evaluation. | 18 template evaluation. |
| 19 | 19 |
| 20 Methods: | 20 Methods: |
| 21 None. | 21 None. |
| 22 | 22 |
| 23 Events: | 23 Events: |
| 24 None. | 24 None. |
| 25 --> | 25 --> |
| 26 | 26 |
| 27 <link rel="import" href="/res/imp/bower_components/iron-flex-layout/iron-flex-la
yout-classes.html"> | 27 <link rel="import" href="/res/imp/bower_components/iron-flex-layout/iron-flex-la
yout-classes.html"> |
| 28 <link rel="import" href="/res/imp/bower_components/polymer/polymer.html"> | 28 <link rel="import" href="/res/imp/bower_components/polymer/polymer.html"> |
| 29 | 29 |
| 30 <link rel="import" href="/res/imp/common/dynamic-table.html"> | 30 <link rel="import" href="/res/imp/common/dynamic-table-behavior.html"> |
| 31 <link rel="import" href="/res/imp/common/sort-toggle.html"> | 31 <link rel="import" href="/res/imp/common/sort-toggle.html"> |
| 32 <link rel="import" href="/res/imp/common/swarming-app.html"> | 32 <link rel="import" href="/res/imp/common/swarming-app.html"> |
| 33 <link rel="import" href="/res/imp/common/url-param.html"> | 33 <link rel="import" href="/res/imp/common/url-param.html"> |
| 34 | 34 |
| 35 <link rel="import" href="bot-filters.html"> | 35 <link rel="import" href="bot-filters.html"> |
| 36 <link rel="import" href="bot-list-data.html"> | 36 <link rel="import" href="bot-list-data.html"> |
| 37 <link rel="import" href="bot-list-shared.html"> | 37 <link rel="import" href="bot-list-shared-behavior.html"> |
| 38 <link rel="import" href="bot-list-summary.html"> | 38 <link rel="import" href="bot-list-summary.html"> |
| 39 | 39 |
| 40 <dom-module id="bot-list"> | 40 <dom-module id="bot-list"> |
| 41 <template> | 41 <template> |
| 42 <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-
style dynamic-table-style"> | 42 <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-
style dynamic-table-style"> |
| 43 bot-filters, bot-list-summary { | 43 bot-filters, bot-list-summary { |
| 44 margin-bottom: 8px; | 44 margin-bottom: 8px; |
| 45 margin-right: 10px; | 45 margin-right: 10px; |
| 46 } | 46 } |
| 47 .quarantined, .bad-device { | 47 .quarantined, .bad-device { |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 "device_type": "Device Type", | 227 "device_type": "Device Type", |
| 228 "disk_space": "Free Space (MB)", | 228 "disk_space": "Free Space (MB)", |
| 229 "gpu": "GPU", | 229 "gpu": "GPU", |
| 230 "os": "OS", | 230 "os": "OS", |
| 231 "pool": "Pool", | 231 "pool": "Pool", |
| 232 "status": "Status", | 232 "status": "Status", |
| 233 "xcode_version": "XCode Version", | 233 "xcode_version": "XCode Version", |
| 234 }; | 234 }; |
| 235 | 235 |
| 236 var columnMap = { | 236 var columnMap = { |
| 237 android_devices: function(bot) { | |
| 238 var devs = this._attribute(bot, "android_devices", "0"); | |
| 239 if (this._verbose) { | |
| 240 return devs.join(" | ") + " devices available"; | |
| 241 } | |
| 242 // max() works on strings as long as they can be coerced to Number. | |
| 243 return Math.max(...devs) + " devices available"; | |
| 244 }, | |
| 245 device_type: function(bot) { | |
| 246 var dt = this._attribute(bot, "device_type", "none"); | |
| 247 dt = dt[0]; | |
| 248 var alias = this._androidAlias(dt); | |
| 249 if (alias === "unknown") { | |
| 250 return dt; | |
| 251 } | |
| 252 return this._applyAlias(dt, alias); | |
| 253 }, | |
| 254 disk_space: function(bot) { | 237 disk_space: function(bot) { |
| 255 var aliased = []; | 238 var aliased = []; |
| 256 bot.disks.forEach(function(disk){ | 239 bot.disks.forEach(function(disk){ |
| 257 var alias = sk.human.bytes(disk.mb, swarming.MB); | 240 var alias = sk.human.bytes(disk.mb, swarming.MB); |
| 258 aliased.push(this._applyAlias(disk.mb, disk.id + " "+ alias)); | 241 aliased.push(swarming.alias.apply(disk.mb, disk.id + " "+ alias)); |
| 259 }.bind(this)); | 242 }.bind(this)); |
| 260 if (this._verbose) { | 243 if (this._verbose) { |
| 261 return aliased.join(" | "); | 244 return aliased.join(" | "); |
| 262 } | 245 } |
| 263 return aliased[0]; | 246 return aliased[0]; |
| 264 }, | 247 }, |
| 265 gpu: function(bot){ | |
| 266 var gpus = this._attribute(bot, "gpu", "none") | |
| 267 var verbose = [] | |
| 268 var named = []; | |
| 269 // non-verbose mode has only the top level GPU info "e.g. NVidia" | |
| 270 // which is found by looking for gpu ids w/o a colon. | |
| 271 gpus.forEach(function(g){ | |
| 272 var alias = this._gpuAlias(g); | |
| 273 if (alias === "unknown") { | |
| 274 verbose.push(g); | |
| 275 if (g.indexOf(":") === -1) { | |
| 276 named.push(g); | |
| 277 } | |
| 278 return; | |
| 279 } | |
| 280 verbose.push(this._applyAlias(g, alias)); | |
| 281 if (g.indexOf(":") === -1) { | |
| 282 named.push(this._applyAlias(g, alias)); | |
| 283 } | |
| 284 }.bind(this)) | |
| 285 if (this._verbose) { | |
| 286 return verbose.join(" | "); | |
| 287 } | |
| 288 return named.join(" | "); | |
| 289 }, | |
| 290 id: function(bot) { | 248 id: function(bot) { |
| 291 return bot.bot_id; | 249 return bot.bot_id; |
| 292 }, | 250 }, |
| 293 pool: function(bot) { | |
| 294 var pool = this._attribute(bot, "pool"); | |
| 295 return pool.join(" | "); | |
| 296 }, | |
| 297 status: function(bot) { | 251 status: function(bot) { |
| 298 // If a bot is both dead and quarantined, show the deadness over the | 252 // If a bot is both dead and quarantined, show the deadness over the |
| 299 // quarentinedness. | 253 // quarentinedness. |
| 300 if (bot.is_dead) { | 254 if (bot.is_dead) { |
| 301 return "Dead. Last seen " + sk.human.diffDate(bot.last_seen_ts) + | 255 return "Dead. Last seen " + sk.human.diffDate(bot.last_seen_ts) + |
| 302 " ago"; | 256 " ago"; |
| 303 } | 257 } |
| 304 if (bot.quarantined) { | 258 if (bot.quarantined) { |
| 305 return "Quarantined: " + this._attribute(bot, "quarantined"); | 259 var msg = this._state(bot, "quarantined")[0]; |
| 260 // Sometimes, the quarantined message is actually in "error". This |
| 261 // happens when the bot code has thrown an exception. |
| 262 if (msg === "unknown" || msg === "true" || msg === true) { |
| 263 msg = this._attribute(bot, "error"); |
| 264 } |
| 265 return "Quarantined: " + msg; |
| 306 } | 266 } |
| 307 return "Alive"; | 267 return "Alive"; |
| 308 }, | 268 }, |
| 309 task: function(bot){ | 269 task: function(bot){ |
| 310 return this._taskId(bot); | 270 return this._taskId(bot); |
| 311 }, | 271 }, |
| 312 }; | 272 }; |
| 313 | 273 |
| 314 var deviceColumnMap = { | 274 var deviceColumnMap = { |
| 315 android_devices: function(device) { | 275 android_devices: function(device) { |
| 316 var str = this._androidAliasDevice(device); | 276 var str = this._androidAliasDevice(device); |
| 317 if (device.okay) { | 277 if (device.okay) { |
| 318 str = this._applyAlias(this._deviceType(device), str); | 278 str = swarming.alias.apply(this._deviceType(device), str); |
| 319 } | 279 } |
| 320 str += " S/N:"; | 280 str += " S/N:"; |
| 321 str += device.serial; | 281 str += device.serial; |
| 322 return str; | 282 return str; |
| 323 }, | 283 }, |
| 324 device_os: function(device) { | 284 device_os: function(device) { |
| 325 if (device.build) { | 285 if (device.build) { |
| 326 return device.build["build.id"]; | 286 return device.build["build.id"]; |
| 327 } | 287 } |
| 328 return "unknown"; | 288 return "unknown"; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 345 disk_space: function(dir, botA, botB) { | 305 disk_space: function(dir, botA, botB) { |
| 346 // We sort based on the raw number of MB of the first disk. | 306 // We sort based on the raw number of MB of the first disk. |
| 347 var botACol = botA.disks[0].mb; | 307 var botACol = botA.disks[0].mb; |
| 348 var botBCol = botB.disks[0].mb;; | 308 var botBCol = botB.disks[0].mb;; |
| 349 return dir * swarming.naturalCompare(botACol, botBCol); | 309 return dir * swarming.naturalCompare(botACol, botBCol); |
| 350 }, | 310 }, |
| 351 }; | 311 }; |
| 352 | 312 |
| 353 Polymer({ | 313 Polymer({ |
| 354 is: 'bot-list', | 314 is: 'bot-list', |
| 355 behaviors: [SwarmingBehaviors.BotListBehavior, | 315 |
| 356 SwarmingBehaviors.DynamicTableBehavior], | 316 // The order behaviors are applied in matters - later ones overwrite |
| 317 // attributes of earlier ones |
| 318 behaviors: [ |
| 319 SwarmingBehaviors.BotListBehavior, |
| 320 SwarmingBehaviors.DynamicTableBehavior, |
| 321 ], |
| 357 | 322 |
| 358 properties: { | 323 properties: { |
| 359 client_id: { | 324 client_id: { |
| 360 type: String, | 325 type: String, |
| 361 }, | 326 }, |
| 362 | 327 |
| 363 // For dynamic table. | 328 // For dynamic table. |
| 364 _columnMap: { | 329 _columnMap: { |
| 365 type: Object, | 330 type: Object, |
| 366 value: columnMap, | 331 value: function() { |
| 332 var base = this._commonColumns(); |
| 333 for (var attr in columnMap) { |
| 334 base[attr] = columnMap[attr]; |
| 335 } |
| 336 return base; |
| 337 }, |
| 367 }, | 338 }, |
| 368 _headerMap: { | 339 _headerMap: { |
| 369 type: Object, | 340 type: Object, |
| 370 value: headerMap, | 341 value: headerMap, |
| 371 }, | 342 }, |
| 372 _specialColumns: { | 343 _specialColumns: { |
| 373 type: Array, | 344 type: Array, |
| 374 value: specialColumns, | 345 value: specialColumns, |
| 375 }, | 346 }, |
| 376 _specialSort: { | 347 _specialSort: { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 393 _botLink: function(id) { | 364 _botLink: function(id) { |
| 394 // TODO(kjlubick) Make this point to /newui/ when appropriate. | 365 // TODO(kjlubick) Make this point to /newui/ when appropriate. |
| 395 return "/restricted/bot/"+id; | 366 return "/restricted/bot/"+id; |
| 396 }, | 367 }, |
| 397 | 368 |
| 398 | 369 |
| 399 _androidAliasDevice: function(device) { | 370 _androidAliasDevice: function(device) { |
| 400 if (device.notReady) { | 371 if (device.notReady) { |
| 401 return UNAUTHENTICATED.toUpperCase(); | 372 return UNAUTHENTICATED.toUpperCase(); |
| 402 } | 373 } |
| 403 return this._androidAlias(this._deviceType(device)); | 374 return swarming.alias.android(this._deviceType(device)); |
| 404 }, | 375 }, |
| 405 | 376 |
| 406 _deviceColumn: function(col, device) { | 377 _deviceColumn: function(col, device) { |
| 407 var f = deviceColumnMap[col]; | 378 var f = deviceColumnMap[col]; |
| 408 if (!f || !device) { | 379 if (!f || !device) { |
| 409 return ""; | 380 return ""; |
| 410 } | 381 } |
| 411 return f.bind(this)(device); | 382 return f.bind(this)(device); |
| 412 }, | 383 }, |
| 413 | 384 |
| 414 _deviceClass: function(device) { | 385 _deviceClass: function(device) { |
| 415 if (!device.okay) { | 386 if (!device.okay) { |
| 416 return "bad-device"; | 387 return "bad-device"; |
| 417 } | 388 } |
| 418 return ""; | 389 return ""; |
| 419 }, | 390 }, |
| 420 | 391 |
| 421 _taskLink: function(data) { | 392 _taskLink: function(data) { |
| 422 if (data && data.task_id) { | 393 if (data && data.task_id) { |
| 423 return "/user/task/" + data.task_id; | 394 return "/user/task/" + data.task_id; |
| 424 } | 395 } |
| 425 return undefined; | 396 return undefined; |
| 426 } | 397 } |
| 427 | 398 |
| 428 }); | 399 }); |
| 429 })(); | 400 })(); |
| 430 </script> | 401 </script> |
| 431 </dom-module> | 402 </dom-module> |
| OLD | NEW |