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

Unified 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, 4 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: appengine/swarming/elements/build/elements.html
diff --git a/appengine/swarming/elements/build/elements.html b/appengine/swarming/elements/build/elements.html
index 04f7bc5bddc0e84069d4e12aee5ea588594014dc..ca1e4793d932ae7f86ebd1aa79dfbb1b939bcc29 100644
--- a/appengine/swarming/elements/build/elements.html
+++ b/appengine/swarming/elements/build/elements.html
@@ -8094,1061 +8094,59 @@ this.fire('dom-change');
-<script>function MakePromise (asap) {
- function Promise(fn) {
- if (typeof this !== 'object' || typeof fn !== 'function') throw new TypeError();
- this._state = null;
- this._value = null;
- this._deferreds = []
-
- doResolve(fn, resolve.bind(this), reject.bind(this));
- }
-
- function handle(deferred) {
- var me = this;
- if (this._state === null) {
- this._deferreds.push(deferred);
- return
- }
- asap(function() {
- var cb = me._state ? deferred.onFulfilled : deferred.onRejected
- if (typeof cb !== 'function') {
- (me._state ? deferred.resolve : deferred.reject)(me._value);
- return;
- }
- var ret;
- try {
- ret = cb(me._value);
- }
- catch (e) {
- deferred.reject(e);
- return;
- }
- deferred.resolve(ret);
- })
- }
-
- function resolve(newValue) {
- try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
- if (newValue === this) throw new TypeError();
- if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
- var then = newValue.then;
- if (typeof then === 'function') {
- doResolve(then.bind(newValue), resolve.bind(this), reject.bind(this));
- return;
- }
- }
- this._state = true;
- this._value = newValue;
- finale.call(this);
- } catch (e) { reject.call(this, e); }
- }
-
- function reject(newValue) {
- this._state = false;
- this._value = newValue;
- finale.call(this);
- }
-
- function finale() {
- for (var i = 0, len = this._deferreds.length; i < len; i++) {
- handle.call(this, this._deferreds[i]);
- }
- this._deferreds = null;
- }
-
- /**
- * Take a potentially misbehaving resolver function and make sure
- * onFulfilled and onRejected are only called once.
- *
- * Makes no guarantees about asynchrony.
- */
- function doResolve(fn, onFulfilled, onRejected) {
- var done = false;
- try {
- fn(function (value) {
- if (done) return;
- done = true;
- onFulfilled(value);
- }, function (reason) {
- if (done) return;
- done = true;
- onRejected(reason);
- })
- } catch (ex) {
- if (done) return;
- done = true;
- onRejected(ex);
- }
- }
-
- Promise.prototype['catch'] = function (onRejected) {
- return this.then(null, onRejected);
- };
-
- Promise.prototype.then = function(onFulfilled, onRejected) {
- var me = this;
- return new Promise(function(resolve, reject) {
- handle.call(me, {
- onFulfilled: onFulfilled,
- onRejected: onRejected,
- resolve: resolve,
- reject: reject
- });
- })
- };
-
- Promise.resolve = function (value) {
- if (value && typeof value === 'object' && value.constructor === Promise) {
- return value;
- }
-
- return new Promise(function (resolve) {
- resolve(value);
- });
- };
-
- Promise.reject = function (value) {
- return new Promise(function (resolve, reject) {
- reject(value);
- });
- };
-
-
- return Promise;
-}
-
-if (typeof module !== 'undefined') {
- module.exports = MakePromise;
-}
-
-</script>
-<script>
-if (!window.Promise) {
- window.Promise = MakePromise(Polymer.Base.async);
-}
-</script>
<script>
- 'use strict';
-
- Polymer({
- is: 'iron-request',
-
- hostAttributes: {
- hidden: true
- },
-
- properties: {
-
- /**
- * A reference to the XMLHttpRequest instance used to generate the
- * network request.
- *
- * @type {XMLHttpRequest}
- */
- xhr: {
- type: Object,
- notify: true,
- readOnly: true,
- value: function() {
- return new XMLHttpRequest();
- }
- },
-
- /**
- * A reference to the parsed response body, if the `xhr` has completely
- * resolved.
- *
- * @type {*}
- * @default null
- */
- response: {
- type: Object,
- notify: true,
- readOnly: true,
- value: function() {
- return null;
- }
- },
-
- /**
- * A reference to the status code, if the `xhr` has completely resolved.
- */
- status: {
- type: Number,
- notify: true,
- readOnly: true,
- value: 0
- },
-
- /**
- * A reference to the status text, if the `xhr` has completely resolved.
- */
- statusText: {
- type: String,
- notify: true,
- readOnly: true,
- value: ''
- },
-
- /**
- * A promise that resolves when the `xhr` response comes back, or rejects
- * if there is an error before the `xhr` completes.
- *
- * @type {Promise}
- */
- completes: {
- type: Object,
- readOnly: true,
- notify: true,
- value: function() {
- return new Promise(function (resolve, reject) {
- this.resolveCompletes = resolve;
- this.rejectCompletes = reject;
- }.bind(this));
- }
- },
-
- /**
- * An object that contains progress information emitted by the XHR if
- * available.
- *
- * @default {}
- */
- progress: {
- type: Object,
- notify: true,
- readOnly: true,
- value: function() {
- return {};
- }
- },
-
- /**
- * Aborted will be true if an abort of the request is attempted.
- */
- aborted: {
- type: Boolean,
- notify: true,
- readOnly: true,
- value: false,
- },
-
- /**
- * Errored will be true if the browser fired an error event from the
- * XHR object (mainly network errors).
- */
- errored: {
- type: Boolean,
- notify: true,
- readOnly: true,
- value: false
- },
-
- /**
- * TimedOut will be true if the XHR threw a timeout event.
- */
- timedOut: {
- type: Boolean,
- notify: true,
- readOnly: true,
- value: false
- }
- },
-
- /**
- * Succeeded is true if the request succeeded. The request succeeded if it
- * loaded without error, wasn't aborted, and the status code is ≥ 200, and
- * < 300, or if the status code is 0.
- *
- * The status code 0 is accepted as a success because some schemes - e.g.
- * file:// - don't provide status codes.
- *
- * @return {boolean}
- */
- get succeeded() {
- if (this.errored || this.aborted || this.timedOut) {
- return false;
- }
- var status = this.xhr.status || 0;
-
- // Note: if we are using the file:// protocol, the status code will be 0
- // for all outcomes (successful or otherwise).
- return status === 0 ||
- (status >= 200 && status < 300);
- },
-
- /**
- * Sends an HTTP request to the server and returns the XHR object.
- *
- * The handling of the `body` parameter will vary based on the Content-Type
- * header. See the docs for iron-ajax's `body` param for details.
- *
- * @param {{
- * url: string,
- * method: (string|undefined),
- * async: (boolean|undefined),
- * body: (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|undefined|Object),
- * headers: (Object|undefined),
- * handleAs: (string|undefined),
- * jsonPrefix: (string|undefined),
- * withCredentials: (boolean|undefined)}} options -
- * url The url to which the request is sent.
- * method The HTTP method to use, default is GET.
- * async By default, all requests are sent asynchronously. To send synchronous requests,
- * set to false.
- * body The content for the request body for POST method.
- * headers HTTP request headers.
- * handleAs The response type. Default is 'text'.
- * withCredentials Whether or not to send credentials on the request. Default is false.
- * timeout: (Number|undefined)
- * @return {Promise}
- */
- send: function (options) {
- var xhr = this.xhr;
-
- if (xhr.readyState > 0) {
- return null;
- }
-
- xhr.addEventListener('progress', function (progress) {
- this._setProgress({
- lengthComputable: progress.lengthComputable,
- loaded: progress.loaded,
- total: progress.total
- });
- }.bind(this))
-
- xhr.addEventListener('error', function (error) {
- this._setErrored(true);
- this._updateStatus();
- this.rejectCompletes(error);
- }.bind(this));
-
- xhr.addEventListener('timeout', function (error) {
- this._setTimedOut(true);
- this._updateStatus();
- this.rejectCompletes(error);
- }.bind(this));
-
- xhr.addEventListener('abort', function () {
- this._updateStatus();
- this.rejectCompletes(new Error('Request aborted.'));
- }.bind(this));
-
- // Called after all of the above.
- xhr.addEventListener('loadend', function () {
- this._updateStatus();
- this._setResponse(this.parseResponse());
-
- if (!this.succeeded) {
- this.rejectCompletes(new Error('The request failed with status code: ' + this.xhr.status));
+ window.SwarmingBehaviors = window.SwarmingBehaviors || {};
+ (function(){
+ // This behavior wraps up all the shared swarming functionality.
+ SwarmingBehaviors.CommonBehavior = {
+
+ // _getJsonAsync makes an XHR to a url, parses the response as JSON
+ // and sticks the resulting object into the property with the name given
+ // by "bindTo". If busy is defined, the property with that name will be
+ // set to true while the request is in flight and false afterwards.
+ // request headers (e.g. authentication) and query params will be used if
+ // provided. Query params is an object like {String:Array<String>}. On
+ // error, bindTo will be set to false. It is not set to undefined
+ // because computed values in Polymer don't fire if a property is
+ // undefined. Clients should check that bindTo is not falsey.
+ _getJsonAsync: function(bindTo, url, busy, headers, params) {
+ if (!bindTo || !url) {
+ console.log("Need at least a polymer element to bind to and a url");
return;
}
-
- this.resolveCompletes(this);
- }.bind(this));
-
- this.url = options.url;
- xhr.open(
- options.method || 'GET',
- options.url,
- options.async !== false
- );
-
- var acceptType = {
- 'json': 'application/json',
- 'text': 'text/plain',
- 'html': 'text/html',
- 'xml': 'application/xml',
- 'arraybuffer': 'application/octet-stream'
- }[options.handleAs];
- var headers = options.headers || Object.create(null);
- var newHeaders = Object.create(null);
- for (var key in headers) {
- newHeaders[key.toLowerCase()] = headers[key];
- }
- headers = newHeaders;
-
- if (acceptType && !headers['accept']) {
- headers['accept'] = acceptType;
- }
- Object.keys(headers).forEach(function (requestHeader) {
- if (/[A-Z]/.test(requestHeader)) {
- Polymer.Base._error('Headers must be lower case, got', requestHeader);
- }
- xhr.setRequestHeader(
- requestHeader,
- headers[requestHeader]
- );
- }, this);
-
- if (options.async !== false) {
- if (options.async) {
- xhr.timeout = options.timeout;
+ if (busy) {
+ this.set(busy, true);
}
-
- var handleAs = options.handleAs;
-
- // If a JSON prefix is present, the responseType must be 'text' or the
- // browser won’t be able to parse the response.
- if (!!options.jsonPrefix || !handleAs) {
- handleAs = 'text';
- }
-
- // In IE, `xhr.responseType` is an empty string when the response
- // returns. Hence, caching it as `xhr._responseType`.
- xhr.responseType = xhr._responseType = handleAs;
-
- // Cache the JSON prefix, if it exists.
- if (!!options.jsonPrefix) {
- xhr._jsonPrefix = options.jsonPrefix;
- }
- }
-
- xhr.withCredentials = !!options.withCredentials;
-
-
- var body = this._encodeBodyObject(options.body, headers['content-type']);
-
- xhr.send(
- /** @type {ArrayBuffer|ArrayBufferView|Blob|Document|FormData|
- null|string|undefined} */
- (body));
-
- return this.completes;
- },
-
- /**
- * Attempts to parse the response body of the XHR. If parsing succeeds,
- * the value returned will be deserialized based on the `responseType`
- * set on the XHR.
- *
- * @return {*} The parsed response,
- * or undefined if there was an empty response or parsing failed.
- */
- parseResponse: function () {
- var xhr = this.xhr;
- var responseType = xhr.responseType || xhr._responseType;
- var preferResponseText = !this.xhr.responseType;
- var prefixLen = (xhr._jsonPrefix && xhr._jsonPrefix.length) || 0;
-
- try {
- switch (responseType) {
- case 'json':
- // If the xhr object doesn't have a natural `xhr.responseType`,
- // we can assume that the browser hasn't parsed the response for us,
- // and so parsing is our responsibility. Likewise if response is
- // undefined, as there's no way to encode undefined in JSON.
- if (preferResponseText || xhr.response === undefined) {
- // Try to emulate the JSON section of the response body section of
- // the spec: https://xhr.spec.whatwg.org/#response-body
- // That is to say, we try to parse as JSON, but if anything goes
- // wrong return null.
- try {
- return JSON.parse(xhr.responseText);
- } catch (_) {
- return null;
- }
- }
-
- return xhr.response;
- case 'xml':
- return xhr.responseXML;
- case 'blob':
- case 'document':
- case 'arraybuffer':
- return xhr.response;
- case 'text':
- default: {
- // If `prefixLen` is set, it implies the response should be parsed
- // as JSON once the prefix of length `prefixLen` is stripped from
- // it. Emulate the behavior above where null is returned on failure
- // to parse.
- if (prefixLen) {
- try {
- return JSON.parse(xhr.responseText.substring(prefixLen));
- } catch (_) {
- return null;
- }
- }
- return xhr.responseText;
+ url = url + "?" + sk.query.fromParamSet(params);
+ sk.request("GET", url, "", headers).then(JSON.parse).then(function(json){
+ this.set(bindTo, json);
+ if (busy) {
+ this.set(busy, false);
}
- }
- } catch (e) {
- this.rejectCompletes(new Error('Could not parse response. ' + e.message));
- }
- },
-
- /**
- * Aborts the request.
- */
- abort: function () {
- this._setAborted(true);
- this.xhr.abort();
- },
-
- /**
- * @param {*} body The given body of the request to try and encode.
- * @param {?string} contentType The given content type, to infer an encoding
- * from.
- * @return {*} Either the encoded body as a string, if successful,
- * or the unaltered body object if no encoding could be inferred.
- */
- _encodeBodyObject: function(body, contentType) {
- if (typeof body == 'string') {
- return body; // Already encoded.
- }
- var bodyObj = /** @type {Object} */ (body);
- switch(contentType) {
- case('application/json'):
- return JSON.stringify(bodyObj);
- case('application/x-www-form-urlencoded'):
- return this._wwwFormUrlEncode(bodyObj);
- }
- return body;
- },
-
- /**
- * @param {Object} object The object to encode as x-www-form-urlencoded.
- * @return {string} .
- */
- _wwwFormUrlEncode: function(object) {
- if (!object) {
- return '';
- }
- var pieces = [];
- Object.keys(object).forEach(function(key) {
- // TODO(rictic): handle array values here, in a consistent way with
- // iron-ajax params.
- pieces.push(
- this._wwwFormUrlEncodePiece(key) + '=' +
- this._wwwFormUrlEncodePiece(object[key]));
- }, this);
- return pieces.join('&');
- },
-
- /**
- * @param {*} str A key or value to encode as x-www-form-urlencoded.
- * @return {string} .
- */
- _wwwFormUrlEncodePiece: function(str) {
- // Spec says to normalize newlines to \r\n and replace %20 spaces with +.
- // jQuery does this as well, so this is likely to be widely compatible.
- if (str === null) {
- return '';
- }
- return encodeURIComponent(str.toString().replace(/\r?\n/g, '\r\n'))
- .replace(/%20/g, '+');
- },
-
- /**
- * Updates the status code and status text.
- */
- _updateStatus: function() {
- this._setStatus(this.xhr.status);
- this._setStatusText((this.xhr.statusText === undefined) ? '' : this.xhr.statusText);
- }
- });
-</script>
-
-<script>
- 'use strict';
-
- Polymer({
-
- is: 'iron-ajax',
-
- /**
- * Fired when a request is sent.
- *
- * @event request
- * @event iron-ajax-request
- */
-
- /**
- * Fired when a response is received.
- *
- * @event response
- * @event iron-ajax-response
- */
-
- /**
- * Fired when an error is received.
- *
- * @event error
- * @event iron-ajax-error
- */
-
- hostAttributes: {
- hidden: true
- },
-
- properties: {
- /**
- * The URL target of the request.
- */
- url: {
- type: String
- },
-
- /**
- * An object that contains query parameters to be appended to the
- * specified `url` when generating a request. If you wish to set the body
- * content when making a POST request, you should use the `body` property
- * instead.
- */
- params: {
- type: Object,
- value: function() {
- return {};
- }
- },
-
- /**
- * The HTTP method to use such as 'GET', 'POST', 'PUT', or 'DELETE'.
- * Default is 'GET'.
- */
- method: {
- type: String,
- value: 'GET'
- },
-
- /**
- * HTTP request headers to send.
- *
- * Example:
- *
- * <iron-ajax
- * auto
- * url="http://somesite.com"
- * headers='{"X-Requested-With": "XMLHttpRequest"}'
- * handle-as="json"></iron-ajax>
- *
- * Note: setting a `Content-Type` header here will override the value
- * specified by the `contentType` property of this element.
- */
- headers: {
- type: Object,
- value: function() {
- return {};
- }
- },
-
- /**
- * Content type to use when sending data. If the `contentType` property
- * is set and a `Content-Type` header is specified in the `headers`
- * property, the `headers` property value will take precedence.
- *
- * Varies the handling of the `body` param.
- */
- contentType: {
- type: String,
- value: null
- },
-
- /**
- * Body content to send with the request, typically used with "POST"
- * requests.
- *
- * If body is a string it will be sent unmodified.
- *
- * If Content-Type is set to a value listed below, then
- * the body will be encoded accordingly.
- *
- * * `content-type="application/json"`
- * * body is encoded like `{"foo":"bar baz","x":1}`
- * * `content-type="application/x-www-form-urlencoded"`
- * * body is encoded like `foo=bar+baz&x=1`
- *
- * Otherwise the body will be passed to the browser unmodified, and it
- * will handle any encoding (e.g. for FormData, Blob, ArrayBuffer).
- *
- * @type (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|undefined|Object)
- */
- body: {
- type: Object,
- value: null
- },
-
- /**
- * Toggle whether XHR is synchronous or asynchronous. Don't change this
- * to true unless You Know What You Are Doing™.
- */
- sync: {
- type: Boolean,
- value: false
- },
-
- /**
- * Specifies what data to store in the `response` property, and
- * to deliver as `event.detail.response` in `response` events.
- *
- * One of:
- *
- * `text`: uses `XHR.responseText`.
- *
- * `xml`: uses `XHR.responseXML`.
- *
- * `json`: uses `XHR.responseText` parsed as JSON.
- *
- * `arraybuffer`: uses `XHR.response`.
- *
- * `blob`: uses `XHR.response`.
- *
- * `document`: uses `XHR.response`.
- */
- handleAs: {
- type: String,
- value: 'json'
- },
-
- /**
- * Set the withCredentials flag on the request.
- */
- withCredentials: {
- type: Boolean,
- value: false
- },
-
- /**
- * Set the timeout flag on the request.
- */
- timeout: {
- type: Number,
- value: 0
- },
-
- /**
- * If true, automatically performs an Ajax request when either `url` or
- * `params` changes.
- */
- auto: {
- type: Boolean,
- value: false
- },
-
- /**
- * If true, error messages will automatically be logged to the console.
- */
- verbose: {
- type: Boolean,
- value: false
- },
-
- /**
- * The most recent request made by this iron-ajax element.
- */
- lastRequest: {
- type: Object,
- notify: true,
- readOnly: true
- },
-
- /**
- * True while lastRequest is in flight.
- */
- loading: {
- type: Boolean,
- notify: true,
- readOnly: true
- },
-
- /**
- * lastRequest's response.
- *
- * Note that lastResponse and lastError are set when lastRequest finishes,
- * so if loading is true, then lastResponse and lastError will correspond
- * to the result of the previous request.
- *
- * The type of the response is determined by the value of `handleAs` at
- * the time that the request was generated.
- *
- * @type {Object}
- */
- lastResponse: {
- type: Object,
- notify: true,
- readOnly: true
+ }.bind(this)).catch(function(reason){
+ console.log("Reason for failure of request to " + url, reason);
+ this.set(bindTo, false);
+ if (busy) {
+ this.set(busy, false);
+ }
+ }.bind(this));
},
- /**
- * lastRequest's error, if any.
- *
- * @type {Object}
- */
- lastError: {
- type: Object,
- notify: true,
- readOnly: true
+ _not: function(a) {
+ return !a;
},
- /**
- * An Array of all in-flight requests originating from this iron-ajax
- * element.
- */
- activeRequests: {
- type: Array,
- notify: true,
- readOnly: true,
- value: function() {
- return [];
+ _or: function() {
+ var result = false;
+ // can't use .foreach, as arguments isn't really an Array.
+ for (var i = 0; i < arguments.length; i++) {
+ result = result || arguments[i];
}
+ return result;
},
-
- /**
- * Length of time in milliseconds to debounce multiple automatically generated requests.
- */
- debounceDuration: {
- type: Number,
- value: 0,
- notify: true
- },
-
- /**
- * Prefix to be stripped from a JSON response before parsing it.
- *
- * In order to prevent an attack using CSRF with Array responses
- * (http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx/)
- * many backends will mitigate this by prefixing all JSON response bodies
- * with a string that would be nonsensical to a JavaScript parser.
- *
- */
- jsonPrefix: {
- type: String,
- value: ''
- },
-
- /**
- * By default, iron-ajax's events do not bubble. Setting this attribute will cause its
- * request and response events as well as its iron-ajax-request, -response, and -error
- * events to bubble to the window object. The vanilla error event never bubbles when
- * using shadow dom even if this.bubbles is true because a scoped flag is not passed with
- * it (first link) and because the shadow dom spec did not used to allow certain events,
- * including events named error, to leak outside of shadow trees (second link).
- * https://www.w3.org/TR/shadow-dom/#scoped-flag
- * https://www.w3.org/TR/2015/WD-shadow-dom-20151215/#events-that-are-not-leaked-into-ancestor-trees
- */
- bubbles: {
- type: Boolean,
- value: false
- },
-
- _boundHandleResponse: {
- type: Function,
- value: function() {
- return this._handleResponse.bind(this);
- }
- }
- },
-
- observers: [
- '_requestOptionsChanged(url, method, params.*, headers, contentType, ' +
- 'body, sync, handleAs, jsonPrefix, withCredentials, timeout, auto)'
- ],
-
- /**
- * The query string that should be appended to the `url`, serialized from
- * the current value of `params`.
- *
- * @return {string}
- */
- get queryString () {
- var queryParts = [];
- var param;
- var value;
-
- for (param in this.params) {
- value = this.params[param];
- param = window.encodeURIComponent(param);
-
- if (Array.isArray(value)) {
- for (var i = 0; i < value.length; i++) {
- queryParts.push(param + '=' + window.encodeURIComponent(value[i]));
- }
- } else if (value !== null) {
- queryParts.push(param + '=' + window.encodeURIComponent(value));
- } else {
- queryParts.push(param);
- }
- }
-
- return queryParts.join('&');
- },
-
- /**
- * The `url` with query string (if `params` are specified), suitable for
- * providing to an `iron-request` instance.
- *
- * @return {string}
- */
- get requestUrl() {
- var queryString = this.queryString;
- var url = this.url || '';
-
- if (queryString) {
- var bindingChar = url.indexOf('?') >= 0 ? '&' : '?';
- return url + bindingChar + queryString;
- }
-
- return url;
- },
-
- /**
- * An object that maps header names to header values, first applying the
- * the value of `Content-Type` and then overlaying the headers specified
- * in the `headers` property.
- *
- * @return {Object}
- */
- get requestHeaders() {
- var headers = {};
- var contentType = this.contentType;
- if (contentType == null && (typeof this.body === 'string')) {
- contentType = 'application/x-www-form-urlencoded';
- }
- if (contentType) {
- headers['content-type'] = contentType;
- }
- var header;
-
- if (this.headers instanceof Object) {
- for (header in this.headers) {
- headers[header] = this.headers[header].toString();
- }
- }
-
- return headers;
- },
-
- /**
- * Request options suitable for generating an `iron-request` instance based
- * on the current state of the `iron-ajax` instance's properties.
- *
- * @return {{
- * url: string,
- * method: (string|undefined),
- * async: (boolean|undefined),
- * body: (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|undefined|Object),
- * headers: (Object|undefined),
- * handleAs: (string|undefined),
- * jsonPrefix: (string|undefined),
- * withCredentials: (boolean|undefined)}}
- */
- toRequestOptions: function() {
- return {
- url: this.requestUrl || '',
- method: this.method,
- headers: this.requestHeaders,
- body: this.body,
- async: !this.sync,
- handleAs: this.handleAs,
- jsonPrefix: this.jsonPrefix,
- withCredentials: this.withCredentials,
- timeout: this.timeout
- };
- },
-
- /**
- * Performs an AJAX request to the specified URL.
- *
- * @return {!IronRequestElement}
- */
- generateRequest: function() {
- var request = /** @type {!IronRequestElement} */ (document.createElement('iron-request'));
- var requestOptions = this.toRequestOptions();
-
- this.push('activeRequests', request);
-
- request.completes.then(
- this._boundHandleResponse
- ).catch(
- this._handleError.bind(this, request)
- ).then(
- this._discardRequest.bind(this, request)
- );
-
- request.send(requestOptions);
-
- this._setLastRequest(request);
- this._setLoading(true);
-
- this.fire('request', {
- request: request,
- options: requestOptions
- }, {bubbles: this.bubbles});
-
- this.fire('iron-ajax-request', {
- request: request,
- options: requestOptions
- }, {bubbles: this.bubbles});
-
- return request;
- },
-
- _handleResponse: function(request) {
- if (request === this.lastRequest) {
- this._setLastResponse(request.response);
- this._setLastError(null);
- this._setLoading(false);
- }
- this.fire('response', request, {bubbles: this.bubbles});
- this.fire('iron-ajax-response', request, {bubbles: this.bubbles});
- },
-
- _handleError: function(request, error) {
- if (this.verbose) {
- Polymer.Base._error(error);
- }
-
- if (request === this.lastRequest) {
- this._setLastError({
- request: request,
- error: error,
- status: request.xhr.status,
- statusText: request.xhr.statusText,
- response: request.xhr.response
- });
- this._setLastResponse(null);
- this._setLoading(false);
- }
-
- // Tests fail if this goes after the normal this.fire('error', ...)
- this.fire('iron-ajax-error', {
- request: request,
- error: error
- }, {bubbles: this.bubbles});
-
- this.fire('error', {
- request: request,
- error: error
- }, {bubbles: this.bubbles});
- },
-
- _discardRequest: function(request) {
- var requestIndex = this.activeRequests.indexOf(request);
-
- if (requestIndex > -1) {
- this.splice('activeRequests', requestIndex, 1);
- }
- },
-
- _requestOptionsChanged: function() {
- this.debounce('generate-request', function() {
- if (this.url == null) {
- return;
- }
-
- if (this.auto) {
- this.generateRequest();
- }
- }, this.debounceDuration);
- },
-
- });
+ };
+ })();
</script>
-
-
<script>
Polymer.AppLayout = Polymer.AppLayout || {};
@@ -14578,7 +13576,7 @@ You can bind to `isAuthorized` property to monitor authorization state.
<app-header fixed="">
<app-toolbar>
<div class="title left">[[name]]</div>
- <paper-spinner-lite class="left" active="[[busy]]"></paper-spinner-lite>
+ <paper-spinner-lite class="left" active="[[_or(busy,_busy)]]"></paper-spinner-lite>
<a class="left" href="/newui/">Home</a>
<a class="left" href="/newui/botlist">Bot List</a>
@@ -14597,36 +13595,55 @@ You can bind to `isAuthorized` property to monitor authorization state.
<script>
Polymer({
is: 'swarming-app',
+
+ behaviors: [
+ SwarmingBehaviors.CommonBehavior,
+ ],
+
properties: {
+ // input
+ busy: {
+ type: Boolean,
+ },
client_id: {
type: String,
},
+ name: {
+ type: String,
+ },
+ // outputs
auth_headers: {
type: Object,
notify: true,
+ observer: "_loadPermissions"
},
+
+ permissions: {
+ type: Object,
+ value: function() {
+ // If we aren't logged in, default to no permissions.
+ return {};
+ },
+ notify: true,
+ },
+
signed_in: {
type: Boolean,
value: false,
notify:true,
},
- permissions: {
- type: Object,
- value: function() {
- // TODO(kjlubick): Make this call the whoami endpoint after signing in.
- return {
- can_cancel_task: true,
- }
- },
- notify: true,
- },
- busy: {
+ // private
+ _busy: {
type: Boolean,
- },
- name: {
- type: String,
- },
+ value: false,
+ }
+
+ },
+
+ _loadPermissions: function() {
+ this._getJsonAsync("permissions", "/_ah/api/swarming/v1/server/permissions",
+ "_busy", this.auth_headers);
},
});
@@ -14647,17 +13664,81 @@ You can bind to `isAuthorized` property to monitor authorization state.
<dom-module id="swarming-index" assetpath="/res/imp/index/">
<template>
<style include="swarming-app-style">
-
+ .command {
+ font-family: monospace;
+ margin-bottom: 10px;
+ margin-top: 10px;
+ white-space: pre-wrap;
+ background-color: #f5f5f5;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ }
</style>
- <swarming-app client_id="[[client_id]]" auth_headers="{{auth_headers}}" name="Swarming" busy="[[busy]]">
-
- <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers="[[auth_headers]]" handle-as="json" last-response="{{serverDetails}}" loading="{{busy}}">
- </iron-ajax>
-
- <h1>HELLO WORLD</h1>
+ <swarming-app client_id="[[client_id]]" auth_headers="{{auth_headers}}" permissions="{{_permissions}}" name="Swarming Server" busy="[[_busy]]">
+ <h2>Service Status</h2>
<div>Server Version: [[serverDetails.server_version]]</div>
+ <ul>
+ <li>
+
+ <a href="/stats">Usage statistics</a>
+ </li>
+ <li>
+ <a href="/restricted/mapreduce/status">Map Reduce Jobs</a>
+ </li>
+ <li>
+ <a href$="[[_makeInstancesUrl(serverDetails,_project_id)]]">View version's instances on Cloud Console</a>
+ </li>
+ <li>
+ <a></a><a href$="[[_makeErrorUrl(_project_id)]]">View server errors on Cloud Console</a>
+ </li>
+ <li>
+ <a></a><a href$="[[_makeLogUrl(_project_id)]]">View logs for HTTP 5xx on Cloud Console</a>
+ </li>
+ </ul>
+
+ <h2>Configuration</h2>
+ <ul>
+
+ <li>
+ <a href="/restricted/config">View server config</a>
+ </li>
+ <li>
+ <a href="/restricted/upload/bootstrap">View/upload bootstrap.py</a>
+ </li>
+ <li>
+ <a href="/restricted/upload/bot_config">View/upload bot_config.py</a>
+ </li>
+ <li>
+ <a href="/auth/groups">View/edit user groups</a>
+ </li>
+ </ul>
+
+ <div hidden$="[[_cannotBootstrap(_permissions)]]">
+ <h2>Bootstrapping a bot</h2>
+ To bootstrap a bot, run one of these (all links are valid for 1 hour):
+ <ol>
+ <li>
+ <strong> TL;DR; </strong>
+ <pre class="command">python -c "import urllib; exec urllib.urlopen('[[_host_url]]/bootstrap?tok=[[_bootstrap_token]]').read()"</pre>
+ </li>
+ <li>
+ Escaped version to pass as a ssh argument:
+ <pre class="command">'python -c "import urllib; exec urllib.urlopen('"'[[_host_url]]/bootstrap?tok=[[_bootstrap_token]]'"').read()"'</pre>
+ </li>
+ <li>
+ Manually:
+ <pre class="command" style="margin-bottom:0">mkdir bot; cd bot
+ rm -f swarming_bot.zip; curl -sSLOJ [[_host_url]]/bot_code?tok=[[_bootstrap_token]]
+ python swarming_bot.zip</pre>
+ </li>
+ </ol>
+ </div>
+
+ <h2>Stats</h2>
+ <div>TODO(kjlubick) add these in</div>
+
</swarming-app>
@@ -14666,6 +13747,10 @@ You can bind to `isAuthorized` property to monitor authorization state.
Polymer({
is: 'swarming-index',
+ behaviors: [
+ SwarmingBehaviors.CommonBehavior,
+ ],
+
properties: {
client_id: {
type: String,
@@ -14677,70 +13762,63 @@ You can bind to `isAuthorized` property to monitor authorization state.
},
serverDetails: {
+ type: Object,
+ },
+
+ _bootstrap_token: {
type: String,
+ // TODO(kjlubick): fetch this from an API
+ value: "abc123",
+ },
+ _busy: {
+ type: Boolean,
+ value: false,
+ },
+ _host_url: {
+ type: String,
+ value: function() {
+ return location.origin;
+ },
+ },
+ _permissions: {
+ type: Object,
+ },
+ _project_id: {
+ type: String,
+ value: function() {
+ var idx = location.hostname.indexOf(".appspot.com");
+ return location.hostname.substring(0, idx);
+ },
}
},
signIn: function(){
- this.$.request.generateRequest();
+ this._getJsonAsync("serverDetails", "/_ah/api/swarming/v1/server/details",
+ "_busy", this.auth_headers);
+ },
+
+ _cannotBootstrap: function(permissions) {
+ return !(permissions && permissions.get_bootstrap_token);
+ },
+
+ _makeInstancesUrl: function(details, project_id) {
+ return "https://console.cloud.google.com/appengine/instances?project="+
+ project_id+"&versionId="+details.server_version;
+ },
+
+ _makeErrorUrl: function(project_id) {
+ return "https://console.cloud.google.com/errors?project="+
+ project_id;
+ },
+
+ _makeLogUrl: function(project_id) {
+ return "https://pantheon.corp.google.com/logs/viewer?filters=text:status:500..599&project="+
+ project_id;
},
});
</script>
-</dom-module><script>
- window.SwarmingBehaviors = window.SwarmingBehaviors || {};
- (function(){
- // This behavior wraps up all the shared swarming functionality.
- SwarmingBehaviors.CommonBehavior = {
-
- // _getJsonAsync makes an XHR to a url, parses the response as JSON
- // and sticks the resulting object into the property with the name given
- // by "bindTo". If busy is defined, the property with that name will be
- // set to true while the request is in flight and false afterwards.
- // request headers (e.g. authentication) and query params will be used if
- // provided. Query params is an object like {String:Array<String>}. On
- // error, bindTo will be set to false. It is not set to undefined
- // because computed values in Polymer don't fire if a property is
- // undefined. Clients should check that bindTo is not falsey.
- _getJsonAsync: function(bindTo, url, busy, headers, params) {
- if (!bindTo || !url) {
- console.log("Need at least a polymer element to bind to and a url");
- return;
- }
- if (busy) {
- this.set(busy, true);
- }
- url = url + "?" + sk.query.fromParamSet(params);
- sk.request("GET", url, "", headers).then(JSON.parse).then(function(json){
- this.set(bindTo, json);
- if (busy) {
- this.set(busy, false);
- }
- }.bind(this)).catch(function(reason){
- console.log("Reason for failure of request to " + url, reason);
- this.set(bindTo, false);
- if (busy) {
- this.set(busy, false);
- }
- }.bind(this));
- },
-
- _not: function(a) {
- return !a;
- },
-
- _or: function() {
- var result = false;
- // can't use .foreach, as arguments isn't really an Array.
- for (var i = 0; i < arguments.length; i++) {
- result = result || arguments[i];
- }
- return result;
- },
- };
- })();
-</script>
-<dom-module id="dynamic-table-style" assetpath="/res/imp/common/">
+</dom-module><dom-module id="dynamic-table-style" assetpath="/res/imp/common/">
<template>
<style>
table {
@@ -25232,7 +24310,7 @@ the fleet.">
},
_cannotCancel: function(task, permissions) {
- return !(permissions && permissions.can_cancel_task &&
+ return !(permissions && permissions.cancel_task &&
this._column("state", task) === "PENDING");
},
« 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