Chromium Code Reviews| 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-page> | 9 <bot-page> |
| 10 | 10 |
| 11 bot-page shows the tasks, events, and dimensions of a bot. | 11 bot-page shows the tasks, events, and dimensions of a bot. |
| 12 | 12 |
| 13 This is a top-level element. | 13 This is a top-level element. |
| 14 | 14 |
| 15 Properties: | 15 Properties: |
| 16 bot_id: String, Used in testing to specify a bot_id | 16 bot_id: String, Used in testing to specify a bot_id |
| 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-collapse/iron-collapse.h tml"> | 27 <link rel="import" href="/res/imp/bower_components/iron-collapse/iron-collapse.h tml"> |
| 28 <link rel="import" href="/res/imp/bower_components/iron-icon/iron-icon.html"> | 28 <link rel="import" href="/res/imp/bower_components/iron-icon/iron-icon.html"> |
| 29 <link rel="import" href="/res/imp/bower_components/iron-icons/iron-icons.html"> | 29 <link rel="import" href="/res/imp/bower_components/iron-icons/iron-icons.html"> |
| 30 <link rel="import" href="/res/imp/bower_components/paper-button/paper-button.htm l"> | |
| 30 <link rel="import" href="/res/imp/bower_components/paper-checkbox/paper-checkbox .html"> | 31 <link rel="import" href="/res/imp/bower_components/paper-checkbox/paper-checkbox .html"> |
| 32 <link rel="import" href="/res/imp/bower_components/paper-dialog/paper-dialog.htm l"> | |
| 31 <link rel="import" href="/res/imp/bower_components/paper-input/paper-input.html" > | 33 <link rel="import" href="/res/imp/bower_components/paper-input/paper-input.html" > |
| 32 <link rel="import" href="/res/imp/bower_components/paper-tabs/paper-tabs.html"> | 34 <link rel="import" href="/res/imp/bower_components/paper-tabs/paper-tabs.html"> |
| 33 <link rel="import" href="/res/imp/bower_components/paper-icon-button/paper-icon- button.html"> | |
| 34 <link rel="import" href="/res/imp/bower_components/polymer/polymer.html"> | 35 <link rel="import" href="/res/imp/bower_components/polymer/polymer.html"> |
| 35 | 36 |
| 36 <link rel="import" href="/res/imp/common/swarming-app.html"> | 37 <link rel="import" href="/res/imp/common/swarming-app.html"> |
| 37 <link rel="import" href="/res/imp/common/url-param.html"> | 38 <link rel="import" href="/res/imp/common/url-param.html"> |
| 39 <link rel="import" href="/res/imp/common/error-toast.html"> | |
| 38 | 40 |
| 39 <link rel="import" href="bot-page-data.html"> | 41 <link rel="import" href="bot-page-data.html"> |
| 40 <link rel="import" href="bot-page-shared-behavior.html"> | 42 <link rel="import" href="bot-page-shared-behavior.html"> |
| 41 | 43 |
| 42 | 44 |
| 43 <dom-module id="bot-page"> | 45 <dom-module id="bot-page"> |
| 44 <template> | 46 <template> |
| 45 <style include="iron-flex iron-flex-alignment iron-positioning swarming-app- style"> | 47 <style include="iron-flex iron-flex-alignment iron-positioning swarming-app- style"> |
| 46 | 48 |
| 47 .header { | 49 .header { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 71 margin-bottom: 5px; | 73 margin-bottom: 5px; |
| 72 } | 74 } |
| 73 td, th { | 75 td, th { |
| 74 border: 1px solid #BBB; | 76 border: 1px solid #BBB; |
| 75 padding: 5px; | 77 padding: 5px; |
| 76 } | 78 } |
| 77 | 79 |
| 78 .quarantined, .failed_task { | 80 .quarantined, .failed_task { |
| 79 background-color: #ffdddd; | 81 background-color: #ffdddd; |
| 80 } | 82 } |
| 81 .dead { | 83 .dead, .bot_died { |
|
jcgregorio
2016/09/07 12:12:48
Each class should be on a new line:
.dead,
.bot_d
kjlubick
2016/09/07 12:36:38
Done. Should we add this to the style guide?
jcgregorio
2016/09/07 12:41:21
Sure.
| |
| 82 background-color: #cccccc; | 84 background-color: #cccccc; |
| 83 } | 85 } |
| 84 | 86 |
| 85 .message { | 87 .message { |
| 86 white-space: pre-line; | 88 white-space: pre-line; |
| 87 font-family: monospace; | 89 font-family: monospace; |
| 88 } | 90 } |
| 89 | 91 |
| 90 .bot_state { | 92 .bot_state { |
| 91 white-space: pre; | 93 white-space: pre; |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 114 } | 116 } |
| 115 | 117 |
| 116 paper-tab.iron-selected { | 118 paper-tab.iron-selected { |
| 117 background-color: #A6CEE3; | 119 background-color: #A6CEE3; |
| 118 border: 3px solid #1F78B4; | 120 border: 3px solid #1F78B4; |
| 119 color: #000; | 121 color: #000; |
| 120 font-weight: bold; | 122 font-weight: bold; |
| 121 text-decoration: underline; | 123 text-decoration: underline; |
| 122 } | 124 } |
| 123 | 125 |
| 126 paper-dialog { | |
| 127 border-radius: 6px; | |
| 128 } | |
| 129 | |
| 124 </style> | 130 </style> |
| 125 | 131 |
| 126 <url-param name="id" | 132 <url-param name="id" |
| 127 value="{{bot_id}}"> | 133 value="{{bot_id}}"> |
| 128 </url-param> | 134 </url-param> |
| 129 <url-param name="show_all_events" | 135 <url-param name="show_all_events" |
| 130 value="{{_show_all}}"> | 136 value="{{_show_all}}"> |
| 131 </url-param> | 137 </url-param> |
| 132 <url-param name="selected" | 138 <url-param name="selected" |
| 133 value="{{_selected}}"> | 139 value="{{_selected}}"> |
| 134 </url-param> | 140 </url-param> |
| 135 <url-param name="show_state" | 141 <url-param name="show_state" |
| 136 value="{{_show_state}}"> | 142 value="{{_show_state}}"> |
| 137 </url-param> | 143 </url-param> |
| 138 | 144 |
| 139 <swarming-app | 145 <swarming-app |
| 140 client_id="[[client_id]]" | 146 client_id="[[client_id]]" |
| 141 auth_headers="{{_auth_headers}}" | 147 auth_headers="{{_auth_headers}}" |
| 142 permissions="{{_permissions}}" | 148 permissions="{{_permissions}}" |
| 143 signed_in="{{_signed_in}}" | 149 signed_in="{{_signed_in}}" |
| 144 | 150 |
| 145 busy="[[_busy]]" | 151 busy="[[_busy]]" |
| 146 name="Swarming Bot Page"> | 152 name="Swarming Bot Page"> |
| 147 | 153 |
| 148 <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2> | 154 <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2> |
| 149 | 155 |
| 150 <div hidden$="[[_not(_signed_in)]]"> | 156 <div hidden$="[[_not(_signed_in)]]"> |
| 151 | 157 |
| 152 <bot-page-data | 158 <bot-page-data |
| 159 id="data" | |
| 153 auth_headers="[[_auth_headers]]" | 160 auth_headers="[[_auth_headers]]" |
| 154 bot_id="[[bot_id]]" | 161 bot_id="[[bot_id]]" |
| 155 | 162 |
| 156 bot="{{_bot}}" | 163 bot="{{_bot}}" |
| 157 busy="{{_busy}}" | 164 busy="{{_busy}}" |
| 158 events="{{_events}}" | 165 events="{{_events}}" |
| 159 tasks="{{_tasks}}"> | 166 tasks="{{_tasks}}"> |
| 160 </bot-page-data> | 167 </bot-page-data> |
| 161 | 168 |
| 162 <div class="header horizontal layout"> | 169 <div class="header horizontal layout"> |
| 163 <paper-input class="id_input" label="Bot id" value="{{bot_id}}"></pape r-input> | 170 <paper-input class="id_input" label="Bot id" value="{{bot_id}}"></pape r-input> |
| 164 <button> | 171 <button on-click="_refresh"> |
| 165 <iron-icon class="refresh" icon="icons:refresh"></iron-icon> | 172 <iron-icon class="refresh" icon="icons:refresh"></iron-icon> |
| 166 </button> | 173 </button> |
| 167 </div> | 174 </div> |
| 168 | 175 |
| 169 <div> | 176 <div> |
| 170 <table> | 177 <table> |
| 171 <tr class$="[[_isDead(_bot)]]"> | 178 <tr class$="[[_isDead(_bot)]]"> |
| 172 <td>Last Seen</td> | 179 <td>Last Seen</td> |
| 173 <td title="[[_bot.human_last_seen_ts]]"> | 180 <td title="[[_bot.human_last_seen_ts]]"> |
| 174 [[_timeDiffExact(_bot.last_seen_ts)]] ago</td> | 181 [[_timeDiffExact(_bot.last_seen_ts)]] ago</td> |
| 175 <td> | 182 <td> |
| 176 <!-- dom-ifs are slightly less performant than hidden$=, but | 183 <!-- dom-ifs are slightly less performant than hidden$=, but |
| 177 prevent things from first drawing and then hiding. We prefer to | 184 prevent things from first drawing and then hiding. We prefer to |
| 178 not flash buttons or quarantined messages --> | 185 not flash buttons or quarantined messages --> |
| 179 <template is="dom-if" if="[[_canShutdown(_bot,_permissions)]]"> | 186 <template is="dom-if" if="[[_canShutdown(_bot,_permissions)]]"> |
| 180 <button class="raised"> | 187 <button class="raised" on-click="_promptShutdown"> |
| 181 Shut Down Gracefully | 188 Shut Down Gracefully |
| 182 </button> | 189 </button> |
| 183 </template> | 190 </template> |
| 184 <template is="dom-if" if="[[_canDelete(_bot,_permissions)]]"> | 191 <template is="dom-if" if="[[_canDelete(_bot,_permissions)]]"> |
| 185 <button class="raised"> | 192 <button class="raised" on-click="_promptDelete"> |
| 186 Delete | 193 Delete |
| 187 </button> | 194 </button> |
| 188 </template> | 195 </template> |
| 189 </td> | 196 </td> |
| 190 </tr> | 197 </tr> |
| 191 <template is="dom-if" if="[[_bot.quarantined]]"> | 198 <template is="dom-if" if="[[_bot.quarantined]]"> |
| 192 <tr class="quarantined"> | 199 <tr class="quarantined"> |
| 193 <td>Quarantined</td> | 200 <td>Quarantined</td> |
| 194 <td colspan="2">[[_quarantineMessage(_bot)]]</td> | 201 <td colspan="2">[[_quarantineMessage(_bot)]]</td> |
| 195 </tr> | 202 </tr> |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 <thead> | 289 <thead> |
| 283 <tr> | 290 <tr> |
| 284 <th>Task</th> | 291 <th>Task</th> |
| 285 <th>Started</th> | 292 <th>Started</th> |
| 286 <th>Duration</th> | 293 <th>Duration</th> |
| 287 <th>Result</th> | 294 <th>Result</th> |
| 288 </tr> | 295 </tr> |
| 289 </thead> | 296 </thead> |
| 290 <tbody> | 297 <tbody> |
| 291 <template is="dom-repeat" items="{{_tasks}}" as="task"> | 298 <template is="dom-repeat" items="{{_tasks}}" as="task"> |
| 292 <tr> | 299 <tr class$="[[_taskClass(task)]]"> |
| 293 <td><a target="_blank" href$="[[_taskLink(task.task_id)]]">[[t ask.name]]</a></td> | 300 <td><a target="_blank" href$="[[_taskLink(task.task_id)]]">[[t ask.name]]</a></td> |
| 294 <td>[[task.human_started_ts]]</td> | 301 <td>[[task.human_started_ts]]</td> |
| 295 <td title="[[task.human_completed_ts]]">[[task.human_duration] ]</td> | 302 <td title="[[task.human_completed_ts]]">[[task.human_duration] ]</td> |
| 296 <td>[[task.state]]</td> | 303 <td>[[task.state]]</td> |
| 297 </tr> | 304 </tr> |
| 298 </template> | 305 </template> |
| 299 </tbody> | 306 </tbody> |
| 300 </table> | 307 </table> |
| 301 </template> | 308 </template> |
| 302 | 309 |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 321 <td> | 328 <td> |
| 322 <a target="_blank" href$="[[_luciLink(_bot.version)]]">[[_sh orten(_bot.version,'8')]]</a> | 329 <a target="_blank" href$="[[_luciLink(_bot.version)]]">[[_sh orten(_bot.version,'8')]]</a> |
| 323 </td> | 330 </td> |
| 324 </tr> | 331 </tr> |
| 325 </template> | 332 </template> |
| 326 </tbody> | 333 </tbody> |
| 327 </table> | 334 </table> |
| 328 </template> | 335 </template> |
| 329 </div> | 336 </div> |
| 330 </div> | 337 </div> |
| 338 </swarming-app> | |
| 331 | 339 |
| 332 </swarming-app> | 340 <paper-dialog id="prompt" modal on-iron-overlay-closed="_promptClosed"> |
| 341 <h2>Are you sure?</h2> | |
| 342 <div>Are you sure you want to [[_dialogPrompt]]?</div> | |
| 343 <div class="buttons"> | |
| 344 <paper-button dialog-dismiss autofocus>No</paper-button> | |
| 345 <paper-button dialog-confirm>Yes</paper-button> | |
| 346 </div> | |
| 347 </paper-dialog> | |
| 348 | |
| 349 <error-toast></error-toast> | |
| 333 | 350 |
| 334 </template> | 351 </template> |
| 335 <script> | 352 <script> |
| 336 (function(){ | 353 (function(){ |
| 337 | 354 |
| 338 | 355 |
| 339 Polymer({ | 356 Polymer({ |
| 340 is: 'bot-page', | 357 is: 'bot-page', |
| 341 | 358 |
| 342 behaviors: [ | 359 behaviors: [ |
| 343 SwarmingBehaviors.BotPageBehavior, | 360 SwarmingBehaviors.BotPageBehavior, |
| 344 ], | 361 ], |
| 345 | 362 |
| 346 properties: { | 363 properties: { |
| 347 bot_id: { | 364 bot_id: { |
| 348 type: String, | 365 type: String, |
| 349 }, | 366 }, |
| 350 client_id: { | 367 client_id: { |
| 351 type: String, | 368 type: String, |
| 352 }, | 369 }, |
| 353 | 370 |
| 371 _auth_headers: { | |
| 372 type: Object, | |
| 373 }, | |
| 354 _bot: { | 374 _bot: { |
| 355 type: Object, | 375 type: Object, |
| 356 }, | 376 }, |
| 377 _dialogPrompt: { | |
| 378 type: String, | |
| 379 value: "", | |
| 380 }, | |
| 357 _selected: { | 381 _selected: { |
| 358 type: Number, | 382 type: Number, |
| 359 }, | 383 }, |
| 360 _show_all: { | 384 _show_all: { |
| 361 type: Boolean, | 385 type: Boolean, |
| 362 }, | 386 }, |
| 363 _show_state: { | 387 _show_state: { |
| 364 type: Boolean, | 388 type: Boolean, |
| 365 } | 389 } |
| 366 }, | 390 }, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 377 return bot && !bot.is_dead && permissions.terminate_bot; | 401 return bot && !bot.is_dead && permissions.terminate_bot; |
| 378 }, | 402 }, |
| 379 | 403 |
| 380 _concat: function(arr) { | 404 _concat: function(arr) { |
| 381 if (!arr) { | 405 if (!arr) { |
| 382 return ""; | 406 return ""; |
| 383 } | 407 } |
| 384 return arr.join(" | "); | 408 return arr.join(" | "); |
| 385 }, | 409 }, |
| 386 | 410 |
| 411 _deleteBot: function() { | |
| 412 swarming.postWithToast("/_ah/api/swarming/v1/bot/"+this.bot_id+"/delete" , | |
| 413 "Deleting "+this.bot_id, this._auth_headers); | |
| 414 }, | |
| 415 | |
| 387 _eventList(events, showAll) { | 416 _eventList(events, showAll) { |
| 388 if (!events) { | 417 if (!events) { |
| 389 return []; | 418 return []; |
| 390 } | 419 } |
| 391 return events.filter(function(e){ | 420 return events.filter(function(e){ |
| 392 return showAll || e.message; | 421 return showAll || e.message; |
| 393 }); | 422 }); |
| 394 }, | 423 }, |
| 395 | 424 |
| 396 _isDead(bot){ | 425 _isDead(bot){ |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 413 return 1; | 442 return 1; |
| 414 } | 443 } |
| 415 return 1 + arr.length; | 444 return 1 + arr.length; |
| 416 }, | 445 }, |
| 417 | 446 |
| 418 _prettyPrint: function(obj) { | 447 _prettyPrint: function(obj) { |
| 419 obj = obj || {}; | 448 obj = obj || {}; |
| 420 return JSON.stringify(obj, null, 2); | 449 return JSON.stringify(obj, null, 2); |
| 421 }, | 450 }, |
| 422 | 451 |
| 452 _promptClosed: function(e) { | |
| 453 if (e.detail.confirmed) { | |
| 454 if (this._dialogPrompt.startsWith("shut down")) { | |
| 455 this._shutdownBot(); | |
| 456 } else { | |
| 457 this._deleteBot(); | |
| 458 } | |
| 459 } | |
| 460 }, | |
| 461 | |
| 462 _promptDelete: function() { | |
| 463 this.set("_dialogPrompt", "delete "+this.bot_id); | |
| 464 this.$.prompt.open(); | |
| 465 }, | |
| 466 | |
| 467 _promptShutdown: function() { | |
| 468 this.set("_dialogPrompt", "shut down "+this.bot_id); | |
| 469 this.$.prompt.open(); | |
| 470 }, | |
| 471 | |
| 423 _quarantineMessage: function(bot) { | 472 _quarantineMessage: function(bot) { |
| 424 if (bot && bot.quarantined) { | 473 if (bot && bot.quarantined) { |
| 425 var msg = bot.state.quarantined; | 474 var msg = bot.state.quarantined; |
| 426 // Sometimes, the quarantined message is actually in "error". This | 475 // Sometimes, the quarantined message is actually in "error". This |
| 427 // happens when the bot code has thrown an exception. | 476 // happens when the bot code has thrown an exception. |
| 428 if (msg === undefined || msg === "true" || msg === true) { | 477 if (msg === undefined || msg === "true" || msg === true) { |
| 429 msg = this._attribute(bot, "error"); | 478 msg = this._attribute(bot, "error"); |
| 430 } | 479 } |
| 431 return msg || "True"; | 480 return msg || "True"; |
| 432 } | 481 } |
| 433 return ""; | 482 return ""; |
| 434 }, | 483 }, |
| 435 | 484 |
| 485 _refresh: function() { | |
| 486 this.$.data.request(); | |
| 487 }, | |
| 488 | |
| 436 _shorten: function(str, length) { | 489 _shorten: function(str, length) { |
| 437 if (!str || ! length) { | 490 if (!str || ! length) { |
| 438 return ""; | 491 return ""; |
| 439 } | 492 } |
| 440 return str.substring(0, length); | 493 return str.substring(0, length); |
| 441 }, | 494 }, |
| 442 | 495 |
| 496 _shutdownBot: function() { | |
| 497 swarming.postWithToast("/_ah/api/swarming/v1/bot/"+this.bot_id+"/termina te", | |
| 498 "Shutting down "+this.bot_id, this._auth_headers); | |
| 499 }, | |
| 500 | |
| 443 _task: function(bot) { | 501 _task: function(bot) { |
| 444 return (bot && bot.task_id) || "idle"; | 502 return (bot && bot.task_id) || "idle"; |
| 445 }, | 503 }, |
| 446 | 504 |
| 505 _taskClass: function(task) { | |
| 506 if (task && task.internal_failure) { | |
| 507 return "bot_died"; | |
| 508 } | |
| 509 if (task && task.failure) { | |
| 510 return "failed_task"; | |
| 511 } | |
| 512 return ""; | |
| 513 }, | |
| 514 | |
| 447 _taskLink: function(task_id) { | 515 _taskLink: function(task_id) { |
| 448 // TODO(kjlubick): Migrate this to /newui/ when ready | 516 // TODO(kjlubick): Migrate this to /newui/ when ready |
| 449 if (task_id) { | 517 if (task_id) { |
| 450 return "/user/task/" + task_id; | 518 return "/user/task/" + task_id; |
| 451 } | 519 } |
| 452 return undefined; | 520 return undefined; |
| 453 }, | 521 }, |
| 454 | 522 |
| 455 _toggleState: function() { | 523 _toggleState: function() { |
| 456 this.set("_show_state", !this._show_state); | 524 this.set("_show_state", !this._show_state); |
| 457 } | 525 } |
| 458 | 526 |
| 459 }); | 527 }); |
| 460 })(); | 528 })(); |
| 461 </script> | 529 </script> |
| 462 </dom-module> | 530 </dom-module> |
| OLD | NEW |