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

Side by Side Diff: appengine/swarming/elements/res/imp/botpage/bot-page.html

Issue 2302973002: Refactor post requests, implement bot cancel/terminate (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@basic-layout
Patch Set: Address comments 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-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
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
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
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
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
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
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>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698