| Index: appengine/swarming/elements/res/imp/taskpage/task-page.html
|
| diff --git a/appengine/swarming/elements/res/imp/taskpage/task-page.html b/appengine/swarming/elements/res/imp/taskpage/task-page.html
|
| index d5cee63f12742ff6a2f36f64712003cd86dc91be..d7f2ca2fad100ed11a394f6cfb116c3882e617a8 100644
|
| --- a/appengine/swarming/elements/res/imp/taskpage/task-page.html
|
| +++ b/appengine/swarming/elements/res/imp/taskpage/task-page.html
|
| @@ -33,6 +33,8 @@
|
| <link rel="import" href="/res/imp/bower_components/polymer/polymer.html">
|
|
|
| <link rel="import" href="/res/imp/common/common-behavior.html">
|
| +<link rel="import" href="/res/imp/common/error-toast.html">
|
| +<link rel="import" href="/res/imp/common/interval-timer.html">
|
| <link rel="import" href="/res/imp/common/single-page-style.html">
|
| <link rel="import" href="/res/imp/common/swarming-app.html">
|
| <link rel="import" href="/res/imp/common/task-behavior.html">
|
| @@ -95,13 +97,15 @@
|
| value="{{_show_raw}}">
|
| </url-param>
|
| <url-param name="refresh"
|
| - value="{{_refresh}}"
|
| + value="{{_refresh_interval}}"
|
| default_value="10">
|
| </url-param>
|
|
|
| <swarming-app
|
| client_id="[[client_id]]"
|
| auth_headers="{{_auth_headers}}"
|
| + permissions="{{_permissions}}"
|
| + profile="{{_profile}}"
|
| signed_in="{{_signed_in}}"
|
|
|
| busy="[[_busy]]"
|
| @@ -112,7 +116,9 @@
|
| <div hidden$="[[_not(_signed_in)]]">
|
|
|
| <task-page-data
|
| + id="data"
|
| auth_headers="[[_auth_headers]]"
|
| + refresh_interval="[[_refresh_interval]]"
|
| task_id="[[task_id]]"
|
|
|
| busy="{{_busy}}"
|
| @@ -128,8 +134,10 @@
|
| <button on-click="_refresh">
|
| <iron-icon class="refresh" icon="icons:refresh"></iron-icon>
|
| </button>
|
| - <button on-click="_retry"><span>Retry</span></button>
|
| - <button on-click="_cancel">Cancel</button>
|
| + <button on-click="_promptRetry">Retry</button>
|
| + <template is="dom-if" if="[[_canCancelTask(_result,_permissions)]]">
|
| + <button on-click="_promptCancel">Cancel</button>
|
| + </template>
|
| </div>
|
| <table>
|
| <tr>
|
| @@ -142,12 +150,12 @@
|
| </tr>
|
| <tr>
|
| <td>Created</td>
|
| - <td>[[_request.human_created_ts]]</td>
|
| + <td title$="[[_request.created_ts]]">[[_request.human_created_ts]]</td>
|
| </tr>
|
| <template is="dom-if" if="[[_wasPickedUp(_result)]]">
|
| <tr>
|
| <td>Started</td>
|
| - <td>[[_result.human_started_ts]]</td>
|
| + <td title$="[[_result.started_ts]]">[[_result.human_started_ts]]</td>
|
| </tr>
|
| </template>
|
| <template is="dom-if" if="[[_wasNotPickedUp(_result)]]">
|
| @@ -159,18 +167,18 @@
|
| <template is="dom-if" if="[[_result.human_completed_ts]]">
|
| <tr>
|
| <td>Completed</td>
|
| - <td>[[_result.human_completed_ts]]</td>
|
| + <td title$="[[_result.completed_ts]]">[[_result.human_completed_ts]]</td>
|
| </tr>
|
| </template>
|
| <template is="dom-if" if="[[_result.human_abandoned_ts]]">
|
| <tr>
|
| <td>Abandoned</td>
|
| - <td>[[_result.human_abandoned_ts]]</td>
|
| + <td title$="[[_result.abandoned_ts]]">[[_result.human_abandoned_ts]]</td>
|
| </tr>
|
| </template>
|
| <tr>
|
| <td>Last Updated</td>
|
| - <td>[[_result.human_modified_ts]]</td>
|
| + <td title$="[[_result.modified_ts]]">[[_result.human_modified_ts]]</td>
|
| </tr>
|
| <template is="dom-if" if="[[_result.deduped_from]]">
|
| <tr>
|
| @@ -223,11 +231,17 @@
|
| </tr>
|
| </template>
|
| <tr>
|
| - <td rowspan$="[[_rowspan(_request.properties.dimensions)]]">Requested Dimensions</td>
|
| + <td rowspan$="[[_rowspan(_request.properties.dimensions)]]">
|
| + <a
|
| + title="The list of bots that matches the list of dimensions"
|
| + href$="[[_botListLink(_request.properties.dimensions)]]">
|
| + Requested Dimensions
|
| + </a>
|
| + </td>
|
| </tr>
|
| <template is="dom-repeat" items="{{_request.properties.dimensions}}" as="dimension">
|
| <tr>
|
| - <td><b>[[dimension.key]]:</b> [[dimension.value]]</td>
|
| + <td><b>[[dimension.key]]:</b> [[_alias(dimension)]]</td>
|
| </tr>
|
| </template>
|
| <tr>
|
| @@ -329,11 +343,13 @@
|
| <td><a href$="[[_botLink(_result.bot_id)]]">[[_result.bot_id]]</td>
|
| </tr>
|
| <tr>
|
| - <td rowspan$="[[_rowspan(_result.bot_dimensions)]]">Bot Dimensions</td>
|
| + <td rowspan$="[[_rowspan(_result.bot_dimensions)]]">
|
| + <a>Bot Dimensions</a>
|
| + </td>
|
| </tr>
|
| <template is="dom-repeat" items="[[_result.bot_dimensions]]" as="dimension">
|
| <tr>
|
| - <td><b>[[dimension.key]]:</b> [[_join(dimension.value," | ")]]</td>
|
| + <td><b>[[dimension.key]]:</b> [[_alias(dimension)]]</td>
|
| </tr>
|
| </template>
|
|
|
| @@ -411,7 +427,7 @@
|
| <paper-input
|
| class="refresh_input"
|
| label="Refresh Interval (seconds)"
|
| - value="{{_refresh}}"
|
| + value="{{_refresh_interval}}"
|
| auto-validate
|
| min="1"
|
| max="1000"
|
| @@ -428,9 +444,22 @@
|
| </div>
|
| </div>
|
| </div>
|
| -
|
| </swarming-app>
|
|
|
| + <paper-dialog id="prompt" modal on-iron-overlay-closed="_promptClosed">
|
| + <h2>Are you sure?</h2>
|
| + <div>Are you sure you want to [[_dialogPrompt]]?</div>
|
| + <div class="buttons">
|
| + <paper-button dialog-dismiss autofocus>No</paper-button>
|
| + <paper-button dialog-confirm>Yes</paper-button>
|
| + </div>
|
| + </paper-dialog>
|
| +
|
| + <error-toast></error-toast>
|
| +
|
| + <interval-timer period="[[_refresh_interval]]" on-trigger="_refreshOutput">
|
| + </interval-timer>
|
| +
|
| </template>
|
| <script>
|
| (function(){
|
| @@ -453,19 +482,55 @@
|
| type: String,
|
| },
|
|
|
| +
|
| + _dialogPrompt: {
|
| + type: String,
|
| + value: "",
|
| + },
|
| + _refresh_interval: {
|
| + type: Number,
|
| + },
|
| _request: {
|
| type: Object,
|
| observer: "_requestUpdated"
|
| },
|
| _request_detail: {
|
| type: Boolean,
|
| + },
|
| + _result: {
|
| + type: Object,
|
| + },
|
| + _stdout: {
|
| + type: String,
|
| }
|
| },
|
|
|
| + _alias: function(dim) {
|
| + var values = dim.value;
|
| + if (!Array.isArray(values)) {
|
| + values = [values];
|
| + }
|
| + if (swarming.alias.has(dim.key)) {
|
| + values.forEach(function(v, i){
|
| + values[i] = swarming.alias.apply(v, dim.key);
|
| + });
|
| + }
|
| + return values.join(" | ");
|
| + },
|
| +
|
| _bytes: function(sizeInBytes) {
|
| return sk.human.bytes(sizeInBytes);
|
| },
|
|
|
| + _canCancelTask: function(result, permissions) {
|
| + return result && result.state === "PENDING" && permissions.cancel_task;
|
| + },
|
| +
|
| + _cancelTask: function() {
|
| + var url = "/_ah/api/swarming/v1/task/" + this.task_id +"/cancel";
|
| + swarming.postWithToast(url, "Canceling task " + this.task_id, this._auth_headers);
|
| + },
|
| +
|
| _cipdRowspan: function(request, result) {
|
| if (!request || !request.properties || !request.properties.cipd_input) {
|
| return 0;
|
| @@ -546,11 +611,6 @@
|
| "&hash=" + ref.isolated;
|
| },
|
|
|
| - _join: function(arr, s) {
|
| - arr = arr || [];
|
| - return arr.join(s);
|
| - },
|
| -
|
| _noMilo: function(result) {
|
| return !this._tag(result, "allow_milo");
|
| },
|
| @@ -567,12 +627,72 @@
|
| return this._timeDiffExact(result.created_ts, end);
|
| },
|
|
|
| + _promptClosed: function(e) {
|
| + if (e.detail.confirmed) {
|
| + if (this._dialogPrompt.startsWith("cancel")) {
|
| + this._cancelTask();
|
| + } else {
|
| + this._retryTask();
|
| + }
|
| + }
|
| + },
|
| +
|
| + _promptCancel: function() {
|
| + this.set("_dialogPrompt", "cancel task "+this.task_id);
|
| + this.$.prompt.open();
|
| + },
|
| +
|
| + _promptRetry: function() {
|
| + this.set("_dialogPrompt", "retry task "+this.task_id);
|
| + this.$.prompt.open();
|
| + },
|
| +
|
| + _refresh: function() {
|
| + this.$.data.reload();
|
| + },
|
| +
|
| + _refreshOutput: function() {
|
| + this.$.data.reloadStdout();
|
| + var miloFrame = this.$$("iframe")
|
| + if (miloFrame) {
|
| + miloFrame.src = this._getMiloLink(this.milo_prefix,this.task_id);
|
| + }
|
| + },
|
| +
|
| _requestUpdated: function(request) {
|
| if (this._noMilo(request)) {
|
| this.set("_show_raw", 1);
|
| }
|
| },
|
|
|
| + _retryTask: function() {
|
| + if (!this._request) {
|
| + sk.errorMessage("Task not yet loaded", 3000);
|
| + return;
|
| + }
|
| + var newTask = {
|
| + expiration_secs: this._request.expiration_secs,
|
| + name: this._request.name +" (retry)",
|
| + parent_task_id: this._request.parent_task_id,
|
| + priority: this._request.priority,
|
| + properties:this._request.properties,
|
| + tags: this._request.tags,
|
| + user: this._profile.email,
|
| + service_account: this._request.service_account,
|
| + }
|
| + swarming.postWithToast("/_ah/api/swarming/v1/tasks/new", "Retrying task " + this.task_id,
|
| + this._auth_headers, newTask)
|
| + .then(function(response) {
|
| + response = JSON.parse(response);
|
| + if (response && response.task_id) {
|
| + this.set("task_id", response.task_id);
|
| + }
|
| + }.bind(this), function(e) {
|
| + console.log("Task could not be retried", e);
|
| + }
|
| + );
|
| + },
|
| +
|
| _rowspan: function(dims) {
|
| dims = dims || [];
|
| return dims.length + 1;
|
|
|