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

Side by Side Diff: appengine/swarming/elements/build/elements.html

Issue 2279903002: Make the new index page more useful (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-py@whoami3
Patch Set: Fix names 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
« no previous file with comments | « no previous file | appengine/swarming/elements/res/imp/common/auth-signin.html » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 <!DOCTYPE html><html><head><!-- 1 <!DOCTYPE html><html><head><!--
2 @license 2 @license
3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
4 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt 4 This code may only be used under the BSD style license found at http://polymer.g ithub.io/LICENSE.txt
5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
6 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI BUTORS.txt
7 Code distributed by Google as part of the polymer project is also 7 Code distributed by Google as part of the polymer project is also
8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN TS.txt
9 --><!-- 9 --><!--
10 @license 10 @license
(...skipping 8076 matching lines...) Expand 10 before | Expand all | Expand 10 after
8087 8087
8088 8088
8089 8089
8090 8090
8091 8091
8092 8092
8093 8093
8094 8094
8095 8095
8096 8096
8097 <script>function MakePromise (asap) { 8097 <script>
8098 function Promise(fn) { 8098 window.SwarmingBehaviors = window.SwarmingBehaviors || {};
8099 » » if (typeof this !== 'object' || typeof fn !== 'function') throw new TypeError(); 8099 (function(){
8100 » » this._state = null; 8100 // This behavior wraps up all the shared swarming functionality.
8101 » » this._value = null; 8101 SwarmingBehaviors.CommonBehavior = {
8102 » » this._deferreds = []
8103 8102
8104 » » doResolve(fn, resolve.bind(this), reject.bind(this)); 8103 // _getJsonAsync makes an XHR to a url, parses the response as JSON
8105 » } 8104 // and sticks the resulting object into the property with the name given
8106 8105 // by "bindTo". If busy is defined, the property with that name will be
8107 » function handle(deferred) { 8106 // set to true while the request is in flight and false afterwards.
8108 » » var me = this; 8107 // request headers (e.g. authentication) and query params will be used if
8109 » » if (this._state === null) { 8108 // provided. Query params is an object like {String:Array<String>}. On
8110 » » » this._deferreds.push(deferred); 8109 // error, bindTo will be set to false. It is not set to undefined
8111 » » » return 8110 // because computed values in Polymer don't fire if a property is
8112 » » } 8111 // undefined. Clients should check that bindTo is not falsey.
8113 » » asap(function() { 8112 _getJsonAsync: function(bindTo, url, busy, headers, params) {
8114 » » » var cb = me._state ? deferred.onFulfilled : deferred.onR ejected 8113 if (!bindTo || !url) {
8115 » » » if (typeof cb !== 'function') { 8114 console.log("Need at least a polymer element to bind to and a url");
8116 » » » » (me._state ? deferred.resolve : deferred.reject) (me._value); 8115 return;
8117 » » » » return;
8118 » » » }
8119 » » » var ret;
8120 » » » try {
8121 » » » » ret = cb(me._value);
8122 » » » }
8123 » » » catch (e) {
8124 » » » » deferred.reject(e);
8125 » » » » return;
8126 » » » }
8127 » » » deferred.resolve(ret);
8128 » » })
8129 » }
8130
8131 » function resolve(newValue) {
8132 » » try { //Promise Resolution Procedure: https://github.com/promise s-aplus/promises-spec#the-promise-resolution-procedure
8133 » » » if (newValue === this) throw new TypeError();
8134 » » » if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
8135 » » » » var then = newValue.then;
8136 » » » » if (typeof then === 'function') {
8137 » » » » » doResolve(then.bind(newValue), resolve.b ind(this), reject.bind(this));
8138 » » » » » return;
8139 » » » » }
8140 » » » }
8141 » » » this._state = true;
8142 » » » this._value = newValue;
8143 » » » finale.call(this);
8144 » » } catch (e) { reject.call(this, e); }
8145 » }
8146
8147 » function reject(newValue) {
8148 » » this._state = false;
8149 » » this._value = newValue;
8150 » » finale.call(this);
8151 » }
8152
8153 » function finale() {
8154 » » for (var i = 0, len = this._deferreds.length; i < len; i++) {
8155 » » » handle.call(this, this._deferreds[i]);
8156 » » }
8157 » » this._deferreds = null;
8158 » }
8159
8160 » /**
8161 » * Take a potentially misbehaving resolver function and make sure
8162 » * onFulfilled and onRejected are only called once.
8163 » *
8164 » * Makes no guarantees about asynchrony.
8165 » */
8166 » function doResolve(fn, onFulfilled, onRejected) {
8167 » » var done = false;
8168 » » try {
8169 » » » fn(function (value) {
8170 » » » » if (done) return;
8171 » » » » done = true;
8172 » » » » onFulfilled(value);
8173 » » » }, function (reason) {
8174 » » » » if (done) return;
8175 » » » » done = true;
8176 » » » » onRejected(reason);
8177 » » » })
8178 » » } catch (ex) {
8179 » » » if (done) return;
8180 » » » done = true;
8181 » » » onRejected(ex);
8182 » » }
8183 » }
8184
8185 » Promise.prototype['catch'] = function (onRejected) {
8186 » » return this.then(null, onRejected);
8187 » };
8188
8189 » Promise.prototype.then = function(onFulfilled, onRejected) {
8190 » » var me = this;
8191 » » return new Promise(function(resolve, reject) {
8192 handle.call(me, {
8193 onFulfilled: onFulfilled,
8194 onRejected: onRejected,
8195 resolve: resolve,
8196 reject: reject
8197 });
8198 » » })
8199 » };
8200
8201 » Promise.resolve = function (value) {
8202 » » if (value && typeof value === 'object' && value.constructor === Promise) {
8203 » » » return value;
8204 » » }
8205
8206 » » return new Promise(function (resolve) {
8207 » » » resolve(value);
8208 » » });
8209 » };
8210
8211 » Promise.reject = function (value) {
8212 » » return new Promise(function (resolve, reject) {
8213 » » » reject(value);
8214 » » });
8215 » };
8216
8217 »
8218 return Promise;
8219 }
8220
8221 if (typeof module !== 'undefined') {
8222 module.exports = MakePromise;
8223 }
8224
8225 </script>
8226 <script>
8227 if (!window.Promise) {
8228 window.Promise = MakePromise(Polymer.Base.async);
8229 }
8230 </script>
8231 <script>
8232 'use strict';
8233
8234 Polymer({
8235 is: 'iron-request',
8236
8237 hostAttributes: {
8238 hidden: true
8239 },
8240
8241 properties: {
8242
8243 /**
8244 * A reference to the XMLHttpRequest instance used to generate the
8245 * network request.
8246 *
8247 * @type {XMLHttpRequest}
8248 */
8249 xhr: {
8250 type: Object,
8251 notify: true,
8252 readOnly: true,
8253 value: function() {
8254 return new XMLHttpRequest();
8255 } 8116 }
8117 if (busy) {
8118 this.set(busy, true);
8119 }
8120 url = url + "?" + sk.query.fromParamSet(params);
8121 sk.request("GET", url, "", headers).then(JSON.parse).then(function(json) {
8122 this.set(bindTo, json);
8123 if (busy) {
8124 this.set(busy, false);
8125 }
8126 }.bind(this)).catch(function(reason){
8127 console.log("Reason for failure of request to " + url, reason);
8128 this.set(bindTo, false);
8129 if (busy) {
8130 this.set(busy, false);
8131 }
8132 }.bind(this));
8256 }, 8133 },
8257 8134
8258 /** 8135 _not: function(a) {
8259 * A reference to the parsed response body, if the `xhr` has completely 8136 return !a;
8260 * resolved.
8261 *
8262 * @type {*}
8263 * @default null
8264 */
8265 response: {
8266 type: Object,
8267 notify: true,
8268 readOnly: true,
8269 value: function() {
8270 return null;
8271 }
8272 }, 8137 },
8273 8138
8274 /** 8139 _or: function() {
8275 * A reference to the status code, if the `xhr` has completely resolved. 8140 var result = false;
8276 */ 8141 // can't use .foreach, as arguments isn't really an Array.
8277 status: { 8142 for (var i = 0; i < arguments.length; i++) {
8278 type: Number, 8143 result = result || arguments[i];
8279 notify: true, 8144 }
8280 readOnly: true, 8145 return result;
8281 value: 0
8282 }, 8146 },
8283 8147 };
8284 /** 8148 })();
8285 * A reference to the status text, if the `xhr` has completely resolved.
8286 */
8287 statusText: {
8288 type: String,
8289 notify: true,
8290 readOnly: true,
8291 value: ''
8292 },
8293
8294 /**
8295 * A promise that resolves when the `xhr` response comes back, or rejects
8296 * if there is an error before the `xhr` completes.
8297 *
8298 * @type {Promise}
8299 */
8300 completes: {
8301 type: Object,
8302 readOnly: true,
8303 notify: true,
8304 value: function() {
8305 return new Promise(function (resolve, reject) {
8306 this.resolveCompletes = resolve;
8307 this.rejectCompletes = reject;
8308 }.bind(this));
8309 }
8310 },
8311
8312 /**
8313 * An object that contains progress information emitted by the XHR if
8314 * available.
8315 *
8316 * @default {}
8317 */
8318 progress: {
8319 type: Object,
8320 notify: true,
8321 readOnly: true,
8322 value: function() {
8323 return {};
8324 }
8325 },
8326
8327 /**
8328 * Aborted will be true if an abort of the request is attempted.
8329 */
8330 aborted: {
8331 type: Boolean,
8332 notify: true,
8333 readOnly: true,
8334 value: false,
8335 },
8336
8337 /**
8338 * Errored will be true if the browser fired an error event from the
8339 * XHR object (mainly network errors).
8340 */
8341 errored: {
8342 type: Boolean,
8343 notify: true,
8344 readOnly: true,
8345 value: false
8346 },
8347
8348 /**
8349 * TimedOut will be true if the XHR threw a timeout event.
8350 */
8351 timedOut: {
8352 type: Boolean,
8353 notify: true,
8354 readOnly: true,
8355 value: false
8356 }
8357 },
8358
8359 /**
8360 * Succeeded is true if the request succeeded. The request succeeded if it
8361 * loaded without error, wasn't aborted, and the status code is ≥ 200, and
8362 * < 300, or if the status code is 0.
8363 *
8364 * The status code 0 is accepted as a success because some schemes - e.g.
8365 * file:// - don't provide status codes.
8366 *
8367 * @return {boolean}
8368 */
8369 get succeeded() {
8370 if (this.errored || this.aborted || this.timedOut) {
8371 return false;
8372 }
8373 var status = this.xhr.status || 0;
8374
8375 // Note: if we are using the file:// protocol, the status code will be 0
8376 // for all outcomes (successful or otherwise).
8377 return status === 0 ||
8378 (status >= 200 && status < 300);
8379 },
8380
8381 /**
8382 * Sends an HTTP request to the server and returns the XHR object.
8383 *
8384 * The handling of the `body` parameter will vary based on the Content-Type
8385 * header. See the docs for iron-ajax's `body` param for details.
8386 *
8387 * @param {{
8388 * url: string,
8389 * method: (string|undefined),
8390 * async: (boolean|undefined),
8391 * body: (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|u ndefined|Object),
8392 * headers: (Object|undefined),
8393 * handleAs: (string|undefined),
8394 * jsonPrefix: (string|undefined),
8395 * withCredentials: (boolean|undefined)}} options -
8396 * url The url to which the request is sent.
8397 * method The HTTP method to use, default is GET.
8398 * async By default, all requests are sent asynchronously. To send synch ronous requests,
8399 * set to false.
8400 * body The content for the request body for POST method.
8401 * headers HTTP request headers.
8402 * handleAs The response type. Default is 'text'.
8403 * withCredentials Whether or not to send credentials on the request. De fault is false.
8404 * timeout: (Number|undefined)
8405 * @return {Promise}
8406 */
8407 send: function (options) {
8408 var xhr = this.xhr;
8409
8410 if (xhr.readyState > 0) {
8411 return null;
8412 }
8413
8414 xhr.addEventListener('progress', function (progress) {
8415 this._setProgress({
8416 lengthComputable: progress.lengthComputable,
8417 loaded: progress.loaded,
8418 total: progress.total
8419 });
8420 }.bind(this))
8421
8422 xhr.addEventListener('error', function (error) {
8423 this._setErrored(true);
8424 this._updateStatus();
8425 this.rejectCompletes(error);
8426 }.bind(this));
8427
8428 xhr.addEventListener('timeout', function (error) {
8429 this._setTimedOut(true);
8430 this._updateStatus();
8431 this.rejectCompletes(error);
8432 }.bind(this));
8433
8434 xhr.addEventListener('abort', function () {
8435 this._updateStatus();
8436 this.rejectCompletes(new Error('Request aborted.'));
8437 }.bind(this));
8438
8439 // Called after all of the above.
8440 xhr.addEventListener('loadend', function () {
8441 this._updateStatus();
8442 this._setResponse(this.parseResponse());
8443
8444 if (!this.succeeded) {
8445 this.rejectCompletes(new Error('The request failed with status code: ' + this.xhr.status));
8446 return;
8447 }
8448
8449 this.resolveCompletes(this);
8450 }.bind(this));
8451
8452 this.url = options.url;
8453 xhr.open(
8454 options.method || 'GET',
8455 options.url,
8456 options.async !== false
8457 );
8458
8459 var acceptType = {
8460 'json': 'application/json',
8461 'text': 'text/plain',
8462 'html': 'text/html',
8463 'xml': 'application/xml',
8464 'arraybuffer': 'application/octet-stream'
8465 }[options.handleAs];
8466 var headers = options.headers || Object.create(null);
8467 var newHeaders = Object.create(null);
8468 for (var key in headers) {
8469 newHeaders[key.toLowerCase()] = headers[key];
8470 }
8471 headers = newHeaders;
8472
8473 if (acceptType && !headers['accept']) {
8474 headers['accept'] = acceptType;
8475 }
8476 Object.keys(headers).forEach(function (requestHeader) {
8477 if (/[A-Z]/.test(requestHeader)) {
8478 Polymer.Base._error('Headers must be lower case, got', requestHeader);
8479 }
8480 xhr.setRequestHeader(
8481 requestHeader,
8482 headers[requestHeader]
8483 );
8484 }, this);
8485
8486 if (options.async !== false) {
8487 if (options.async) {
8488 xhr.timeout = options.timeout;
8489 }
8490
8491 var handleAs = options.handleAs;
8492
8493 // If a JSON prefix is present, the responseType must be 'text' or the
8494 // browser won’t be able to parse the response.
8495 if (!!options.jsonPrefix || !handleAs) {
8496 handleAs = 'text';
8497 }
8498
8499 // In IE, `xhr.responseType` is an empty string when the response
8500 // returns. Hence, caching it as `xhr._responseType`.
8501 xhr.responseType = xhr._responseType = handleAs;
8502
8503 // Cache the JSON prefix, if it exists.
8504 if (!!options.jsonPrefix) {
8505 xhr._jsonPrefix = options.jsonPrefix;
8506 }
8507 }
8508
8509 xhr.withCredentials = !!options.withCredentials;
8510
8511
8512 var body = this._encodeBodyObject(options.body, headers['content-type']);
8513
8514 xhr.send(
8515 /** @type {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|
8516 null|string|undefined} */
8517 (body));
8518
8519 return this.completes;
8520 },
8521
8522 /**
8523 * Attempts to parse the response body of the XHR. If parsing succeeds,
8524 * the value returned will be deserialized based on the `responseType`
8525 * set on the XHR.
8526 *
8527 * @return {*} The parsed response,
8528 * or undefined if there was an empty response or parsing failed.
8529 */
8530 parseResponse: function () {
8531 var xhr = this.xhr;
8532 var responseType = xhr.responseType || xhr._responseType;
8533 var preferResponseText = !this.xhr.responseType;
8534 var prefixLen = (xhr._jsonPrefix && xhr._jsonPrefix.length) || 0;
8535
8536 try {
8537 switch (responseType) {
8538 case 'json':
8539 // If the xhr object doesn't have a natural `xhr.responseType`,
8540 // we can assume that the browser hasn't parsed the response for us,
8541 // and so parsing is our responsibility. Likewise if response is
8542 // undefined, as there's no way to encode undefined in JSON.
8543 if (preferResponseText || xhr.response === undefined) {
8544 // Try to emulate the JSON section of the response body section of
8545 // the spec: https://xhr.spec.whatwg.org/#response-body
8546 // That is to say, we try to parse as JSON, but if anything goes
8547 // wrong return null.
8548 try {
8549 return JSON.parse(xhr.responseText);
8550 } catch (_) {
8551 return null;
8552 }
8553 }
8554
8555 return xhr.response;
8556 case 'xml':
8557 return xhr.responseXML;
8558 case 'blob':
8559 case 'document':
8560 case 'arraybuffer':
8561 return xhr.response;
8562 case 'text':
8563 default: {
8564 // If `prefixLen` is set, it implies the response should be parsed
8565 // as JSON once the prefix of length `prefixLen` is stripped from
8566 // it. Emulate the behavior above where null is returned on failure
8567 // to parse.
8568 if (prefixLen) {
8569 try {
8570 return JSON.parse(xhr.responseText.substring(prefixLen));
8571 } catch (_) {
8572 return null;
8573 }
8574 }
8575 return xhr.responseText;
8576 }
8577 }
8578 } catch (e) {
8579 this.rejectCompletes(new Error('Could not parse response. ' + e.message) );
8580 }
8581 },
8582
8583 /**
8584 * Aborts the request.
8585 */
8586 abort: function () {
8587 this._setAborted(true);
8588 this.xhr.abort();
8589 },
8590
8591 /**
8592 * @param {*} body The given body of the request to try and encode.
8593 * @param {?string} contentType The given content type, to infer an encoding
8594 * from.
8595 * @return {*} Either the encoded body as a string, if successful,
8596 * or the unaltered body object if no encoding could be inferred.
8597 */
8598 _encodeBodyObject: function(body, contentType) {
8599 if (typeof body == 'string') {
8600 return body; // Already encoded.
8601 }
8602 var bodyObj = /** @type {Object} */ (body);
8603 switch(contentType) {
8604 case('application/json'):
8605 return JSON.stringify(bodyObj);
8606 case('application/x-www-form-urlencoded'):
8607 return this._wwwFormUrlEncode(bodyObj);
8608 }
8609 return body;
8610 },
8611
8612 /**
8613 * @param {Object} object The object to encode as x-www-form-urlencoded.
8614 * @return {string} .
8615 */
8616 _wwwFormUrlEncode: function(object) {
8617 if (!object) {
8618 return '';
8619 }
8620 var pieces = [];
8621 Object.keys(object).forEach(function(key) {
8622 // TODO(rictic): handle array values here, in a consistent way with
8623 // iron-ajax params.
8624 pieces.push(
8625 this._wwwFormUrlEncodePiece(key) + '=' +
8626 this._wwwFormUrlEncodePiece(object[key]));
8627 }, this);
8628 return pieces.join('&');
8629 },
8630
8631 /**
8632 * @param {*} str A key or value to encode as x-www-form-urlencoded.
8633 * @return {string} .
8634 */
8635 _wwwFormUrlEncodePiece: function(str) {
8636 // Spec says to normalize newlines to \r\n and replace %20 spaces with +.
8637 // jQuery does this as well, so this is likely to be widely compatible.
8638 if (str === null) {
8639 return '';
8640 }
8641 return encodeURIComponent(str.toString().replace(/\r?\n/g, '\r\n'))
8642 .replace(/%20/g, '+');
8643 },
8644
8645 /**
8646 * Updates the status code and status text.
8647 */
8648 _updateStatus: function() {
8649 this._setStatus(this.xhr.status);
8650 this._setStatusText((this.xhr.statusText === undefined) ? '' : this.xhr.st atusText);
8651 }
8652 });
8653 </script> 8149 </script>
8654
8655 <script>
8656 'use strict';
8657
8658 Polymer({
8659
8660 is: 'iron-ajax',
8661
8662 /**
8663 * Fired when a request is sent.
8664 *
8665 * @event request
8666 * @event iron-ajax-request
8667 */
8668
8669 /**
8670 * Fired when a response is received.
8671 *
8672 * @event response
8673 * @event iron-ajax-response
8674 */
8675
8676 /**
8677 * Fired when an error is received.
8678 *
8679 * @event error
8680 * @event iron-ajax-error
8681 */
8682
8683 hostAttributes: {
8684 hidden: true
8685 },
8686
8687 properties: {
8688 /**
8689 * The URL target of the request.
8690 */
8691 url: {
8692 type: String
8693 },
8694
8695 /**
8696 * An object that contains query parameters to be appended to the
8697 * specified `url` when generating a request. If you wish to set the body
8698 * content when making a POST request, you should use the `body` property
8699 * instead.
8700 */
8701 params: {
8702 type: Object,
8703 value: function() {
8704 return {};
8705 }
8706 },
8707
8708 /**
8709 * The HTTP method to use such as 'GET', 'POST', 'PUT', or 'DELETE'.
8710 * Default is 'GET'.
8711 */
8712 method: {
8713 type: String,
8714 value: 'GET'
8715 },
8716
8717 /**
8718 * HTTP request headers to send.
8719 *
8720 * Example:
8721 *
8722 * <iron-ajax
8723 * auto
8724 * url="http://somesite.com"
8725 * headers='{"X-Requested-With": "XMLHttpRequest"}'
8726 * handle-as="json"></iron-ajax>
8727 *
8728 * Note: setting a `Content-Type` header here will override the value
8729 * specified by the `contentType` property of this element.
8730 */
8731 headers: {
8732 type: Object,
8733 value: function() {
8734 return {};
8735 }
8736 },
8737
8738 /**
8739 * Content type to use when sending data. If the `contentType` property
8740 * is set and a `Content-Type` header is specified in the `headers`
8741 * property, the `headers` property value will take precedence.
8742 *
8743 * Varies the handling of the `body` param.
8744 */
8745 contentType: {
8746 type: String,
8747 value: null
8748 },
8749
8750 /**
8751 * Body content to send with the request, typically used with "POST"
8752 * requests.
8753 *
8754 * If body is a string it will be sent unmodified.
8755 *
8756 * If Content-Type is set to a value listed below, then
8757 * the body will be encoded accordingly.
8758 *
8759 * * `content-type="application/json"`
8760 * * body is encoded like `{"foo":"bar baz","x":1}`
8761 * * `content-type="application/x-www-form-urlencoded"`
8762 * * body is encoded like `foo=bar+baz&x=1`
8763 *
8764 * Otherwise the body will be passed to the browser unmodified, and it
8765 * will handle any encoding (e.g. for FormData, Blob, ArrayBuffer).
8766 *
8767 * @type (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|u ndefined|Object)
8768 */
8769 body: {
8770 type: Object,
8771 value: null
8772 },
8773
8774 /**
8775 * Toggle whether XHR is synchronous or asynchronous. Don't change this
8776 * to true unless You Know What You Are Doingâ„¢.
8777 */
8778 sync: {
8779 type: Boolean,
8780 value: false
8781 },
8782
8783 /**
8784 * Specifies what data to store in the `response` property, and
8785 * to deliver as `event.detail.response` in `response` events.
8786 *
8787 * One of:
8788 *
8789 * `text`: uses `XHR.responseText`.
8790 *
8791 * `xml`: uses `XHR.responseXML`.
8792 *
8793 * `json`: uses `XHR.responseText` parsed as JSON.
8794 *
8795 * `arraybuffer`: uses `XHR.response`.
8796 *
8797 * `blob`: uses `XHR.response`.
8798 *
8799 * `document`: uses `XHR.response`.
8800 */
8801 handleAs: {
8802 type: String,
8803 value: 'json'
8804 },
8805
8806 /**
8807 * Set the withCredentials flag on the request.
8808 */
8809 withCredentials: {
8810 type: Boolean,
8811 value: false
8812 },
8813
8814 /**
8815 * Set the timeout flag on the request.
8816 */
8817 timeout: {
8818 type: Number,
8819 value: 0
8820 },
8821
8822 /**
8823 * If true, automatically performs an Ajax request when either `url` or
8824 * `params` changes.
8825 */
8826 auto: {
8827 type: Boolean,
8828 value: false
8829 },
8830
8831 /**
8832 * If true, error messages will automatically be logged to the console.
8833 */
8834 verbose: {
8835 type: Boolean,
8836 value: false
8837 },
8838
8839 /**
8840 * The most recent request made by this iron-ajax element.
8841 */
8842 lastRequest: {
8843 type: Object,
8844 notify: true,
8845 readOnly: true
8846 },
8847
8848 /**
8849 * True while lastRequest is in flight.
8850 */
8851 loading: {
8852 type: Boolean,
8853 notify: true,
8854 readOnly: true
8855 },
8856
8857 /**
8858 * lastRequest's response.
8859 *
8860 * Note that lastResponse and lastError are set when lastRequest finishes,
8861 * so if loading is true, then lastResponse and lastError will correspond
8862 * to the result of the previous request.
8863 *
8864 * The type of the response is determined by the value of `handleAs` at
8865 * the time that the request was generated.
8866 *
8867 * @type {Object}
8868 */
8869 lastResponse: {
8870 type: Object,
8871 notify: true,
8872 readOnly: true
8873 },
8874
8875 /**
8876 * lastRequest's error, if any.
8877 *
8878 * @type {Object}
8879 */
8880 lastError: {
8881 type: Object,
8882 notify: true,
8883 readOnly: true
8884 },
8885
8886 /**
8887 * An Array of all in-flight requests originating from this iron-ajax
8888 * element.
8889 */
8890 activeRequests: {
8891 type: Array,
8892 notify: true,
8893 readOnly: true,
8894 value: function() {
8895 return [];
8896 }
8897 },
8898
8899 /**
8900 * Length of time in milliseconds to debounce multiple automatically gener ated requests.
8901 */
8902 debounceDuration: {
8903 type: Number,
8904 value: 0,
8905 notify: true
8906 },
8907
8908 /**
8909 * Prefix to be stripped from a JSON response before parsing it.
8910 *
8911 * In order to prevent an attack using CSRF with Array responses
8912 * (http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnera bility.aspx/)
8913 * many backends will mitigate this by prefixing all JSON response bodies
8914 * with a string that would be nonsensical to a JavaScript parser.
8915 *
8916 */
8917 jsonPrefix: {
8918 type: String,
8919 value: ''
8920 },
8921
8922 /**
8923 * By default, iron-ajax's events do not bubble. Setting this attribute wi ll cause its
8924 * request and response events as well as its iron-ajax-request, -response , and -error
8925 * events to bubble to the window object. The vanilla error event never bu bbles when
8926 * using shadow dom even if this.bubbles is true because a scoped flag is not passed with
8927 * it (first link) and because the shadow dom spec did not used to allow c ertain events,
8928 * including events named error, to leak outside of shadow trees (second l ink).
8929 * https://www.w3.org/TR/shadow-dom/#scoped-flag
8930 * https://www.w3.org/TR/2015/WD-shadow-dom-20151215/#events-that-are-not- leaked-into-ancestor-trees
8931 */
8932 bubbles: {
8933 type: Boolean,
8934 value: false
8935 },
8936
8937 _boundHandleResponse: {
8938 type: Function,
8939 value: function() {
8940 return this._handleResponse.bind(this);
8941 }
8942 }
8943 },
8944
8945 observers: [
8946 '_requestOptionsChanged(url, method, params.*, headers, contentType, ' +
8947 'body, sync, handleAs, jsonPrefix, withCredentials, timeout, auto)'
8948 ],
8949
8950 /**
8951 * The query string that should be appended to the `url`, serialized from
8952 * the current value of `params`.
8953 *
8954 * @return {string}
8955 */
8956 get queryString () {
8957 var queryParts = [];
8958 var param;
8959 var value;
8960
8961 for (param in this.params) {
8962 value = this.params[param];
8963 param = window.encodeURIComponent(param);
8964
8965 if (Array.isArray(value)) {
8966 for (var i = 0; i < value.length; i++) {
8967 queryParts.push(param + '=' + window.encodeURIComponent(value[i]));
8968 }
8969 } else if (value !== null) {
8970 queryParts.push(param + '=' + window.encodeURIComponent(value));
8971 } else {
8972 queryParts.push(param);
8973 }
8974 }
8975
8976 return queryParts.join('&');
8977 },
8978
8979 /**
8980 * The `url` with query string (if `params` are specified), suitable for
8981 * providing to an `iron-request` instance.
8982 *
8983 * @return {string}
8984 */
8985 get requestUrl() {
8986 var queryString = this.queryString;
8987 var url = this.url || '';
8988
8989 if (queryString) {
8990 var bindingChar = url.indexOf('?') >= 0 ? '&' : '?';
8991 return url + bindingChar + queryString;
8992 }
8993
8994 return url;
8995 },
8996
8997 /**
8998 * An object that maps header names to header values, first applying the
8999 * the value of `Content-Type` and then overlaying the headers specified
9000 * in the `headers` property.
9001 *
9002 * @return {Object}
9003 */
9004 get requestHeaders() {
9005 var headers = {};
9006 var contentType = this.contentType;
9007 if (contentType == null && (typeof this.body === 'string')) {
9008 contentType = 'application/x-www-form-urlencoded';
9009 }
9010 if (contentType) {
9011 headers['content-type'] = contentType;
9012 }
9013 var header;
9014
9015 if (this.headers instanceof Object) {
9016 for (header in this.headers) {
9017 headers[header] = this.headers[header].toString();
9018 }
9019 }
9020
9021 return headers;
9022 },
9023
9024 /**
9025 * Request options suitable for generating an `iron-request` instance based
9026 * on the current state of the `iron-ajax` instance's properties.
9027 *
9028 * @return {{
9029 * url: string,
9030 * method: (string|undefined),
9031 * async: (boolean|undefined),
9032 * body: (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|u ndefined|Object),
9033 * headers: (Object|undefined),
9034 * handleAs: (string|undefined),
9035 * jsonPrefix: (string|undefined),
9036 * withCredentials: (boolean|undefined)}}
9037 */
9038 toRequestOptions: function() {
9039 return {
9040 url: this.requestUrl || '',
9041 method: this.method,
9042 headers: this.requestHeaders,
9043 body: this.body,
9044 async: !this.sync,
9045 handleAs: this.handleAs,
9046 jsonPrefix: this.jsonPrefix,
9047 withCredentials: this.withCredentials,
9048 timeout: this.timeout
9049 };
9050 },
9051
9052 /**
9053 * Performs an AJAX request to the specified URL.
9054 *
9055 * @return {!IronRequestElement}
9056 */
9057 generateRequest: function() {
9058 var request = /** @type {!IronRequestElement} */ (document.createElement(' iron-request'));
9059 var requestOptions = this.toRequestOptions();
9060
9061 this.push('activeRequests', request);
9062
9063 request.completes.then(
9064 this._boundHandleResponse
9065 ).catch(
9066 this._handleError.bind(this, request)
9067 ).then(
9068 this._discardRequest.bind(this, request)
9069 );
9070
9071 request.send(requestOptions);
9072
9073 this._setLastRequest(request);
9074 this._setLoading(true);
9075
9076 this.fire('request', {
9077 request: request,
9078 options: requestOptions
9079 }, {bubbles: this.bubbles});
9080
9081 this.fire('iron-ajax-request', {
9082 request: request,
9083 options: requestOptions
9084 }, {bubbles: this.bubbles});
9085
9086 return request;
9087 },
9088
9089 _handleResponse: function(request) {
9090 if (request === this.lastRequest) {
9091 this._setLastResponse(request.response);
9092 this._setLastError(null);
9093 this._setLoading(false);
9094 }
9095 this.fire('response', request, {bubbles: this.bubbles});
9096 this.fire('iron-ajax-response', request, {bubbles: this.bubbles});
9097 },
9098
9099 _handleError: function(request, error) {
9100 if (this.verbose) {
9101 Polymer.Base._error(error);
9102 }
9103
9104 if (request === this.lastRequest) {
9105 this._setLastError({
9106 request: request,
9107 error: error,
9108 status: request.xhr.status,
9109 statusText: request.xhr.statusText,
9110 response: request.xhr.response
9111 });
9112 this._setLastResponse(null);
9113 this._setLoading(false);
9114 }
9115
9116 // Tests fail if this goes after the normal this.fire('error', ...)
9117 this.fire('iron-ajax-error', {
9118 request: request,
9119 error: error
9120 }, {bubbles: this.bubbles});
9121
9122 this.fire('error', {
9123 request: request,
9124 error: error
9125 }, {bubbles: this.bubbles});
9126 },
9127
9128 _discardRequest: function(request) {
9129 var requestIndex = this.activeRequests.indexOf(request);
9130
9131 if (requestIndex > -1) {
9132 this.splice('activeRequests', requestIndex, 1);
9133 }
9134 },
9135
9136 _requestOptionsChanged: function() {
9137 this.debounce('generate-request', function() {
9138 if (this.url == null) {
9139 return;
9140 }
9141
9142 if (this.auto) {
9143 this.generateRequest();
9144 }
9145 }, this.debounceDuration);
9146 },
9147
9148 });
9149 </script>
9150
9151
9152 <script> 8150 <script>
9153 Polymer.AppLayout = Polymer.AppLayout || {}; 8151 Polymer.AppLayout = Polymer.AppLayout || {};
9154 8152
9155 Polymer.AppLayout._scrollEffects = Polymer.AppLayout._scrollEffects || {}; 8153 Polymer.AppLayout._scrollEffects = Polymer.AppLayout._scrollEffects || {};
9156 8154
9157 Polymer.AppLayout.scrollTimingFunction = function easeOutQuad(t, b, c, d) { 8155 Polymer.AppLayout.scrollTimingFunction = function easeOutQuad(t, b, c, d) {
9158 t /= d; 8156 t /= d;
9159 return -c * t*(t-2) + b; 8157 return -c * t*(t-2) + b;
9160 }; 8158 };
9161 8159
(...skipping 5409 matching lines...) Expand 10 before | Expand all | Expand 10 after
14571 } 13569 }
14572 13570
14573 paper-spinner-lite { 13571 paper-spinner-lite {
14574 --paper-spinner-color: var(--google-yellow-500); 13572 --paper-spinner-color: var(--google-yellow-500);
14575 } 13573 }
14576 </style> 13574 </style>
14577 <app-header-layout> 13575 <app-header-layout>
14578 <app-header fixed=""> 13576 <app-header fixed="">
14579 <app-toolbar> 13577 <app-toolbar>
14580 <div class="title left">[[name]]</div> 13578 <div class="title left">[[name]]</div>
14581 <paper-spinner-lite class="left" active="[[busy]]"></paper-spinner-lit e> 13579 <paper-spinner-lite class="left" active="[[_or(busy,_busy)]]"></paper- spinner-lite>
14582 13580
14583 <a class="left" href="/newui/">Home</a> 13581 <a class="left" href="/newui/">Home</a>
14584 <a class="left" href="/newui/botlist">Bot List</a> 13582 <a class="left" href="/newui/botlist">Bot List</a>
14585 <a class="left" href="/newui/tasklist">Task List</a> 13583 <a class="left" href="/newui/tasklist">Task List</a>
14586 <div class="flex"></div> 13584 <div class="flex"></div>
14587 <auth-signin class="right" client-id="[[client_id]]" auth-headers="{{a uth_headers}}" signed-in="{{signed_in}}"> 13585 <auth-signin class="right" client-id="[[client_id]]" auth-headers="{{a uth_headers}}" signed-in="{{signed_in}}">
14588 </auth-signin> 13586 </auth-signin>
14589 </app-toolbar> 13587 </app-toolbar>
14590 </app-header> 13588 </app-header>
14591 <div class="main-content"> 13589 <div class="main-content">
14592 <content></content> 13590 <content></content>
14593 </div> 13591 </div>
14594 </app-header-layout> 13592 </app-header-layout>
14595 13593
14596 </template> 13594 </template>
14597 <script> 13595 <script>
14598 Polymer({ 13596 Polymer({
14599 is: 'swarming-app', 13597 is: 'swarming-app',
13598
13599 behaviors: [
13600 SwarmingBehaviors.CommonBehavior,
13601 ],
13602
14600 properties: { 13603 properties: {
13604 // input
13605 busy: {
13606 type: Boolean,
13607 },
14601 client_id: { 13608 client_id: {
14602 type: String, 13609 type: String,
14603 }, 13610 },
13611 name: {
13612 type: String,
13613 },
13614 // outputs
14604 auth_headers: { 13615 auth_headers: {
14605 type: Object, 13616 type: Object,
14606 notify: true, 13617 notify: true,
13618 observer: "_loadPermissions"
14607 }, 13619 },
13620
13621 permissions: {
13622 type: Object,
13623 value: function() {
13624 // If we aren't logged in, default to no permissions.
13625 return {};
13626 },
13627 notify: true,
13628 },
13629
14608 signed_in: { 13630 signed_in: {
14609 type: Boolean, 13631 type: Boolean,
14610 value: false, 13632 value: false,
14611 notify:true, 13633 notify:true,
14612 }, 13634 },
14613 permissions: {
14614 type: Object,
14615 value: function() {
14616 // TODO(kjlubick): Make this call the whoami endpoint after signing in.
14617 return {
14618 can_cancel_task: true,
14619 }
14620 },
14621 notify: true,
14622 },
14623 13635
14624 busy: { 13636 // private
13637 _busy: {
14625 type: Boolean, 13638 type: Boolean,
14626 }, 13639 value: false,
14627 name: { 13640 }
14628 type: String, 13641
14629 }, 13642 },
13643
13644 _loadPermissions: function() {
13645 this._getJsonAsync("permissions", "/_ah/api/swarming/v1/server/permissio ns",
13646 "_busy", this.auth_headers);
14630 }, 13647 },
14631 13648
14632 }); 13649 });
14633 </script> 13650 </script>
14634 </dom-module> 13651 </dom-module>
14635 13652
14636 <dom-module id="swarming-app-style" assetpath="/res/imp/common/"> 13653 <dom-module id="swarming-app-style" assetpath="/res/imp/common/">
14637 <style> 13654 <style>
14638 * { 13655 * {
14639 font-family: sans-serif; 13656 font-family: sans-serif;
14640 } 13657 }
14641 /* Only style anchor tags that are actually linking somewhere.*/ 13658 /* Only style anchor tags that are actually linking somewhere.*/
14642 a[href] { 13659 a[href] {
14643 color: #1F78B4; 13660 color: #1F78B4;
14644 } 13661 }
14645 </style> 13662 </style>
14646 </dom-module> 13663 </dom-module>
14647 <dom-module id="swarming-index" assetpath="/res/imp/index/"> 13664 <dom-module id="swarming-index" assetpath="/res/imp/index/">
14648 <template> 13665 <template>
14649 <style include="swarming-app-style"> 13666 <style include="swarming-app-style">
14650 13667 .command {
13668 font-family: monospace;
13669 margin-bottom: 10px;
13670 margin-top: 10px;
13671 white-space: pre-wrap;
13672 background-color: #f5f5f5;
13673 border: 1px solid #ccc;
13674 border-radius: 4px;
13675 }
14651 </style> 13676 </style>
14652 13677
14653 <swarming-app client_id="[[client_id]]" auth_headers="{{auth_headers}}" name ="Swarming" busy="[[busy]]"> 13678 <swarming-app client_id="[[client_id]]" auth_headers="{{auth_headers}}" perm issions="{{_permissions}}" name="Swarming Server" busy="[[_busy]]">
14654 13679
14655 <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers= "[[auth_headers]]" handle-as="json" last-response="{{serverDetails}}" loading="{ {busy}}"> 13680 <h2>Service Status</h2>
14656 </iron-ajax> 13681 <div>Server Version: [[serverDetails.server_version]]</div>
13682 <ul>
13683 <li>
13684
13685 <a href="/stats">Usage statistics</a>
13686 </li>
13687 <li>
13688 <a href="/restricted/mapreduce/status">Map Reduce Jobs</a>
13689 </li>
13690 <li>
13691 <a href$="[[_makeInstancesUrl(serverDetails,_project_id)]]">View versi on's instances on Cloud Console</a>
13692 </li>
13693 <li>
13694 <a></a><a href$="[[_makeErrorUrl(_project_id)]]">View server errors on Cloud Console</a>
13695 </li>
13696 <li>
13697 <a></a><a href$="[[_makeLogUrl(_project_id)]]">View logs for HTTP 5xx on Cloud Console</a>
13698 </li>
13699 </ul>
14657 13700
14658 <h1>HELLO WORLD</h1> 13701 <h2>Configuration</h2>
13702 <ul>
13703
13704 <li>
13705 <a href="/restricted/config">View server config</a>
13706 </li>
13707 <li>
13708 <a href="/restricted/upload/bootstrap">View/upload bootstrap.py</a>
13709 </li>
13710 <li>
13711 <a href="/restricted/upload/bot_config">View/upload bot_config.py</a>
13712 </li>
13713 <li>
13714 <a href="/auth/groups">View/edit user groups</a>
13715 </li>
13716 </ul>
14659 13717
14660 <div>Server Version: [[serverDetails.server_version]]</div> 13718 <div hidden$="[[_cannotBootstrap(_permissions)]]">
13719 <h2>Bootstrapping a bot</h2>
13720 To bootstrap a bot, run one of these (all links are valid for 1 hour):
13721 <ol>
13722 <li>
13723 <strong> TL;DR; </strong>
13724 <pre class="command">python -c "import urllib; exec urllib.urlopen('[[_host_ur l]]/bootstrap?tok=[[_bootstrap_token]]').read()"</pre>
13725 </li>
13726 <li>
13727 Escaped version to pass as a ssh argument:
13728 <pre class="command">'python -c "import urllib; exec urllib.urlopen('"'[[_host _url]]/bootstrap?tok=[[_bootstrap_token]]'"').read()"'</pre>
13729 </li>
13730 <li>
13731 Manually:
13732 <pre class="command" style="margin-bottom:0">mkdir bot; cd bot
13733 rm -f swarming_bot.zip; curl -sSLOJ [[_host_url]]/bot_code?tok=[[_bootstrap_to ken]]
13734 python swarming_bot.zip</pre>
13735 </li>
13736 </ol>
13737 </div>
13738
13739 <h2>Stats</h2>
13740 <div>TODO(kjlubick) add these in</div>
13741
14661 13742
14662 </swarming-app> 13743 </swarming-app>
14663 13744
14664 </template> 13745 </template>
14665 <script> 13746 <script>
14666 Polymer({ 13747 Polymer({
14667 is: 'swarming-index', 13748 is: 'swarming-index',
14668 13749
13750 behaviors: [
13751 SwarmingBehaviors.CommonBehavior,
13752 ],
13753
14669 properties: { 13754 properties: {
14670 client_id: { 13755 client_id: {
14671 type: String, 13756 type: String,
14672 }, 13757 },
14673 13758
14674 auth_headers: { 13759 auth_headers: {
14675 type: Object, 13760 type: Object,
14676 observer: "signIn", 13761 observer: "signIn",
14677 }, 13762 },
14678 13763
14679 serverDetails: { 13764 serverDetails: {
13765 type: Object,
13766 },
13767
13768 _bootstrap_token: {
14680 type: String, 13769 type: String,
13770 // TODO(kjlubick): fetch this from an API
13771 value: "abc123",
13772 },
13773 _busy: {
13774 type: Boolean,
13775 value: false,
13776 },
13777 _host_url: {
13778 type: String,
13779 value: function() {
13780 return location.origin;
13781 },
13782 },
13783 _permissions: {
13784 type: Object,
13785 },
13786 _project_id: {
13787 type: String,
13788 value: function() {
13789 var idx = location.hostname.indexOf(".appspot.com");
13790 return location.hostname.substring(0, idx);
13791 },
14681 } 13792 }
14682 }, 13793 },
14683 13794
14684 signIn: function(){ 13795 signIn: function(){
14685 this.$.request.generateRequest(); 13796 this._getJsonAsync("serverDetails", "/_ah/api/swarming/v1/server/details ",
13797 "_busy", this.auth_headers);
13798 },
13799
13800 _cannotBootstrap: function(permissions) {
13801 return !(permissions && permissions.get_bootstrap_token);
13802 },
13803
13804 _makeInstancesUrl: function(details, project_id) {
13805 return "https://console.cloud.google.com/appengine/instances?project="+
13806 project_id+"&versionId="+details.server_version;
13807 },
13808
13809 _makeErrorUrl: function(project_id) {
13810 return "https://console.cloud.google.com/errors?project="+
13811 project_id;
13812 },
13813
13814 _makeLogUrl: function(project_id) {
13815 return "https://pantheon.corp.google.com/logs/viewer?filters=text:status :500..599&project="+
13816 project_id;
14686 }, 13817 },
14687 13818
14688 }); 13819 });
14689 </script> 13820 </script>
14690 </dom-module><script> 13821 </dom-module><dom-module id="dynamic-table-style" assetpath="/res/imp/common/">
14691 window.SwarmingBehaviors = window.SwarmingBehaviors || {};
14692 (function(){
14693 // This behavior wraps up all the shared swarming functionality.
14694 SwarmingBehaviors.CommonBehavior = {
14695
14696 // _getJsonAsync makes an XHR to a url, parses the response as JSON
14697 // and sticks the resulting object into the property with the name given
14698 // by "bindTo". If busy is defined, the property with that name will be
14699 // set to true while the request is in flight and false afterwards.
14700 // request headers (e.g. authentication) and query params will be used if
14701 // provided. Query params is an object like {String:Array<String>}. On
14702 // error, bindTo will be set to false. It is not set to undefined
14703 // because computed values in Polymer don't fire if a property is
14704 // undefined. Clients should check that bindTo is not falsey.
14705 _getJsonAsync: function(bindTo, url, busy, headers, params) {
14706 if (!bindTo || !url) {
14707 console.log("Need at least a polymer element to bind to and a url");
14708 return;
14709 }
14710 if (busy) {
14711 this.set(busy, true);
14712 }
14713 url = url + "?" + sk.query.fromParamSet(params);
14714 sk.request("GET", url, "", headers).then(JSON.parse).then(function(json) {
14715 this.set(bindTo, json);
14716 if (busy) {
14717 this.set(busy, false);
14718 }
14719 }.bind(this)).catch(function(reason){
14720 console.log("Reason for failure of request to " + url, reason);
14721 this.set(bindTo, false);
14722 if (busy) {
14723 this.set(busy, false);
14724 }
14725 }.bind(this));
14726 },
14727
14728 _not: function(a) {
14729 return !a;
14730 },
14731
14732 _or: function() {
14733 var result = false;
14734 // can't use .foreach, as arguments isn't really an Array.
14735 for (var i = 0; i < arguments.length; i++) {
14736 result = result || arguments[i];
14737 }
14738 return result;
14739 },
14740 };
14741 })();
14742 </script>
14743 <dom-module id="dynamic-table-style" assetpath="/res/imp/common/">
14744 <template> 13822 <template>
14745 <style> 13823 <style>
14746 table { 13824 table {
14747 border-collapse: collapse; 13825 border-collapse: collapse;
14748 margin-left: 5px; 13826 margin-left: 5px;
14749 } 13827 }
14750 td, th { 13828 td, th {
14751 border: 1px solid #DDD; 13829 border: 1px solid #DDD;
14752 padding: 5px; 13830 padding: 5px;
14753 } 13831 }
(...skipping 10471 matching lines...) Expand 10 before | Expand all | Expand 10 after
25225 def = "none"; 24303 def = "none";
25226 } 24304 }
25227 var retVal = this._tag(task, col) || task[col] || [def]; 24305 var retVal = this._tag(task, col) || task[col] || [def];
25228 if (!Array.isArray(retVal)) { 24306 if (!Array.isArray(retVal)) {
25229 return [retVal]; 24307 return [retVal];
25230 } 24308 }
25231 return retVal; 24309 return retVal;
25232 }, 24310 },
25233 24311
25234 _cannotCancel: function(task, permissions) { 24312 _cannotCancel: function(task, permissions) {
25235 return !(permissions && permissions.can_cancel_task && 24313 return !(permissions && permissions.cancel_task &&
25236 this._column("state", task) === "PENDING"); 24314 this._column("state", task) === "PENDING");
25237 }, 24315 },
25238 24316
25239 _cancelTask: function(e) { 24317 _cancelTask: function(e) {
25240 var task = e.model.task; 24318 var task = e.model.task;
25241 if (!task || !task.task_id) { 24319 if (!task || !task.task_id) {
25242 console.log("Missing task info", task); 24320 console.log("Missing task info", task);
25243 return 24321 return
25244 } 24322 }
25245 var id = task.task_id 24323 var id = task.task_id
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
25294 if (state === "RUNNING" || state === "PENDING") { 24372 if (state === "RUNNING" || state === "PENDING") {
25295 return "pending"; 24373 return "pending";
25296 } 24374 }
25297 return ""; 24375 return "";
25298 } 24376 }
25299 24377
25300 }); 24378 });
25301 })(); 24379 })();
25302 </script> 24380 </script>
25303 </dom-module></div></body></html> 24381 </dom-module></div></body></html>
OLDNEW
« no previous file with comments | « no previous file | appengine/swarming/elements/res/imp/common/auth-signin.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698