| Index: appengine/swarming/elements/build/elements.html
|
| diff --git a/appengine/swarming/elements/build/elements.html b/appengine/swarming/elements/build/elements.html
|
| index 1ee8b858f417915d6f3e3c9d472dff03d8954cd2..23402ebfa495d970db954b0cf6cada3f28bc06ef 100644
|
| --- a/appengine/swarming/elements/build/elements.html
|
| +++ b/appengine/swarming/elements/build/elements.html
|
| @@ -198,7 +198,7 @@ the fleet."> <template is="dom-repeat" items="[[_filters]]" as="fil"> <div class
|
| }
|
|
|
| });
|
| - })(); </script> </dom-module> <dom-module id="paper-material" assetpath="/res/imp/bower_components/paper-material/"> <template> <style include="paper-material-shared-styles"></style> <style>:host([animated]){@apply(--shadow-transition)}</style> <content></content> </template> </dom-module> <script>Polymer({is:"paper-material",properties:{elevation:{type:Number,reflectToAttribute:!0,value:1},animated:{type:Boolean,reflectToAttribute:!0,value:!1}}})</script> <dom-module id="paper-button" assetpath="/res/imp/bower_components/paper-button/"> <template strip-whitespace=""> <style include="paper-material">:host{@apply(--layout-inline);@apply(--layout-center-center);position:relative;box-sizing:border-box;min-width:5.14em;margin:0 .29em;background:0 0;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent;font:inherit;text-transform:uppercase;outline-width:0;border-radius:3px;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none;cursor:pointer;z-index:0;padding:.7em .57em;@apply(--paper-font-common-base);@apply(--paper-button)}:host([raised].keyboard-focus){font-weight:700;@apply(--paper-button-raised-keyboard-focus)}:host(:not([raised]).keyboard-focus){font-weight:700;@apply(--paper-button-flat-keyboard-focus)}:host([disabled]){background:#eaeaea;color:#a8a8a8;cursor:auto;pointer-events:none;@apply(--paper-button-disabled)}paper-ripple{color:var(--paper-button-ink-color)}</style> <content></content> </template> <script>Polymer({is:"paper-button",behaviors:[Polymer.PaperButtonBehavior],properties:{raised:{type:Boolean,reflectToAttribute:!0,value:!1,observer:"_calculateElevation"}},_calculateElevation:function(){this.raised?Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this):this._setElevation(0)}})</script> </dom-module> <dom-module id="error-toast" assetpath="/res/imp/common/"> <template> <paper-toast id="toast"></paper-toast> </template> </dom-module> <script>Polymer({is:"error-toast",ready:function(){document.addEventListener("error-sk",function(t){if(this.$.toast.close(),t.detail.message){this.$.toast.text=t.detail.message;var e=1e4;void 0!==t.detail.duration&&(e=t.detail.duration),this.$.toast.duration=e,this.$.toast.show()}else console.log("Empty message?",t)}.bind(this))}})</script> <dom-module id="task-filters" assetpath="/res/imp/tasklist/"> <template> <style is="custom-style" include="iron-flex iron-flex-alignment iron-positioning query-column-filter-style">.item.wide{max-width:400px}.selector.wide{min-width:275px}</style> <url-param name="filters" value="{{_filters}}" default_values="[]" multi=""> </url-param> <url-param name="columns" value="{{columns}}" default_values="["name","state","created_ts","user"]" multi=""> </url-param> <url-param name="query" value="{{_query}}" default_value=""> </url-param> <url-param name="limit" default_value="200" value="{{limit}}"> </url-param> <div class="container horizontal layout"> <div class="narrow-down-selector"> <div> <paper-input id="filter" label="Search columns and filters" placeholder="gpu nvidia" value="{{_query}}"> </paper-input> </div> <div class="wide selector side-by-side" title="This shows all task tags and other interesting task properties. Mark the check box to add as a column. Select the row to see filter options."> <iron-selector attr-for-selected="label" selected="{{_primarySelected}}"> <template is="dom-repeat" items="[[_primaryItems]]" as="item"> <div class="selectable item horizontal layout" label="[[item]]"> <span>[[_beforeBold(item,_query)]]<span class="bold">[[_bold(item,_query)]]</span>[[_afterBold(item,_query)]]</span> <span class="flex"></span> <paper-checkbox noink="" disabled$="[[_cantToggleColumn(item)]]" checked="[[_columnState(item,columns.*)]]" on-change="_toggleColumn"> </paper-checkbox> </div> </template> </iron-selector> </div> <div class="selector side-by-side" title="These are all options (if any) that the task list can be filtered on."> <template is="dom-repeat" id="secondaryList" items="[[_secondaryItems]]" as="item"> <div class="item horizontal layout" label="[[item]]"> <span>[[_beforeBold(item,_query)]]<span class="bold">[[_bold(item,_query)]]</span>[[_afterBold(item,_query)]]</span> <span class="flex"></span> <iron-icon class="icons" icon="icons:arrow-forward" hidden="[[_cantAddFilter(_primarySelected,item,_filters.*)]]" on-tap="_addFilter"> </iron-icon> </div> </template> </div> <div class="selector side-by-side" title="These tag filters are AND'd together and applied to all tasks."> <template is="dom-repeat" items="[[_filters]]" as="fil"> <div class="item horizontal layout" label="[[fil]]"> <span>[[fil]]</span> <span class="flex"></span> <iron-icon class="icons" icon="icons:remove-circle-outline" hidden="[[_cantRemoveFilter(fil,_filters.*)]]" on-tap="_removeFilter"> </iron-icon> </div> </template> </div> <div class="side-by-side"> <paper-input id="limit" label="Limit Results" auto-validate="" min="0" max="1000" pattern="[0-9]+" value="{{limit}}"> </paper-input> </div> </div> </div> </template> <script>!function(){var t={state:function(t,r){var i=this._attribute(t,"state")[0];if(r===i)return!0;if("PENDING_RUNNING"===r)return"PENDING"===i||"RUNNING"===i;var e=this._attribute(t,"failure",!1)[0];if("COMPLETED_SUCCESS"===r)return"COMPLETED"===i&&!e;if("COMPLETED_FAILURE"===r)return"COMPLETED"===i&&e;var a=this._attribute(t,"try_number","-1")[0];return"DEDUPED"===r?"COMPLETED"===i&&"0"===a:void 0}};Polymer({is:"task-filters",behaviors:[SwarmingBehaviors.QueryColumnFilter],properties:{columns:{type:Array,notify:!0},query_params:{type:Object,computed:"_extractQueryParams(_filters.*, limit)",notify:!0},_filterMap:{type:Object,value:function(){var r=this._commonFilters();for(var i in t)r[i]=t[i];return r}}},_cantToggleColumn:function(t){return!t||"name"===t},_extractQueryParams:function(){var t={},r=[];this._filters.forEach(function(i){var e=i.split(this.FILTER_SEP,1),a=e[0],n=i.substring(a.length+this.FILTER_SEP.length);"state"===a?t.state=[n]:r.push(a+this.FILTER_SEP+swarming.alias.unapply(n))}.bind(this)),t.tags=r;var i=Math.floor(this.limit);return Number.isInteger(i)&&(i=Math.max(i,1),i=Math.min(1e3,i),t.limit=[i],this.limit!=i&&this.set("limit",i)),t}})}()</script> </dom-module><dom-module id="task-list-data" assetpath="/res/imp/tasklist/"> <script>!function(){var t=["abandoned_ts","completed_ts","created_ts","modified_ts","started_ts"];Polymer({is:"task-list-data",behaviors:[SwarmingBehaviors.CommonBehavior],properties:{auth_headers:{type:Object,observer:"signIn"},query_params:{type:Object,observer:"_request"},busy:{type:Boolean,computed:"_or(_busy1,_busy2,_busy3)",notify:!0},primary_map:{type:Object,computed:"_primaryMap(_tags,_dimensions,tasks)",notify:!0},primary_arr:{type:Array,computed:"_primaryArr(primary_map)",notify:!0},tasks:{type:Array,computed:"_tasks(_list)",notify:!0},_busy1:{type:Boolean,value:!1},_busy2:{type:Boolean,value:!1},_busy3:{type:Boolean,value:!1},_dimensions:{type:Object},_list:{type:Object},_tags:{type:Object}},signIn:function(){this._getJsonAsync("_tags","/_ah/api/swarming/v1/tasks/tags","_busy2",this.auth_headers),this._getJsonAsync("_dimensions","/_ah/api/swarming/v1/bots/dimensions","_busy3",this.auth_headers),this._request()},_primaryArr:function(t){var s=Object.keys(t);return s.sort(),s},_primaryMap:function(s,e,a){s=s&&s.tasks_tags||[],e=e&&e.bots_dimensions||[],a=a||[];var r={};s.forEach(function(t){r[t.key]||(r[t.key]={});var s=t.value||[];s.forEach(function(s){r[t.key][s]=!0})}),e.forEach(function(t){var s=t.value;r[t.key]||(r[t.key]={}),s.forEach(function(s){r[t.key][s]=!0})}),a.forEach(function(t){Object.keys(t.tagMap).forEach(function(s){var e=t.tagMap[s];r[s]||(r[s]={}),r[s][e]=!0})});var i={};for(key in r){var n=Object.keys(r[key]);if(swarming.alias.DIMENSIONS_WITH_ALIASES.indexOf(key)===-1)i[key]=n;else{var o=[];n.forEach(function(t){o.push(swarming.alias.apply(t,key))}),i[key]=o}}return i.android_devices.push("0"),i.device_os.push("none"),i.device_type.push("none"),i.user.push("none"),i.name=[],i.state=["PENDING","RUNNING","PENDING_RUNNING","COMPLETED","COMPLETED_SUCCESS","COMPLETED_FAILURE","EXPIRED","TIMED_OUT","BOT_DIED","CANCELED","ALL","DEDUPED"],i.costs_usd=[],i.deduped_from=[],i.duration=[],i.server_versions=[],t.forEach(function(t){i[t]=[]}),i},_request:function(){this.auth_headers&&this.query_params&&this._getJsonAsync("_list","/_ah/api/swarming/v1/tasks/list","_busy1",this.auth_headers,this.query_params)},_tasks:function(){if(!this._list||!this._list.items)return[];var s=new Date,e=s.toString(),a=e.substring(e.indexOf("("));return this._list.items.forEach(function(e){var r={};e.tags.forEach(function(t){var s=t.split(":",1),e=s[0],a=t.substring(e.length+1);r[e]=a}),e.tagMap=r,t.forEach(function(t){if(e[t]){e[t]=new Date(e[t]);var s=e[t].toLocaleString();e["human_"+t]=s+" "+a}}),!e.duration&&"RUNNING"===e.state&&e.started_ts&&(e.duration=(s-e.started_ts)/1e3),e.duration&&(e.human_duration=sk.human.strDuration(e.duration))}),this._list.items}})}()</script> </dom-module> <dom-module id="task-list" assetpath="/res/imp/tasklist/"> <template> <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-style dynamic-table-style">task-filters{margin-bottom:8px;margin-right:10px}.task-list th>span{padding-right:30px}.failed{background-color:#fdd}.died{background-color:#ccc}.exception{background-color:#edd2ff}.pending{background-color:#fffc6c}</style> <url-param name="sort" value="{{_sortstr}}" default_value="created_ts:desc"> </url-param> <swarming-app client_id="[[client_id]]" auth_headers="{{_auth_headers}}" permissions="{{_permissions}}" signed_in="{{_signed_in}}" busy="[[_busy]]" name="Swarming Task List"> <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2> <div hidden$="[[_not(_signed_in)]]"> <task-list-data auth_headers="[[_auth_headers]]" query_params="[[_query_params]]" tasks="{{_items}}" busy="{{_busy}}" primary_map="{{_primary_map}}" primary_arr="{{_primary_arr}}"> </task-list-data> <error-toast></error-toast> <div class="horizontal layout"> <task-filters primary_map="[[_primary_map]]" primary_arr="[[_primary_arr]]" columns="{{_columns}}" query_params="{{_query_params}}" filter="{{_filter}}"> </task-filters> </div> <table class="task-list"> <thead on-sort_change="_sortChange"> <tr> <th> <span>Task Name</span> <sort-toggle name="name" current="[[_sort]]"> </sort-toggle> </th> <th hidden$="[[_hide('state', _columns.*)]]"> <span>State</span> <sort-toggle name="state" current="[[_sort]]"> </sort-toggle> </th> <th hidden$="[[_hide('deduped_from', _columns.*)]]"> <span>Deduped from</span> <sort-toggle name="deduped_from" current="[[_sort]]"> </sort-toggle> </th> <template is="dom-repeat" items="[[_plainColumns]]" as="c"> <th hidden$="[[_hide(c)]]"> <span>[[_header(c)]]</span> <sort-toggle name="[[c]]" current="[[_sort]]"> </sort-toggle> </th> </template> </tr> </thead> <tbody> <template id="tasks_table" is="dom-repeat" items="[[_filteredSortedItems]]" as="task" initial-count="50"> <tr class$="[[_taskClass(task)]]"> <td> <a class="center" href$="[[_taskLink(task.task_id)]]" target="_blank"> [[task.name]] </a> </td> <td hidden$="[[_hide('state', _columns.*)]]"> [[_column('state', task)]] <paper-button raised="" hidden$="[[_cannotCancel(task,_permissions)]]" on-tap="_cancelTask"> Cancel </paper-button> </td> <td hidden$="[[_hide('deduped_from', _columns.*)]]"> <a class="center" href$="[[_taskLink(task.deduped_from)]]" target="_blank"> [[_column('deduped_from',task)]] </a> </td> <template is="dom-repeat" items="[[_plainColumns]]" as="c"> <td hidden$="[[_hide(c)]]"> [[_column(c, task)]] </td> </template> </tr> </template> </tbody> </table> </div> </swarming-app> </template> <script>!function(){function t(t){return function(e){return this._attribute(e,"human_"+t)[0]}}function e(t){return function(e,a,n){var r=this._attribute(a,t)[0],i=this._attribute(n,t)[0];return e*(r-i)}}var a=["deduped_from","name","state"],n={abandoned_ts:t("abandoned_ts"),completed_ts:t("completed_ts"),costs_usd:function(t){return this._attribute(t,"costs_usd",0)[0]},created_ts:t("created_ts"),duration:t("duration"),modified_ts:t("modified_ts"),started_ts:t("started_ts"),state:function(t){var e=this._attribute(t,"state")[0];if("COMPLETED"===e){if(this._attribute(t,"failure",!1)[0])return"COMPLETED (FAILURE)";var a=this._attribute(t,"try_number","-1")[0];return"0"===a?"COMPLETED (DEDUPED)":"COMPLETED (SUCCESS)"}return e}},r={user:"Requesting User"},i={abandoned_ts:e("abandoned_ts"),completed_ts:e("completed_ts"),created_ts:e("created_ts"),duration:e("duration"),modified_ts:e("modified_ts"),started_ts:e("started_ts")};Polymer({is:"task-list",behaviors:[SwarmingBehaviors.DynamicTableBehavior],properties:{client_id:{type:String},_columnMap:{type:Object,value:function(){var t=this._commonColumns();for(var e in n)t[e]=n[e];return t}},_headerMap:{type:Object,value:r},_specialColumns:{type:Array,value:a},_specialSort:{type:Object,value:i}},_attribute:function(t,e,a){void 0===a&&(a="none");var n=this._tag(t,e)||t[e]||[a];return Array.isArray(n)?n:[n]},_cannotCancel:function(t,e){return!(e&&e.cancel_task&&"PENDING"===this._column("state",t))},_cancelTask:function(t){var e=t.model.task;if(!e||!e.task_id)return void console.log("Missing task info",e);var a=e.task_id,n="/_ah/api/swarming/v1/task/"+a+"/cancel";swarming.postWithToast(n,"Canceling task "+a,this._auth_headers)},_tag:function(t,e){if(t&&t.tagMap)return t.tagMap[e]},_taskLink:function(t){if(t)return"/user/task/"+t},_taskClass:function(t){var e=this._column("state",t);return"CANCELED"===e||"TIMED_OUT"===e||"EXPIRED"===e?"exception":"BOT_DIED"===e?"died":"COMPLETED (FAILURE)"===e?"failed":"RUNNING"===e||"PENDING"===e?"pending":""}})}()</script> </dom-module> <dom-module id="iron-collapse" assetpath="/res/imp/bower_components/iron-collapse/"> <template> <style>:host{display:block;transition-duration:var(--iron-collapse-transition-duration,300ms);overflow:visible}:host(.iron-collapse-closed){display:none}:host(:not(.iron-collapse-opened)){overflow:hidden}</style> <content></content> </template> </dom-module> <script>Polymer({is:"iron-collapse",behaviors:[Polymer.IronResizableBehavior],properties:{horizontal:{type:Boolean,value:!1,observer:"_horizontalChanged"},opened:{type:Boolean,value:!1,notify:!0,observer:"_openedChanged"},noAnimation:{type:Boolean}},get dimension(){return this.horizontal?"width":"height"},get _dimensionMax(){return this.horizontal?"maxWidth":"maxHeight"},get _dimensionMaxCss(){return this.horizontal?"max-width":"max-height"},hostAttributes:{role:"group","aria-hidden":"true","aria-expanded":"false"},listeners:{transitionend:"_transitionEnd"},attached:function(){this._transitionEnd()},toggle:function(){this.opened=!this.opened},show:function(){this.opened=!0},hide:function(){this.opened=!1},updateSize:function(t,i){var e=this.style[this._dimensionMax];if(e!==t&&("auto"!==t||e)){if(this._updateTransition(!1),i&&!this.noAnimation&&this._isDisplayed){var n=this._calcSize();"auto"===t&&(this.style[this._dimensionMax]="",t=this._calcSize()),this.style[this._dimensionMax]=n,this.scrollTop=this.scrollTop,this._updateTransition(!0)}"auto"===t?this.style[this._dimensionMax]="":this.style[this._dimensionMax]=t}},enableTransition:function(t){Polymer.Base._warn("`enableTransition()` is deprecated, use `noAnimation` instead."),this.noAnimation=!t},_updateTransition:function(t){this.style.transitionDuration=t&&!this.noAnimation?"":"0s"},_horizontalChanged:function(){this.style.transitionProperty=this._dimensionMaxCss;var t="maxWidth"===this._dimensionMax?"maxHeight":"maxWidth";this.style[t]="",this.updateSize(this.opened?"auto":"0px",!1)},_openedChanged:function(){this.setAttribute("aria-expanded",this.opened),this.setAttribute("aria-hidden",!this.opened),this.toggleClass("iron-collapse-closed",!1),this.toggleClass("iron-collapse-opened",!1),this.updateSize(this.opened?"auto":"0px",!0),this.opened&&this.focus(),this.noAnimation&&this._transitionEnd()},_transitionEnd:function(){this.opened&&(this.style[this._dimensionMax]=""),this.toggleClass("iron-collapse-closed",!this.opened),this.toggleClass("iron-collapse-opened",this.opened),this._updateTransition(!1),this.notifyResize()},get _isDisplayed(){var t=this.getBoundingClientRect();for(var i in t)if(0!==t[i])return!0;return!1},_calcSize:function(){return this.getBoundingClientRect()[this.dimension]+"px"}})</script> <script>Polymer.NeonAnimatableBehavior={properties:{animationConfig:{type:Object},entryAnimation:{observer:"_entryAnimationChanged",type:String},exitAnimation:{observer:"_exitAnimationChanged",type:String}},_entryAnimationChanged:function(){this.animationConfig=this.animationConfig||{},this.animationConfig.entry=[{name:this.entryAnimation,node:this}]},_exitAnimationChanged:function(){this.animationConfig=this.animationConfig||{},this.animationConfig.exit=[{name:this.exitAnimation,node:this}]},_copyProperties:function(i,n){for(var t in n)i[t]=n[t]},_cloneConfig:function(i){var n={isClone:!0};return this._copyProperties(n,i),n},_getAnimationConfigRecursive:function(i,n,t){if(this.animationConfig){if(this.animationConfig.value&&"function"==typeof this.animationConfig.value)return void this._warn(this._logf("playAnimation","Please put 'animationConfig' inside of your components 'properties' object instead of outside of it."));var o;if(o=i?this.animationConfig[i]:this.animationConfig,Array.isArray(o)||(o=[o]),o)for(var e,a=0;e=o[a];a++)if(e.animatable)e.animatable._getAnimationConfigRecursive(e.type||i,n,t);else if(e.id){var r=n[e.id];r?(r.isClone||(n[e.id]=this._cloneConfig(r),r=n[e.id]),this._copyProperties(r,e)):n[e.id]=e}else t.push(e)}},getAnimationConfig:function(i){var n={},t=[];this._getAnimationConfigRecursive(i,n,t);for(var o in n)t.push(n[o]);return t}}</script> <script>Polymer.NeonAnimationRunnerBehaviorImpl={_configureAnimations:function(n){var i=[];if(n.length>0)for(var e,t=0;e=n[t];t++){var o=document.createElement(e.name);if(o.isNeonAnimation){var a=null;try{a=o.configure(e),"function"!=typeof a.cancel&&(a=document.timeline.play(a))}catch(n){a=null,console.warn("Couldnt play","(",e.name,").",n)}a&&i.push({neonAnimation:o,config:e,animation:a})}else console.warn(this.is+":",e.name,"not found!")}return i},_shouldComplete:function(n){for(var i=!0,e=0;e<n.length;e++)if("finished"!=n[e].animation.playState){i=!1;break}return i},_complete:function(n){for(var i=0;i<n.length;i++)n[i].neonAnimation.complete(n[i].config);for(var i=0;i<n.length;i++)n[i].animation.cancel()},playAnimation:function(n,i){var e=this.getAnimationConfig(n);if(e){this._active=this._active||{},this._active[n]&&(this._complete(this._active[n]),delete this._active[n]);var t=this._configureAnimations(e);if(0==t.length)return void this.fire("neon-animation-finish",i,{bubbles:!1});this._active[n]=t;for(var o=0;o<t.length;o++)t[o].animation.onfinish=function(){this._shouldComplete(t)&&(this._complete(t),delete this._active[n],this.fire("neon-animation-finish",i,{bubbles:!1}))}.bind(this)}},cancelAnimation:function(){for(var n in this._animations)this._animations[n].cancel();this._animations={}}},Polymer.NeonAnimationRunnerBehavior=[Polymer.NeonAnimatableBehavior,Polymer.NeonAnimationRunnerBehaviorImpl]</script> <script>Polymer.PaperDialogBehaviorImpl={hostAttributes:{role:"dialog",tabindex:"-1"},properties:{modal:{type:Boolean,value:!1}},observers:["_modalChanged(modal, _readied)"],listeners:{tap:"_onDialogClick"},ready:function(){this.__prevNoCancelOnOutsideClick=this.noCancelOnOutsideClick,this.__prevNoCancelOnEscKey=this.noCancelOnEscKey,this.__prevWithBackdrop=this.withBackdrop},_modalChanged:function(i,e){e&&(i?(this.__prevNoCancelOnOutsideClick=this.noCancelOnOutsideClick,this.__prevNoCancelOnEscKey=this.noCancelOnEscKey,this.__prevWithBackdrop=this.withBackdrop,this.noCancelOnOutsideClick=!0,this.noCancelOnEscKey=!0,this.withBackdrop=!0):(this.noCancelOnOutsideClick=this.noCancelOnOutsideClick&&this.__prevNoCancelOnOutsideClick,this.noCancelOnEscKey=this.noCancelOnEscKey&&this.__prevNoCancelOnEscKey,this.withBackdrop=this.withBackdrop&&this.__prevWithBackdrop))},_updateClosingReasonConfirmed:function(i){this.closingReason=this.closingReason||{},this.closingReason.confirmed=i},_onDialogClick:function(i){for(var e=Polymer.dom(i).path,o=0;o<e.indexOf(this);o++){var t=e[o];if(t.hasAttribute&&(t.hasAttribute("dialog-dismiss")||t.hasAttribute("dialog-confirm"))){this._updateClosingReasonConfirmed(t.hasAttribute("dialog-confirm")),this.close(),i.stopPropagation();break}}}},Polymer.PaperDialogBehavior=[Polymer.IronOverlayBehavior,Polymer.PaperDialogBehaviorImpl]</script> <dom-module id="paper-dialog-shared-styles" assetpath="/res/imp/bower_components/paper-dialog-behavior/"> <template> <style>:host{display:block;margin:24px 40px;background:var(--paper-dialog-background-color,--primary-background-color);color:var(--paper-dialog-color,--primary-text-color);@apply(--paper-font-body1);@apply(--shadow-elevation-16dp);@apply(--paper-dialog)}:host>::content>*{margin-top:20px;padding:0 24px}:host>::content>.no-padding{padding:0}:host>::content>:first-child{margin-top:24px}:host>::content>:last-child{margin-bottom:24px}:host>::content h2{position:relative;margin:0;@apply(--paper-font-title);@apply(--paper-dialog-title)}:host>::content .buttons{position:relative;padding:8px 8px 8px 24px;margin:0;color:var(--paper-dialog-button-color,--primary-color);@apply(--layout-horizontal);@apply(--layout-end-justified)}</style> </template> </dom-module> <dom-module id="paper-dialog" assetpath="/res/imp/bower_components/paper-dialog/"> <template> <style include="paper-dialog-shared-styles"></style> <content></content> </template> </dom-module> <script>!function(){Polymer({is:"paper-dialog",behaviors:[Polymer.PaperDialogBehavior,Polymer.NeonAnimationRunnerBehavior],listeners:{"neon-animation-finish":"_onNeonAnimationFinish"},_renderOpened:function(){this.cancelAnimation(),this.playAnimation("entry")},_renderClosed:function(){this.cancelAnimation(),this.playAnimation("exit")},_onNeonAnimationFinish:function(){this.opened?this._finishRenderOpened():this._finishRenderClosed()}})}()</script> <script>Polymer.IronMenuBehaviorImpl={properties:{focusedItem:{observer:"_focusedItemChanged",readOnly:!0,type:Object},attrForItemTitle:{type:String}},hostAttributes:{role:"menu",tabindex:"0"},observers:["_updateMultiselectable(multi)"],listeners:{focus:"_onFocus",keydown:"_onKeydown","iron-items-changed":"_onIronItemsChanged"},keyBindings:{up:"_onUpKey",down:"_onDownKey",esc:"_onEscKey","shift+tab:keydown":"_onShiftTabDown"},attached:function(){this._resetTabindices()},select:function(e){this._defaultFocusAsync&&(this.cancelAsync(this._defaultFocusAsync),this._defaultFocusAsync=null);var t=this._valueToItem(e);t&&t.hasAttribute("disabled")||(this._setFocusedItem(t),Polymer.IronMultiSelectableBehaviorImpl.select.apply(this,arguments))},_resetTabindices:function(){var e=this.multi?this.selectedItems&&this.selectedItems[0]:this.selectedItem;this.items.forEach(function(t){t.setAttribute("tabindex",t===e?"0":"-1")},this)},_updateMultiselectable:function(e){e?this.setAttribute("aria-multiselectable","true"):this.removeAttribute("aria-multiselectable")},_focusWithKeyboardEvent:function(e){for(var t,s=0;t=this.items[s];s++){var i=this.attrForItemTitle||"textContent",o=t[i]||t.getAttribute(i);if(!t.hasAttribute("disabled")&&o&&o.trim().charAt(0).toLowerCase()===String.fromCharCode(e.keyCode).toLowerCase()){this._setFocusedItem(t);break}}},_focusPrevious:function(){for(var e=this.items.length,t=Number(this.indexOf(this.focusedItem)),s=1;s<e+1;s++){var i=this.items[(t-s+e)%e];if(!i.hasAttribute("disabled"))return void this._setFocusedItem(i)}},_focusNext:function(){for(var e=this.items.length,t=Number(this.indexOf(this.focusedItem)),s=1;s<e+1;s++){var i=this.items[(t+s)%e];if(!i.hasAttribute("disabled"))return void this._setFocusedItem(i)}},_applySelection:function(e,t){t?e.setAttribute("aria-selected","true"):e.removeAttribute("aria-selected"),Polymer.IronSelectableBehavior._applySelection.apply(this,arguments)},_focusedItemChanged:function(e,t){t&&t.setAttribute("tabindex","-1"),e&&(e.setAttribute("tabindex","0"),e.focus())},_onIronItemsChanged:function(e){e.detail.addedNodes.length&&this._resetTabindices()},_onShiftTabDown:function(e){var t=this.getAttribute("tabindex");Polymer.IronMenuBehaviorImpl._shiftTabPressed=!0,this._setFocusedItem(null),this.setAttribute("tabindex","-1"),this.async(function(){this.setAttribute("tabindex",t),Polymer.IronMenuBehaviorImpl._shiftTabPressed=!1},1)},_onFocus:function(e){if(!Polymer.IronMenuBehaviorImpl._shiftTabPressed){var t=Polymer.dom(e).rootTarget;(t===this||"undefined"==typeof t.tabIndex||this.isLightDescendant(t))&&(this._defaultFocusAsync=this.async(function(){var e=this.multi?this.selectedItems&&this.selectedItems[0]:this.selectedItem;this._setFocusedItem(null),e?this._setFocusedItem(e):this.items[0]&&this._focusNext()}))}},_onUpKey:function(e){this._focusPrevious(),e.detail.keyboardEvent.preventDefault()},_onDownKey:function(e){this._focusNext(),e.detail.keyboardEvent.preventDefault()},_onEscKey:function(e){this.focusedItem.blur()},_onKeydown:function(e){this.keyboardEventMatchesKeys(e,"up down esc")||this._focusWithKeyboardEvent(e),e.stopPropagation()},_activateHandler:function(e){Polymer.IronSelectableBehavior._activateHandler.call(this,e),e.stopPropagation()}},Polymer.IronMenuBehaviorImpl._shiftTabPressed=!1,Polymer.IronMenuBehavior=[Polymer.IronMultiSelectableBehavior,Polymer.IronA11yKeysBehavior,Polymer.IronMenuBehaviorImpl]</script> <script>Polymer.IronMenubarBehaviorImpl={hostAttributes:{role:"menubar"},keyBindings:{left:"_onLeftKey",right:"_onRightKey"},_onUpKey:function(e){this.focusedItem.click(),e.detail.keyboardEvent.preventDefault()},_onDownKey:function(e){this.focusedItem.click(),e.detail.keyboardEvent.preventDefault()},get _isRTL(){return"rtl"===window.getComputedStyle(this).direction},_onLeftKey:function(e){this._isRTL?this._focusNext():this._focusPrevious(),e.detail.keyboardEvent.preventDefault()},_onRightKey:function(e){this._isRTL?this._focusPrevious():this._focusNext(),e.detail.keyboardEvent.preventDefault()},_onKeydown:function(e){this.keyboardEventMatchesKeys(e,"up down left right esc")||this._focusWithKeyboardEvent(e)}},Polymer.IronMenubarBehavior=[Polymer.IronMenuBehavior,Polymer.IronMenubarBehaviorImpl]</script> <iron-iconset-svg name="paper-tabs" size="24"> <svg><defs> <g id="chevron-left"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"></path></g> <g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path></g> </defs></svg> </iron-iconset-svg> <dom-module id="paper-tab" assetpath="/res/imp/bower_components/paper-tabs/"> <template> <style>:host{@apply(--layout-inline);@apply(--layout-center);@apply(--layout-center-justified);@apply(--layout-flex-auto);position:relative;padding:0 12px;overflow:hidden;cursor:pointer;vertical-align:middle;@apply(--paper-font-common-base);@apply(--paper-tab)}:host(:focus){outline:0}:host([link]){padding:0}.tab-content{height:100%;transform:translateZ(0);-webkit-transform:translateZ(0);transition:opacity .1s cubic-bezier(.4,0,1,1);@apply(--layout-horizontal);@apply(--layout-center-center);@apply(--layout-flex-auto);@apply(--paper-tab-content)}:host(:not(.iron-selected))>.tab-content{opacity:.8;@apply(--paper-tab-content-unselected)}:host(:focus) .tab-content{opacity:1;font-weight:700}paper-ripple{color:var(--paper-tab-ink,--paper-yellow-a100)}.tab-content>::content>a{@apply(--layout-flex-auto);height:100%}</style> <div class="tab-content"> <content></content> </div> </template> <script>Polymer({is:"paper-tab",behaviors:[Polymer.IronControlState,Polymer.IronButtonState,Polymer.PaperRippleBehavior],properties:{link:{type:Boolean,value:!1,reflectToAttribute:!0}},hostAttributes:{role:"tab"},listeners:{down:"_updateNoink",tap:"_onTap"},attached:function(){this._updateNoink()},get _parentNoink(){var t=Polymer.dom(this).parentNode;return!!t&&!!t.noink},_updateNoink:function(){this.noink=!!this.noink||!!this._parentNoink},_onTap:function(t){if(this.link){var e=this.queryEffectiveChildren("a");if(!e)return;if(t.target===e)return;e.click()}}})</script> </dom-module> <dom-module id="paper-tabs" assetpath="/res/imp/bower_components/paper-tabs/"> <template> <style>:host{@apply(--layout);@apply(--layout-center);height:48px;font-size:14px;font-weight:500;overflow:hidden;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent;@apply(--paper-tabs)}:host-context([dir=rtl]){@apply(--layout-horizontal-reverse)}#tabsContainer{position:relative;height:100%;white-space:nowrap;overflow:hidden;@apply(--layout-flex-auto)}#tabsContent{height:100%;-moz-flex-basis:auto;-ms-flex-basis:auto;flex-basis:auto}#tabsContent.scrollable{position:absolute;white-space:nowrap}#tabsContent.scrollable.fit-container,#tabsContent:not(.scrollable){@apply(--layout-horizontal)}#tabsContent.scrollable.fit-container{min-width:100%}#tabsContent.scrollable.fit-container>::content>*{-ms-flex:1 0 auto;-webkit-flex:1 0 auto;flex:1 0 auto}.hidden{display:none}.not-visible{opacity:0;cursor:default}paper-icon-button{width:48px;height:48px;padding:12px;margin:0 4px}#selectionBar{position:absolute;height:2px;bottom:0;left:0;right:0;background-color:var(--paper-tabs-selection-bar-color,--paper-yellow-a100);-webkit-transform:scale(0);transform:scale(0);-webkit-transform-origin:left center;transform-origin:left center;transition:-webkit-transform;transition:transform;@apply(--paper-tabs-selection-bar)}#selectionBar.align-bottom{top:0;bottom:auto}#selectionBar.expand{transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,1,1)}#selectionBar.contract{transition-duration:.18s;transition-timing-function:cubic-bezier(0,0,.2,1)}#tabsContent>::content>:not(#selectionBar){height:100%}</style> <paper-icon-button icon="paper-tabs:chevron-left" class$="[[_computeScrollButtonClass(_leftHidden, scrollable, hideScrollButtons)]]" on-up="_onScrollButtonUp" on-down="_onLeftScrollButtonDown" tabindex="-1"></paper-icon-button> <div id="tabsContainer" on-track="_scroll" on-down="_down"> <div id="tabsContent" class$="[[_computeTabsContentClass(scrollable, fitContainer)]]"> <div id="selectionBar" class$="[[_computeSelectionBarClass(noBar, alignBottom)]]" on-transitionend="_onBarTransitionEnd"></div> <content select="*"></content> </div> </div> <paper-icon-button icon="paper-tabs:chevron-right" class$="[[_computeScrollButtonClass(_rightHidden, scrollable, hideScrollButtons)]]" on-up="_onScrollButtonUp" on-down="_onRightScrollButtonDown" tabindex="-1"></paper-icon-button> </template> <script>Polymer({is:"paper-tabs",behaviors:[Polymer.IronResizableBehavior,Polymer.IronMenubarBehavior],properties:{noink:{type:Boolean,value:!1,observer:"_noinkChanged"},noBar:{type:Boolean,value:!1},noSlide:{type:Boolean,value:!1},scrollable:{type:Boolean,value:!1},fitContainer:{type:Boolean,value:!1},disableDrag:{type:Boolean,value:!1},hideScrollButtons:{type:Boolean,value:!1},alignBottom:{type:Boolean,value:!1},selectable:{type:String,value:"paper-tab"},autoselect:{type:Boolean,value:!1},autoselectDelay:{type:Number,value:0},_step:{type:Number,value:10},_holdDelay:{type:Number,value:1},_leftHidden:{type:Boolean,value:!1},_rightHidden:{type:Boolean,value:!1},_previousTab:{type:Object}},hostAttributes:{role:"tablist"},listeners:{"iron-resize":"_onTabSizingChanged","iron-items-changed":"_onTabSizingChanged","iron-select":"_onIronSelect","iron-deselect":"_onIronDeselect"},keyBindings:{"left:keyup right:keyup":"_onArrowKeyup"},created:function(){this._holdJob=null,this._pendingActivationItem=void 0,this._pendingActivationTimeout=void 0,this._bindDelayedActivationHandler=this._delayedActivationHandler.bind(this),this.addEventListener("blur",this._onBlurCapture.bind(this),!0)},ready:function(){this.setScrollDirection("y",this.$.tabsContainer)},detached:function(){this._cancelPendingActivation()},_noinkChanged:function(t){var e=Polymer.dom(this).querySelectorAll("paper-tab");e.forEach(t?this._setNoinkAttribute:this._removeNoinkAttribute)},_setNoinkAttribute:function(t){t.setAttribute("noink","")},_removeNoinkAttribute:function(t){t.removeAttribute("noink")},_computeScrollButtonClass:function(t,e,i){return!e||i?"hidden":t?"not-visible":""},_computeTabsContentClass:function(t,e){return t?"scrollable"+(e?" fit-container":""):" fit-container"},_computeSelectionBarClass:function(t,e){return t?"hidden":e?"align-bottom":""},_onTabSizingChanged:function(){this.debounce("_onTabSizingChanged",function(){this._scroll(),this._tabChanged(this.selectedItem)},10)},_onIronSelect:function(t){this._tabChanged(t.detail.item,this._previousTab),this._previousTab=t.detail.item,this.cancelDebouncer("tab-changed")},_onIronDeselect:function(t){this.debounce("tab-changed",function(){this._tabChanged(null,this._previousTab),this._previousTab=null},1)},_activateHandler:function(){this._cancelPendingActivation(),Polymer.IronMenuBehaviorImpl._activateHandler.apply(this,arguments)},_scheduleActivation:function(t,e){this._pendingActivationItem=t,this._pendingActivationTimeout=this.async(this._bindDelayedActivationHandler,e)},_delayedActivationHandler:function(){var t=this._pendingActivationItem;this._pendingActivationItem=void 0,this._pendingActivationTimeout=void 0,t.fire(this.activateEvent,null,{bubbles:!0,cancelable:!0})},_cancelPendingActivation:function(){void 0!==this._pendingActivationTimeout&&(this.cancelAsync(this._pendingActivationTimeout),this._pendingActivationItem=void 0,this._pendingActivationTimeout=void 0)},_onArrowKeyup:function(t){this.autoselect&&this._scheduleActivation(this.focusedItem,this.autoselectDelay)},_onBlurCapture:function(t){t.target===this._pendingActivationItem&&this._cancelPendingActivation()},get _tabContainerScrollSize(){return Math.max(0,this.$.tabsContainer.scrollWidth-this.$.tabsContainer.offsetWidth)},_scroll:function(t,e){if(this.scrollable){var i=e&&-e.ddx||0;this._affectScroll(i)}},_down:function(t){this.async(function(){this._defaultFocusAsync&&(this.cancelAsync(this._defaultFocusAsync),this._defaultFocusAsync=null)},1)},_affectScroll:function(t){this.$.tabsContainer.scrollLeft+=t;var e=this.$.tabsContainer.scrollLeft;this._leftHidden=0===e,this._rightHidden=e===this._tabContainerScrollSize},_onLeftScrollButtonDown:function(){this._scrollToLeft(),this._holdJob=setInterval(this._scrollToLeft.bind(this),this._holdDelay)},_onRightScrollButtonDown:function(){this._scrollToRight(),this._holdJob=setInterval(this._scrollToRight.bind(this),this._holdDelay)},_onScrollButtonUp:function(){clearInterval(this._holdJob),this._holdJob=null},_scrollToLeft:function(){this._affectScroll(-this._step)},_scrollToRight:function(){this._affectScroll(this._step)},_tabChanged:function(t,e){if(!t)return this.$.selectionBar.classList.remove("expand"),this.$.selectionBar.classList.remove("contract"),void this._positionBar(0,0);var i=this.$.tabsContent.getBoundingClientRect(),n=i.width,o=t.getBoundingClientRect(),s=o.left-i.left;if(this._pos={width:this._calcPercent(o.width,n),left:this._calcPercent(s,n)},this.noSlide||null==e)return this.$.selectionBar.classList.remove("expand"),this.$.selectionBar.classList.remove("contract"),void this._positionBar(this._pos.width,this._pos.left);var a=e.getBoundingClientRect(),l=this.items.indexOf(e),c=this.items.indexOf(t),r=5;this.$.selectionBar.classList.add("expand");var h=l<c,d=this._isRTL;d&&(h=!h),h?this._positionBar(this._calcPercent(o.left+o.width-a.left,n)-r,this._left):this._positionBar(this._calcPercent(a.left+a.width-o.left,n)-r,this._calcPercent(s,n)+r),this.scrollable&&this._scrollToSelectedIfNeeded(o.width,s)},_scrollToSelectedIfNeeded:function(t,e){var i=e-this.$.tabsContainer.scrollLeft;i<0?this.$.tabsContainer.scrollLeft+=i:(i+=t-this.$.tabsContainer.offsetWidth,i>0&&(this.$.tabsContainer.scrollLeft+=i))},_calcPercent:function(t,e){return 100*t/e},_positionBar:function(t,e){t=t||0,e=e||0,this._width=t,this._left=e,this.transform("translateX("+e+"%) scaleX("+t/100+")",this.$.selectionBar)},_onBarTransitionEnd:function(t){var e=this.$.selectionBar.classList;e.contains("expand")?(e.remove("expand"),e.add("contract"),this._positionBar(this._pos.width,this._pos.left)):e.contains("contract")&&e.remove("contract")}})</script> </dom-module> <script>!function(){SwarmingBehaviors.BotPageBehavior=[SwarmingBehaviors.CommonBehavior,{_timeDiffApprox:function(e){return e?sk.human.diffDate(e.getTime()):"eons"},_timeDiffExact:function(e,i){return e?(i||(i=new Date),sk.human.strDuration((i.getTime()-e.getTime())/1e3)):"eons"}}]}()</script> <dom-module id="bot-page-data" assetpath="/res/imp/botpage/"> <script>!function(){function t(t){if(!s){var e=t.toString();s=e.substring(e.indexOf("("))}return t.toLocaleString()+" "+s}var e,s,a=400,n=["first_seen_ts","last_seen_ts"],i=["started_ts","completed_ts","abandoned_ts","modified_ts"];Polymer({is:"bot-page-data",behaviors:[SwarmingBehaviors.BotPageBehavior],properties:{auth_headers:{type:Object},bot_id:{type:String},busy:{type:Boolean,computed:"_or(_busy1,_busy2,_busy3)",notify:!0},bot:{type:Object,computed:"_parseBot(_bot)",notify:!0},events:{type:Array,computed:"_parseEvents(_events)",notify:!0},tasks:{type:Array,computed:"_parseTasks(_tasks)",notify:!0},_busy1:{type:Boolean,value:!1},_busy2:{type:Boolean,value:!1},_busy3:{type:Boolean,value:!1},_bot:{type:Object},_events:{type:Object},_tasks:{type:Object}},observers:["request(auth_headers,bot_id)"],request:function(){this.bot_id&&this.auth_headers&&(e&&this.cancelAsync(e),e=this.async(function(){e=void 0;var t="/_ah/api/swarming/v1/bot/"+this.bot_id;this._getJsonAsync("_bot",t+"/get","_busy1",this.auth_headers),this._getJsonAsync("_events",t+"/events?fields=items(event_type%2Cmessage%2Cquarantined%2Ctask_id%2Cts%2Cversion)","_busy2",this.auth_headers),this._getJsonAsync("_tasks",t+"/tasks?fields=items(abandoned_ts%2Cbot_version%2Ccompleted_ts%2Cduration%2Cexit_code%2Cfailure%2Cinternal_failure%2Cmodified_ts%2Cname%2Cstarted_ts%2Cstate%2Ctask_id%2Ctry_number)","_busy3",this.auth_headers)},a))},_parseBot:function(e){if(!e)return{};e.state=e.state||"{}",e.state=JSON.parse(e.state);var s=e.state.disks||{},a=Object.keys(s);if(a.length){e.disks=[];for(var i=0;i<a.length;i++)e.disks.push({id:a[i],mb:s[a[i]].free_mb});e.disks.sort(function(t,e){return e.mb-t.mb})}else e.disks=[{id:"unknown",mb:0}];return e.dimensions=e.dimensions||[],e.dimensions.forEach(function(t){swarming.alias.DIMENSIONS_WITH_ALIASES.indexOf(t.key)!==-1&&t.value.forEach(function(e,s){t.value[s]=swarming.alias.apply(e,t.key)})}),n.forEach(function(s){e[s]&&(e[s]=new Date(e[s]),e["human_"+s]=t(e[s]))}),e},_parseEvents:function(e){if(!e||!e.items)return[];var e=e.items;return e.forEach(function(e){e.ts&&(e.ts=new Date(e.ts),e.human_ts=t(e.ts))}),e.sort(function(t,e){return e.ts-t.ts}),e},_parseTasks:function(e){if(!e||!e.items)return[];var e=e.items;return e.forEach(function(e){if(i.forEach(function(s){e[s]&&(e[s]=new Date(e[s]),e["human_"+s]=t(e[s]))}),e.duration)e.human_duration=sk.human.strDuration(e.duration)||"0s";else{var s=e.completed_ts||e.abandoned_ts||e.modified_ts||new Date;e.human_duration=this._timeDiffExact(e.started_ts,s)}e.state=e.state||"UNKNOWN","COMPLETED"===e.state&&(e.failure?e.state="FAILURE":e.state="SUCCESS")}.bind(this)),e.sort(function(t,e){return e.started_ts-t.started_ts}),e}})}()</script> </dom-module> <dom-module id="bot-page" assetpath="/res/imp/botpage/"> <template> <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-style">.header{max-width:450px}.title{font-size:1.5em;font-weight:700;margin-bottom:5px}.id_input{--paper-input-container-input:{font-size:2em};}.refresh{max-width:50px;max-height:50px;width:initial;height:initial}table{border-collapse:collapse;margin-left:5px;margin-bottom:5px}td,th{border:1px solid #BBB;padding:5px}.failed_task,.quarantined{background-color:#fdd}.bot_died,.dead{background-color:#ccc}.message{white-space:pre-line;font-family:monospace}.bot_state{white-space:pre;font-family:monospace;margin-bottom:10px}.tabs{background-color:#1F78B4;color:#fff;max-width:600px;--paper-checkbox-label-color:#fff;margin-left:5px}.events_table,.tasks_table{border:3px solid #1F78B4}paper-checkbox{--paper-checkbox-label-color:#fff;--paper-checkbox-checked-color:#fff;--paper-checkbox-checkmark-color:#000;--paper-checkbox-unchecked-color:#fff;padding:3px}paper-tab.iron-selected{background-color:#A6CEE3;border:3px solid #1F78B4;color:#000;font-weight:700;text-decoration:underline}paper-dialog{border-radius:6px}</style> <url-param name="id" value="{{bot_id}}"> </url-param> <url-param name="show_all_events" value="{{_show_all}}"> </url-param> <url-param name="selected" value="{{_selected}}"> </url-param> <url-param name="show_state" value="{{_show_state}}"> </url-param> <swarming-app client_id="[[client_id]]" auth_headers="{{_auth_headers}}" permissions="{{_permissions}}" signed_in="{{_signed_in}}" busy="[[_busy]]" name="Swarming Bot Page"> <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2> <div hidden$="[[_not(_signed_in)]]"> <bot-page-data id="data" auth_headers="[[_auth_headers]]" bot_id="[[bot_id]]" bot="{{_bot}}" busy="{{_busy}}" events="{{_events}}" tasks="{{_tasks}}"> </bot-page-data> <div class="header horizontal layout"> <paper-input class="id_input" label="Bot id" value="{{bot_id}}"></paper-input> <button on-click="_refresh"> <iron-icon class="refresh" icon="icons:refresh"></iron-icon> </button> </div> <div> <table> <tbody><tr class$="[[_isDead(_bot)]]"> <td>Last Seen</td> <td title="[[_bot.human_last_seen_ts]]"> [[_timeDiffExact(_bot.last_seen_ts)]] ago</td> <td> <template is="dom-if" if="[[_canShutdown(_bot,_permissions)]]"> <button class="raised" on-click="_promptShutdown"> Shut Down Gracefully </button> </template> <template is="dom-if" if="[[_canDelete(_bot,_permissions)]]"> <button class="raised" on-click="_promptDelete"> Delete </button> </template> </td> </tr> <template is="dom-if" if="[[_bot.quarantined]]"> <tr class="quarantined"> <td>Quarantined</td> <td colspan="2">[[_quarantineMessage(_bot)]]</td> </tr> </template> <tr> <td>Current Task</td> <td> <a target="_blank" href$="[[_taskLink(_bot.task_id)]]"> [[_task(_bot)]] </a> </td> <td> </td> </tr> <tr> <td rowspan$="[[_numRows(_bot.dimensions)]]">Dimensions</td> </tr> <template is="dom-repeat" items="[[_bot.dimensions]]" as="dim"> <tr> <td>[[dim.key]]</td> <td>[[_concat(dim.value)]]</td> </tr> </template> <tr> <td>External IP</td> <td><a href$="[[_bot.external_ip]]">[[_bot.external_ip]]</a></td> <td></td> </tr> <tr> <td>Swarming Revision</td> <td> <a target="_blank" href$="[[_luciLink(_bot.version)]]">[[_shorten(_bot.version,'8')]]</a> </td> <td></td> </tr> <tr> <td>First seen</td> <td title="[[_bot.human_first_seen_ts]]"> [[_timeDiffApprox(_bot.first_seen_ts)]] ago </td> <td></td> </tr> <tr> <td>Authenticated as</td> <td>[[_bot.authenticated_as]]</td> <td></td> </tr> </tbody></table> <span class="title">State</span> <template is="dom-if" if="[[_not(_show_state)]]"> <button on-click="_toggleState"> <iron-icon icon="icons:add-circle-outline"></iron-icon> </button> </template> <template is="dom-if" if="[[_show_state]]"> <button on-click="_toggleState"> <iron-icon icon="icons:remove-circle-outline"></iron-icon> </button> </template> <iron-collapse id="collapse" opened="[[_show_state]]"> <div class="bot_state">[[_prettyPrint(_bot.state)]]</div> </iron-collapse> </div> <div class="tabs"> <paper-tabs selected="{{_selected}}" no-bar=""> <paper-tab>Tasks</paper-tab> <paper-tab>Events</paper-tab> </paper-tabs> <template is="dom-if" if="[[_selected]]"> <paper-checkbox checked="{{_show_all}}"> Show all events </paper-checkbox> </template> </div> <template is="dom-if" if="[[_not(_selected)]]"> <table class="tasks_table"> <thead> <tr> <th>Task</th> <th>Started</th> <th>Duration</th> <th>Result</th> </tr> </thead> <tbody> <template is="dom-repeat" items="{{_tasks}}" as="task"> <tr class$="[[_taskClass(task)]]"> <td><a target="_blank" href$="[[_taskLink(task.task_id)]]">[[task.name]]</a></td> <td>[[task.human_started_ts]]</td> <td title="[[task.human_completed_ts]]">[[task.human_duration]]</td> <td>[[task.state]]</td> </tr> </template> </tbody> </table> </template> <template is="dom-if" if="[[_selected]]"> <table class="events_table"> <thead> <tr> <th>Message</th> <th>Type</th> <th>Timestamp</th> <th>Task ID</th> <th>Version</th> </tr> </thead> <tbody> <template is="dom-repeat" items="{{_eventList(_events,_show_all)}}" as="event"> <tr> <td class="message">[[event.message]]</td> <td>[[event.event_type]]</td> <td>[[event.human_ts]]</td> <td><a target="_blank" href$="[[_taskLink(event.task_id)]]">[[event.task_id]]</a></td> <td> <a target="_blank" href$="[[_luciLink(_bot.version)]]">[[_shorten(_bot.version,'8')]]</a> </td> </tr> </template> </tbody> </table> </template> </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> </template> <script> (function(){
|
| + })(); </script> </dom-module> <dom-module id="paper-material" assetpath="/res/imp/bower_components/paper-material/"> <template> <style include="paper-material-shared-styles"></style> <style>:host([animated]){@apply(--shadow-transition)}</style> <content></content> </template> </dom-module> <script>Polymer({is:"paper-material",properties:{elevation:{type:Number,reflectToAttribute:!0,value:1},animated:{type:Boolean,reflectToAttribute:!0,value:!1}}})</script> <dom-module id="paper-button" assetpath="/res/imp/bower_components/paper-button/"> <template strip-whitespace=""> <style include="paper-material">:host{@apply(--layout-inline);@apply(--layout-center-center);position:relative;box-sizing:border-box;min-width:5.14em;margin:0 .29em;background:0 0;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent;font:inherit;text-transform:uppercase;outline-width:0;border-radius:3px;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none;cursor:pointer;z-index:0;padding:.7em .57em;@apply(--paper-font-common-base);@apply(--paper-button)}:host([raised].keyboard-focus){font-weight:700;@apply(--paper-button-raised-keyboard-focus)}:host(:not([raised]).keyboard-focus){font-weight:700;@apply(--paper-button-flat-keyboard-focus)}:host([disabled]){background:#eaeaea;color:#a8a8a8;cursor:auto;pointer-events:none;@apply(--paper-button-disabled)}paper-ripple{color:var(--paper-button-ink-color)}</style> <content></content> </template> <script>Polymer({is:"paper-button",behaviors:[Polymer.PaperButtonBehavior],properties:{raised:{type:Boolean,reflectToAttribute:!0,value:!1,observer:"_calculateElevation"}},_calculateElevation:function(){this.raised?Polymer.PaperButtonBehaviorImpl._calculateElevation.apply(this):this._setElevation(0)}})</script> </dom-module> <script>Polymer.NeonAnimatableBehavior={properties:{animationConfig:{type:Object},entryAnimation:{observer:"_entryAnimationChanged",type:String},exitAnimation:{observer:"_exitAnimationChanged",type:String}},_entryAnimationChanged:function(){this.animationConfig=this.animationConfig||{},this.animationConfig.entry=[{name:this.entryAnimation,node:this}]},_exitAnimationChanged:function(){this.animationConfig=this.animationConfig||{},this.animationConfig.exit=[{name:this.exitAnimation,node:this}]},_copyProperties:function(i,n){for(var t in n)i[t]=n[t]},_cloneConfig:function(i){var n={isClone:!0};return this._copyProperties(n,i),n},_getAnimationConfigRecursive:function(i,n,t){if(this.animationConfig){if(this.animationConfig.value&&"function"==typeof this.animationConfig.value)return void this._warn(this._logf("playAnimation","Please put 'animationConfig' inside of your components 'properties' object instead of outside of it."));var o;if(o=i?this.animationConfig[i]:this.animationConfig,Array.isArray(o)||(o=[o]),o)for(var e,a=0;e=o[a];a++)if(e.animatable)e.animatable._getAnimationConfigRecursive(e.type||i,n,t);else if(e.id){var r=n[e.id];r?(r.isClone||(n[e.id]=this._cloneConfig(r),r=n[e.id]),this._copyProperties(r,e)):n[e.id]=e}else t.push(e)}},getAnimationConfig:function(i){var n={},t=[];this._getAnimationConfigRecursive(i,n,t);for(var o in n)t.push(n[o]);return t}}</script> <script>Polymer.NeonAnimationRunnerBehaviorImpl={_configureAnimations:function(n){var i=[];if(n.length>0)for(var e,t=0;e=n[t];t++){var o=document.createElement(e.name);if(o.isNeonAnimation){var a=null;try{a=o.configure(e),"function"!=typeof a.cancel&&(a=document.timeline.play(a))}catch(n){a=null,console.warn("Couldnt play","(",e.name,").",n)}a&&i.push({neonAnimation:o,config:e,animation:a})}else console.warn(this.is+":",e.name,"not found!")}return i},_shouldComplete:function(n){for(var i=!0,e=0;e<n.length;e++)if("finished"!=n[e].animation.playState){i=!1;break}return i},_complete:function(n){for(var i=0;i<n.length;i++)n[i].neonAnimation.complete(n[i].config);for(var i=0;i<n.length;i++)n[i].animation.cancel()},playAnimation:function(n,i){var e=this.getAnimationConfig(n);if(e){this._active=this._active||{},this._active[n]&&(this._complete(this._active[n]),delete this._active[n]);var t=this._configureAnimations(e);if(0==t.length)return void this.fire("neon-animation-finish",i,{bubbles:!1});this._active[n]=t;for(var o=0;o<t.length;o++)t[o].animation.onfinish=function(){this._shouldComplete(t)&&(this._complete(t),delete this._active[n],this.fire("neon-animation-finish",i,{bubbles:!1}))}.bind(this)}},cancelAnimation:function(){for(var n in this._animations)this._animations[n].cancel();this._animations={}}},Polymer.NeonAnimationRunnerBehavior=[Polymer.NeonAnimatableBehavior,Polymer.NeonAnimationRunnerBehaviorImpl]</script> <script>Polymer.PaperDialogBehaviorImpl={hostAttributes:{role:"dialog",tabindex:"-1"},properties:{modal:{type:Boolean,value:!1}},observers:["_modalChanged(modal, _readied)"],listeners:{tap:"_onDialogClick"},ready:function(){this.__prevNoCancelOnOutsideClick=this.noCancelOnOutsideClick,this.__prevNoCancelOnEscKey=this.noCancelOnEscKey,this.__prevWithBackdrop=this.withBackdrop},_modalChanged:function(i,e){e&&(i?(this.__prevNoCancelOnOutsideClick=this.noCancelOnOutsideClick,this.__prevNoCancelOnEscKey=this.noCancelOnEscKey,this.__prevWithBackdrop=this.withBackdrop,this.noCancelOnOutsideClick=!0,this.noCancelOnEscKey=!0,this.withBackdrop=!0):(this.noCancelOnOutsideClick=this.noCancelOnOutsideClick&&this.__prevNoCancelOnOutsideClick,this.noCancelOnEscKey=this.noCancelOnEscKey&&this.__prevNoCancelOnEscKey,this.withBackdrop=this.withBackdrop&&this.__prevWithBackdrop))},_updateClosingReasonConfirmed:function(i){this.closingReason=this.closingReason||{},this.closingReason.confirmed=i},_onDialogClick:function(i){for(var e=Polymer.dom(i).path,o=0;o<e.indexOf(this);o++){var t=e[o];if(t.hasAttribute&&(t.hasAttribute("dialog-dismiss")||t.hasAttribute("dialog-confirm"))){this._updateClosingReasonConfirmed(t.hasAttribute("dialog-confirm")),this.close(),i.stopPropagation();break}}}},Polymer.PaperDialogBehavior=[Polymer.IronOverlayBehavior,Polymer.PaperDialogBehaviorImpl]</script> <dom-module id="paper-dialog-shared-styles" assetpath="/res/imp/bower_components/paper-dialog-behavior/"> <template> <style>:host{display:block;margin:24px 40px;background:var(--paper-dialog-background-color,--primary-background-color);color:var(--paper-dialog-color,--primary-text-color);@apply(--paper-font-body1);@apply(--shadow-elevation-16dp);@apply(--paper-dialog)}:host>::content>*{margin-top:20px;padding:0 24px}:host>::content>.no-padding{padding:0}:host>::content>:first-child{margin-top:24px}:host>::content>:last-child{margin-bottom:24px}:host>::content h2{position:relative;margin:0;@apply(--paper-font-title);@apply(--paper-dialog-title)}:host>::content .buttons{position:relative;padding:8px 8px 8px 24px;margin:0;color:var(--paper-dialog-button-color,--primary-color);@apply(--layout-horizontal);@apply(--layout-end-justified)}</style> </template> </dom-module> <dom-module id="paper-dialog" assetpath="/res/imp/bower_components/paper-dialog/"> <template> <style include="paper-dialog-shared-styles"></style> <content></content> </template> </dom-module> <script>!function(){Polymer({is:"paper-dialog",behaviors:[Polymer.PaperDialogBehavior,Polymer.NeonAnimationRunnerBehavior],listeners:{"neon-animation-finish":"_onNeonAnimationFinish"},_renderOpened:function(){this.cancelAnimation(),this.playAnimation("entry")},_renderClosed:function(){this.cancelAnimation(),this.playAnimation("exit")},_onNeonAnimationFinish:function(){this.opened?this._finishRenderOpened():this._finishRenderClosed()}})}()</script> <dom-module id="error-toast" assetpath="/res/imp/common/"> <template> <paper-toast id="toast"></paper-toast> </template> </dom-module> <script>Polymer({is:"error-toast",ready:function(){document.addEventListener("error-sk",function(t){if(this.$.toast.close(),t.detail.message){this.$.toast.text=t.detail.message;var e=1e4;void 0!==t.detail.duration&&(e=t.detail.duration),this.$.toast.duration=e,this.$.toast.show()}else console.log("Empty message?",t)}.bind(this))}})</script> <dom-module id="task-filters" assetpath="/res/imp/tasklist/"> <template> <style is="custom-style" include="iron-flex iron-flex-alignment iron-positioning query-column-filter-style">.item.wide{max-width:400px}.selector.wide{min-width:275px}</style> <url-param name="filters" value="{{_filters}}" default_values="[]" multi=""> </url-param> <url-param name="columns" value="{{columns}}" default_values="["name","state","created_ts","user"]" multi=""> </url-param> <url-param name="query" value="{{_query}}" default_value=""> </url-param> <url-param name="limit" default_value="200" value="{{limit}}"> </url-param> <div class="container horizontal layout"> <div class="narrow-down-selector"> <div> <paper-input id="filter" label="Search columns and filters" placeholder="gpu nvidia" value="{{_query}}"> </paper-input> </div> <div class="wide selector side-by-side" title="This shows all task tags and other interesting task properties. Mark the check box to add as a column. Select the row to see filter options."> <iron-selector attr-for-selected="label" selected="{{_primarySelected}}"> <template is="dom-repeat" items="[[_primaryItems]]" as="item"> <div class="selectable item horizontal layout" label="[[item]]"> <span>[[_beforeBold(item,_query)]]<span class="bold">[[_bold(item,_query)]]</span>[[_afterBold(item,_query)]]</span> <span class="flex"></span> <paper-checkbox noink="" disabled$="[[_cantToggleColumn(item)]]" checked="[[_columnState(item,columns.*)]]" on-change="_toggleColumn"> </paper-checkbox> </div> </template> </iron-selector> </div> <div class="selector side-by-side" title="These are all options (if any) that the task list can be filtered on."> <template is="dom-repeat" id="secondaryList" items="[[_secondaryItems]]" as="item"> <div class="item horizontal layout" label="[[item]]"> <span>[[_beforeBold(item,_query)]]<span class="bold">[[_bold(item,_query)]]</span>[[_afterBold(item,_query)]]</span> <span class="flex"></span> <iron-icon class="icons" icon="icons:arrow-forward" hidden="[[_cantAddFilter(_primarySelected,item,_filters.*)]]" on-tap="_addFilter"> </iron-icon> </div> </template> </div> <div class="selector side-by-side" title="These tag filters are AND'd together and applied to all tasks."> <template is="dom-repeat" items="[[_filters]]" as="fil"> <div class="item horizontal layout" label="[[fil]]"> <span>[[fil]]</span> <span class="flex"></span> <iron-icon class="icons" icon="icons:remove-circle-outline" hidden="[[_cantRemoveFilter(fil,_filters.*)]]" on-tap="_removeFilter"> </iron-icon> </div> </template> </div> <div class="side-by-side"> <paper-input id="limit" label="Limit Results" auto-validate="" min="0" max="1000" pattern="[0-9]+" value="{{limit}}"> </paper-input> </div> </div> </div> </template> <script>!function(){var t={state:function(t,r){var i=this._attribute(t,"state")[0];if(r===i)return!0;if("PENDING_RUNNING"===r)return"PENDING"===i||"RUNNING"===i;var e=this._attribute(t,"failure",!1)[0];if("COMPLETED_SUCCESS"===r)return"COMPLETED"===i&&!e;if("COMPLETED_FAILURE"===r)return"COMPLETED"===i&&e;var a=this._attribute(t,"try_number","-1")[0];return"DEDUPED"===r?"COMPLETED"===i&&"0"===a:void 0}};Polymer({is:"task-filters",behaviors:[SwarmingBehaviors.QueryColumnFilter],properties:{columns:{type:Array,notify:!0},query_params:{type:Object,computed:"_extractQueryParams(_filters.*, limit)",notify:!0},_filterMap:{type:Object,value:function(){var r=this._commonFilters();for(var i in t)r[i]=t[i];return r}}},_cantToggleColumn:function(t){return!t||"name"===t},_extractQueryParams:function(){var t={},r=[];this._filters.forEach(function(i){var e=i.split(this.FILTER_SEP,1),a=e[0],n=i.substring(a.length+this.FILTER_SEP.length);"state"===a?t.state=[n]:r.push(a+this.FILTER_SEP+swarming.alias.unapply(n))}.bind(this)),t.tags=r;var i=Math.floor(this.limit);return Number.isInteger(i)&&(i=Math.max(i,1),i=Math.min(1e3,i),t.limit=[i],this.limit!=i&&this.set("limit",i)),t}})}()</script> </dom-module><dom-module id="task-list-data" assetpath="/res/imp/tasklist/"> <script>!function(){var t=["abandoned_ts","completed_ts","created_ts","modified_ts","started_ts"];Polymer({is:"task-list-data",behaviors:[SwarmingBehaviors.CommonBehavior],properties:{auth_headers:{type:Object,observer:"signIn"},query_params:{type:Object,observer:"_request"},busy:{type:Boolean,computed:"_or(_busy1,_busy2,_busy3)",notify:!0},primary_map:{type:Object,computed:"_primaryMap(_tags,_dimensions,tasks)",notify:!0},primary_arr:{type:Array,computed:"_primaryArr(primary_map)",notify:!0},tasks:{type:Array,computed:"_tasks(_list)",notify:!0},_busy1:{type:Boolean,value:!1},_busy2:{type:Boolean,value:!1},_busy3:{type:Boolean,value:!1},_dimensions:{type:Object},_list:{type:Object},_tags:{type:Object}},signIn:function(){this._getJsonAsync("_tags","/_ah/api/swarming/v1/tasks/tags","_busy2",this.auth_headers),this._getJsonAsync("_dimensions","/_ah/api/swarming/v1/bots/dimensions","_busy3",this.auth_headers),this._request()},_primaryArr:function(t){var s=Object.keys(t);return s.sort(),s},_primaryMap:function(s,e,a){s=s&&s.tasks_tags||[],e=e&&e.bots_dimensions||[],a=a||[];var r={};s.forEach(function(t){r[t.key]||(r[t.key]={});var s=t.value||[];s.forEach(function(s){r[t.key][s]=!0})}),e.forEach(function(t){var s=t.value;r[t.key]||(r[t.key]={}),s.forEach(function(s){r[t.key][s]=!0})}),a.forEach(function(t){Object.keys(t.tagMap).forEach(function(s){var e=t.tagMap[s];r[s]||(r[s]={}),r[s][e]=!0})});var i={};for(key in r){var n=Object.keys(r[key]);if(swarming.alias.DIMENSIONS_WITH_ALIASES.indexOf(key)===-1)i[key]=n;else{var o=[];n.forEach(function(t){o.push(swarming.alias.apply(t,key))}),i[key]=o}}return i.android_devices.push("0"),i.device_os.push("none"),i.device_type.push("none"),i.user.push("none"),i.name=[],i.state=["PENDING","RUNNING","PENDING_RUNNING","COMPLETED","COMPLETED_SUCCESS","COMPLETED_FAILURE","EXPIRED","TIMED_OUT","BOT_DIED","CANCELED","ALL","DEDUPED"],i.costs_usd=[],i.deduped_from=[],i.duration=[],i.server_versions=[],t.forEach(function(t){i[t]=[]}),i},_request:function(){this.auth_headers&&this.query_params&&this._getJsonAsync("_list","/_ah/api/swarming/v1/tasks/list","_busy1",this.auth_headers,this.query_params)},_tasks:function(){if(!this._list||!this._list.items)return[];var s=new Date,e=s.toString(),a=e.substring(e.indexOf("("));return this._list.items.forEach(function(e){var r={};e.tags.forEach(function(t){var s=t.split(":",1),e=s[0],a=t.substring(e.length+1);r[e]=a}),e.tagMap=r,t.forEach(function(t){if(e[t]){e[t]=new Date(e[t]);var s=e[t].toLocaleString();e["human_"+t]=s+" "+a}}),!e.duration&&"RUNNING"===e.state&&e.started_ts&&(e.duration=(s-e.started_ts)/1e3),e.duration&&(e.human_duration=sk.human.strDuration(e.duration))}),this._list.items}})}()</script> </dom-module> <dom-module id="task-list" assetpath="/res/imp/tasklist/"> <template> <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-style dynamic-table-style">task-filters{margin-bottom:8px;margin-right:10px}.task-list th>span{padding-right:30px}.failed{background-color:#fdd}.died{background-color:#ccc}.exception{background-color:#edd2ff}.pending{background-color:#fffc6c}</style> <url-param name="sort" value="{{_sortstr}}" default_value="created_ts:desc"> </url-param> <swarming-app client_id="[[client_id]]" auth_headers="{{_auth_headers}}" permissions="{{_permissions}}" signed_in="{{_signed_in}}" busy="[[_busy]]" name="Swarming Task List"> <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2> <div hidden$="[[_not(_signed_in)]]"> <task-list-data auth_headers="[[_auth_headers]]" query_params="[[_query_params]]" tasks="{{_items}}" busy="{{_busy}}" primary_map="{{_primary_map}}" primary_arr="{{_primary_arr}}"> </task-list-data> <div class="horizontal layout"> <task-filters primary_map="[[_primary_map]]" primary_arr="[[_primary_arr]]" columns="{{_columns}}" query_params="{{_query_params}}" filter="{{_filter}}"> </task-filters> </div> <table class="task-list"> <thead on-sort_change="_sortChange"> <tr> <th> <span>Task Name</span> <sort-toggle name="name" current="[[_sort]]"> </sort-toggle> </th> <th hidden$="[[_hide('state', _columns.*)]]"> <span>State</span> <sort-toggle name="state" current="[[_sort]]"> </sort-toggle> </th> <th hidden$="[[_hide('deduped_from', _columns.*)]]"> <span>Deduped from</span> <sort-toggle name="deduped_from" current="[[_sort]]"> </sort-toggle> </th> <template is="dom-repeat" items="[[_plainColumns]]" as="c"> <th hidden$="[[_hide(c)]]"> <span>[[_header(c)]]</span> <sort-toggle name="[[c]]" current="[[_sort]]"> </sort-toggle> </th> </template> </tr> </thead> <tbody> <template id="tasks_table" is="dom-repeat" items="[[_filteredSortedItems]]" as="task" initial-count="50"> <tr class$="[[_taskClass(task)]]"> <td> <a class="center" href$="[[_taskLink(task.task_id)]]" target="_blank"> [[task.name]] </a> </td> <td hidden$="[[_hide('state', _columns.*)]]"> [[_column('state', task)]] <paper-button raised="" hidden$="[[_cannotCancel(task,_permissions)]]" on-tap="_promptCancel"> Cancel </paper-button> </td> <td hidden$="[[_hide('deduped_from', _columns.*)]]"> <a class="center" href$="[[_taskLink(task.deduped_from)]]" target="_blank"> [[_column('deduped_from',task)]] </a> </td> <template is="dom-repeat" items="[[_plainColumns]]" as="c"> <td hidden$="[[_hide(c)]]"> [[_column(c, task)]] </td> </template> </tr> </template> </tbody> </table> </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> </template> <script>!function(){function t(t){return function(e){return this._attribute(e,"human_"+t)[0]}}function e(t){return function(e,a,n){var i=this._attribute(a,t)[0],s=this._attribute(n,t)[0];return e*(i-s)}}var a=["deduped_from","name","state"],n={abandoned_ts:t("abandoned_ts"),completed_ts:t("completed_ts"),costs_usd:function(t){return this._attribute(t,"costs_usd",0)[0]},created_ts:t("created_ts"),duration:t("duration"),modified_ts:t("modified_ts"),started_ts:t("started_ts"),state:function(t){var e=this._attribute(t,"state")[0];if("COMPLETED"===e){if(this._attribute(t,"failure",!1)[0])return"COMPLETED (FAILURE)";var a=this._attribute(t,"try_number","-1")[0];return"0"===a?"COMPLETED (DEDUPED)":"COMPLETED (SUCCESS)"}return e}},i={user:"Requesting User"},s={abandoned_ts:e("abandoned_ts"),completed_ts:e("completed_ts"),created_ts:e("created_ts"),duration:e("duration"),modified_ts:e("modified_ts"),started_ts:e("started_ts")};Polymer({is:"task-list",behaviors:[SwarmingBehaviors.DynamicTableBehavior],properties:{client_id:{type:String},_toCancel:{type:String},_columnMap:{type:Object,value:function(){var t=this._commonColumns();for(var e in n)t[e]=n[e];return t}},_headerMap:{type:Object,value:i},_specialColumns:{type:Array,value:a},_specialSort:{type:Object,value:s}},_attribute:function(t,e,a){void 0===a&&(a="none");var n=this._tag(t,e)||t[e]||[a];return Array.isArray(n)?n:[n]},_cannotCancel:function(t,e){return!(e&&e.cancel_task&&"PENDING"===this._column("state",t))},_cancelTask:function(){var t="/_ah/api/swarming/v1/task/"+this._toCancel+"/cancel";swarming.postWithToast(t,"Canceling task "+this._toCancel,this._auth_headers),this.set("_toCancel","")},_promptClosed:function(t){t.detail.confirmed&&this._cancelTask()},_promptCancel:function(t){var e=t.model.task;return e&&e.task_id?(this.set("_toCancel",e.task_id),this.set("_dialogPrompt",'cancel task "'+e.name+'"'),void this.$.prompt.open()):void console.log("Missing task info",e)},_tag:function(t,e){if(t&&t.tagMap)return t.tagMap[e]},_taskLink:function(t){if(t)return"/user/task/"+t},_taskClass:function(t){var e=this._column("state",t);return"CANCELED"===e||"TIMED_OUT"===e||"EXPIRED"===e?"exception":"BOT_DIED"===e?"died":"COMPLETED (FAILURE)"===e?"failed":"RUNNING"===e||"PENDING"===e?"pending":""}})}()</script> </dom-module> <dom-module id="iron-collapse" assetpath="/res/imp/bower_components/iron-collapse/"> <template> <style>:host{display:block;transition-duration:var(--iron-collapse-transition-duration,300ms);overflow:visible}:host(.iron-collapse-closed){display:none}:host(:not(.iron-collapse-opened)){overflow:hidden}</style> <content></content> </template> </dom-module> <script>Polymer({is:"iron-collapse",behaviors:[Polymer.IronResizableBehavior],properties:{horizontal:{type:Boolean,value:!1,observer:"_horizontalChanged"},opened:{type:Boolean,value:!1,notify:!0,observer:"_openedChanged"},noAnimation:{type:Boolean}},get dimension(){return this.horizontal?"width":"height"},get _dimensionMax(){return this.horizontal?"maxWidth":"maxHeight"},get _dimensionMaxCss(){return this.horizontal?"max-width":"max-height"},hostAttributes:{role:"group","aria-hidden":"true","aria-expanded":"false"},listeners:{transitionend:"_transitionEnd"},attached:function(){this._transitionEnd()},toggle:function(){this.opened=!this.opened},show:function(){this.opened=!0},hide:function(){this.opened=!1},updateSize:function(t,i){var e=this.style[this._dimensionMax];if(e!==t&&("auto"!==t||e)){if(this._updateTransition(!1),i&&!this.noAnimation&&this._isDisplayed){var n=this._calcSize();"auto"===t&&(this.style[this._dimensionMax]="",t=this._calcSize()),this.style[this._dimensionMax]=n,this.scrollTop=this.scrollTop,this._updateTransition(!0)}"auto"===t?this.style[this._dimensionMax]="":this.style[this._dimensionMax]=t}},enableTransition:function(t){Polymer.Base._warn("`enableTransition()` is deprecated, use `noAnimation` instead."),this.noAnimation=!t},_updateTransition:function(t){this.style.transitionDuration=t&&!this.noAnimation?"":"0s"},_horizontalChanged:function(){this.style.transitionProperty=this._dimensionMaxCss;var t="maxWidth"===this._dimensionMax?"maxHeight":"maxWidth";this.style[t]="",this.updateSize(this.opened?"auto":"0px",!1)},_openedChanged:function(){this.setAttribute("aria-expanded",this.opened),this.setAttribute("aria-hidden",!this.opened),this.toggleClass("iron-collapse-closed",!1),this.toggleClass("iron-collapse-opened",!1),this.updateSize(this.opened?"auto":"0px",!0),this.opened&&this.focus(),this.noAnimation&&this._transitionEnd()},_transitionEnd:function(){this.opened&&(this.style[this._dimensionMax]=""),this.toggleClass("iron-collapse-closed",!this.opened),this.toggleClass("iron-collapse-opened",this.opened),this._updateTransition(!1),this.notifyResize()},get _isDisplayed(){var t=this.getBoundingClientRect();for(var i in t)if(0!==t[i])return!0;return!1},_calcSize:function(){return this.getBoundingClientRect()[this.dimension]+"px"}})</script> <script>Polymer.IronMenuBehaviorImpl={properties:{focusedItem:{observer:"_focusedItemChanged",readOnly:!0,type:Object},attrForItemTitle:{type:String}},hostAttributes:{role:"menu",tabindex:"0"},observers:["_updateMultiselectable(multi)"],listeners:{focus:"_onFocus",keydown:"_onKeydown","iron-items-changed":"_onIronItemsChanged"},keyBindings:{up:"_onUpKey",down:"_onDownKey",esc:"_onEscKey","shift+tab:keydown":"_onShiftTabDown"},attached:function(){this._resetTabindices()},select:function(e){this._defaultFocusAsync&&(this.cancelAsync(this._defaultFocusAsync),this._defaultFocusAsync=null);var t=this._valueToItem(e);t&&t.hasAttribute("disabled")||(this._setFocusedItem(t),Polymer.IronMultiSelectableBehaviorImpl.select.apply(this,arguments))},_resetTabindices:function(){var e=this.multi?this.selectedItems&&this.selectedItems[0]:this.selectedItem;this.items.forEach(function(t){t.setAttribute("tabindex",t===e?"0":"-1")},this)},_updateMultiselectable:function(e){e?this.setAttribute("aria-multiselectable","true"):this.removeAttribute("aria-multiselectable")},_focusWithKeyboardEvent:function(e){for(var t,s=0;t=this.items[s];s++){var i=this.attrForItemTitle||"textContent",o=t[i]||t.getAttribute(i);if(!t.hasAttribute("disabled")&&o&&o.trim().charAt(0).toLowerCase()===String.fromCharCode(e.keyCode).toLowerCase()){this._setFocusedItem(t);break}}},_focusPrevious:function(){for(var e=this.items.length,t=Number(this.indexOf(this.focusedItem)),s=1;s<e+1;s++){var i=this.items[(t-s+e)%e];if(!i.hasAttribute("disabled"))return void this._setFocusedItem(i)}},_focusNext:function(){for(var e=this.items.length,t=Number(this.indexOf(this.focusedItem)),s=1;s<e+1;s++){var i=this.items[(t+s)%e];if(!i.hasAttribute("disabled"))return void this._setFocusedItem(i)}},_applySelection:function(e,t){t?e.setAttribute("aria-selected","true"):e.removeAttribute("aria-selected"),Polymer.IronSelectableBehavior._applySelection.apply(this,arguments)},_focusedItemChanged:function(e,t){t&&t.setAttribute("tabindex","-1"),e&&(e.setAttribute("tabindex","0"),e.focus())},_onIronItemsChanged:function(e){e.detail.addedNodes.length&&this._resetTabindices()},_onShiftTabDown:function(e){var t=this.getAttribute("tabindex");Polymer.IronMenuBehaviorImpl._shiftTabPressed=!0,this._setFocusedItem(null),this.setAttribute("tabindex","-1"),this.async(function(){this.setAttribute("tabindex",t),Polymer.IronMenuBehaviorImpl._shiftTabPressed=!1},1)},_onFocus:function(e){if(!Polymer.IronMenuBehaviorImpl._shiftTabPressed){var t=Polymer.dom(e).rootTarget;(t===this||"undefined"==typeof t.tabIndex||this.isLightDescendant(t))&&(this._defaultFocusAsync=this.async(function(){var e=this.multi?this.selectedItems&&this.selectedItems[0]:this.selectedItem;this._setFocusedItem(null),e?this._setFocusedItem(e):this.items[0]&&this._focusNext()}))}},_onUpKey:function(e){this._focusPrevious(),e.detail.keyboardEvent.preventDefault()},_onDownKey:function(e){this._focusNext(),e.detail.keyboardEvent.preventDefault()},_onEscKey:function(e){this.focusedItem.blur()},_onKeydown:function(e){this.keyboardEventMatchesKeys(e,"up down esc")||this._focusWithKeyboardEvent(e),e.stopPropagation()},_activateHandler:function(e){Polymer.IronSelectableBehavior._activateHandler.call(this,e),e.stopPropagation()}},Polymer.IronMenuBehaviorImpl._shiftTabPressed=!1,Polymer.IronMenuBehavior=[Polymer.IronMultiSelectableBehavior,Polymer.IronA11yKeysBehavior,Polymer.IronMenuBehaviorImpl]</script> <script>Polymer.IronMenubarBehaviorImpl={hostAttributes:{role:"menubar"},keyBindings:{left:"_onLeftKey",right:"_onRightKey"},_onUpKey:function(e){this.focusedItem.click(),e.detail.keyboardEvent.preventDefault()},_onDownKey:function(e){this.focusedItem.click(),e.detail.keyboardEvent.preventDefault()},get _isRTL(){return"rtl"===window.getComputedStyle(this).direction},_onLeftKey:function(e){this._isRTL?this._focusNext():this._focusPrevious(),e.detail.keyboardEvent.preventDefault()},_onRightKey:function(e){this._isRTL?this._focusPrevious():this._focusNext(),e.detail.keyboardEvent.preventDefault()},_onKeydown:function(e){this.keyboardEventMatchesKeys(e,"up down left right esc")||this._focusWithKeyboardEvent(e)}},Polymer.IronMenubarBehavior=[Polymer.IronMenuBehavior,Polymer.IronMenubarBehaviorImpl]</script> <iron-iconset-svg name="paper-tabs" size="24"> <svg><defs> <g id="chevron-left"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"></path></g> <g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path></g> </defs></svg> </iron-iconset-svg> <dom-module id="paper-tab" assetpath="/res/imp/bower_components/paper-tabs/"> <template> <style>:host{@apply(--layout-inline);@apply(--layout-center);@apply(--layout-center-justified);@apply(--layout-flex-auto);position:relative;padding:0 12px;overflow:hidden;cursor:pointer;vertical-align:middle;@apply(--paper-font-common-base);@apply(--paper-tab)}:host(:focus){outline:0}:host([link]){padding:0}.tab-content{height:100%;transform:translateZ(0);-webkit-transform:translateZ(0);transition:opacity .1s cubic-bezier(.4,0,1,1);@apply(--layout-horizontal);@apply(--layout-center-center);@apply(--layout-flex-auto);@apply(--paper-tab-content)}:host(:not(.iron-selected))>.tab-content{opacity:.8;@apply(--paper-tab-content-unselected)}:host(:focus) .tab-content{opacity:1;font-weight:700}paper-ripple{color:var(--paper-tab-ink,--paper-yellow-a100)}.tab-content>::content>a{@apply(--layout-flex-auto);height:100%}</style> <div class="tab-content"> <content></content> </div> </template> <script>Polymer({is:"paper-tab",behaviors:[Polymer.IronControlState,Polymer.IronButtonState,Polymer.PaperRippleBehavior],properties:{link:{type:Boolean,value:!1,reflectToAttribute:!0}},hostAttributes:{role:"tab"},listeners:{down:"_updateNoink",tap:"_onTap"},attached:function(){this._updateNoink()},get _parentNoink(){var t=Polymer.dom(this).parentNode;return!!t&&!!t.noink},_updateNoink:function(){this.noink=!!this.noink||!!this._parentNoink},_onTap:function(t){if(this.link){var e=this.queryEffectiveChildren("a");if(!e)return;if(t.target===e)return;e.click()}}})</script> </dom-module> <dom-module id="paper-tabs" assetpath="/res/imp/bower_components/paper-tabs/"> <template> <style>:host{@apply(--layout);@apply(--layout-center);height:48px;font-size:14px;font-weight:500;overflow:hidden;-moz-user-select:none;-ms-user-select:none;-webkit-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent;-webkit-tap-highlight-color:transparent;@apply(--paper-tabs)}:host-context([dir=rtl]){@apply(--layout-horizontal-reverse)}#tabsContainer{position:relative;height:100%;white-space:nowrap;overflow:hidden;@apply(--layout-flex-auto)}#tabsContent{height:100%;-moz-flex-basis:auto;-ms-flex-basis:auto;flex-basis:auto}#tabsContent.scrollable{position:absolute;white-space:nowrap}#tabsContent.scrollable.fit-container,#tabsContent:not(.scrollable){@apply(--layout-horizontal)}#tabsContent.scrollable.fit-container{min-width:100%}#tabsContent.scrollable.fit-container>::content>*{-ms-flex:1 0 auto;-webkit-flex:1 0 auto;flex:1 0 auto}.hidden{display:none}.not-visible{opacity:0;cursor:default}paper-icon-button{width:48px;height:48px;padding:12px;margin:0 4px}#selectionBar{position:absolute;height:2px;bottom:0;left:0;right:0;background-color:var(--paper-tabs-selection-bar-color,--paper-yellow-a100);-webkit-transform:scale(0);transform:scale(0);-webkit-transform-origin:left center;transform-origin:left center;transition:-webkit-transform;transition:transform;@apply(--paper-tabs-selection-bar)}#selectionBar.align-bottom{top:0;bottom:auto}#selectionBar.expand{transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,1,1)}#selectionBar.contract{transition-duration:.18s;transition-timing-function:cubic-bezier(0,0,.2,1)}#tabsContent>::content>:not(#selectionBar){height:100%}</style> <paper-icon-button icon="paper-tabs:chevron-left" class$="[[_computeScrollButtonClass(_leftHidden, scrollable, hideScrollButtons)]]" on-up="_onScrollButtonUp" on-down="_onLeftScrollButtonDown" tabindex="-1"></paper-icon-button> <div id="tabsContainer" on-track="_scroll" on-down="_down"> <div id="tabsContent" class$="[[_computeTabsContentClass(scrollable, fitContainer)]]"> <div id="selectionBar" class$="[[_computeSelectionBarClass(noBar, alignBottom)]]" on-transitionend="_onBarTransitionEnd"></div> <content select="*"></content> </div> </div> <paper-icon-button icon="paper-tabs:chevron-right" class$="[[_computeScrollButtonClass(_rightHidden, scrollable, hideScrollButtons)]]" on-up="_onScrollButtonUp" on-down="_onRightScrollButtonDown" tabindex="-1"></paper-icon-button> </template> <script>Polymer({is:"paper-tabs",behaviors:[Polymer.IronResizableBehavior,Polymer.IronMenubarBehavior],properties:{noink:{type:Boolean,value:!1,observer:"_noinkChanged"},noBar:{type:Boolean,value:!1},noSlide:{type:Boolean,value:!1},scrollable:{type:Boolean,value:!1},fitContainer:{type:Boolean,value:!1},disableDrag:{type:Boolean,value:!1},hideScrollButtons:{type:Boolean,value:!1},alignBottom:{type:Boolean,value:!1},selectable:{type:String,value:"paper-tab"},autoselect:{type:Boolean,value:!1},autoselectDelay:{type:Number,value:0},_step:{type:Number,value:10},_holdDelay:{type:Number,value:1},_leftHidden:{type:Boolean,value:!1},_rightHidden:{type:Boolean,value:!1},_previousTab:{type:Object}},hostAttributes:{role:"tablist"},listeners:{"iron-resize":"_onTabSizingChanged","iron-items-changed":"_onTabSizingChanged","iron-select":"_onIronSelect","iron-deselect":"_onIronDeselect"},keyBindings:{"left:keyup right:keyup":"_onArrowKeyup"},created:function(){this._holdJob=null,this._pendingActivationItem=void 0,this._pendingActivationTimeout=void 0,this._bindDelayedActivationHandler=this._delayedActivationHandler.bind(this),this.addEventListener("blur",this._onBlurCapture.bind(this),!0)},ready:function(){this.setScrollDirection("y",this.$.tabsContainer)},detached:function(){this._cancelPendingActivation()},_noinkChanged:function(t){var e=Polymer.dom(this).querySelectorAll("paper-tab");e.forEach(t?this._setNoinkAttribute:this._removeNoinkAttribute)},_setNoinkAttribute:function(t){t.setAttribute("noink","")},_removeNoinkAttribute:function(t){t.removeAttribute("noink")},_computeScrollButtonClass:function(t,e,i){return!e||i?"hidden":t?"not-visible":""},_computeTabsContentClass:function(t,e){return t?"scrollable"+(e?" fit-container":""):" fit-container"},_computeSelectionBarClass:function(t,e){return t?"hidden":e?"align-bottom":""},_onTabSizingChanged:function(){this.debounce("_onTabSizingChanged",function(){this._scroll(),this._tabChanged(this.selectedItem)},10)},_onIronSelect:function(t){this._tabChanged(t.detail.item,this._previousTab),this._previousTab=t.detail.item,this.cancelDebouncer("tab-changed")},_onIronDeselect:function(t){this.debounce("tab-changed",function(){this._tabChanged(null,this._previousTab),this._previousTab=null},1)},_activateHandler:function(){this._cancelPendingActivation(),Polymer.IronMenuBehaviorImpl._activateHandler.apply(this,arguments)},_scheduleActivation:function(t,e){this._pendingActivationItem=t,this._pendingActivationTimeout=this.async(this._bindDelayedActivationHandler,e)},_delayedActivationHandler:function(){var t=this._pendingActivationItem;this._pendingActivationItem=void 0,this._pendingActivationTimeout=void 0,t.fire(this.activateEvent,null,{bubbles:!0,cancelable:!0})},_cancelPendingActivation:function(){void 0!==this._pendingActivationTimeout&&(this.cancelAsync(this._pendingActivationTimeout),this._pendingActivationItem=void 0,this._pendingActivationTimeout=void 0)},_onArrowKeyup:function(t){this.autoselect&&this._scheduleActivation(this.focusedItem,this.autoselectDelay)},_onBlurCapture:function(t){t.target===this._pendingActivationItem&&this._cancelPendingActivation()},get _tabContainerScrollSize(){return Math.max(0,this.$.tabsContainer.scrollWidth-this.$.tabsContainer.offsetWidth)},_scroll:function(t,e){if(this.scrollable){var i=e&&-e.ddx||0;this._affectScroll(i)}},_down:function(t){this.async(function(){this._defaultFocusAsync&&(this.cancelAsync(this._defaultFocusAsync),this._defaultFocusAsync=null)},1)},_affectScroll:function(t){this.$.tabsContainer.scrollLeft+=t;var e=this.$.tabsContainer.scrollLeft;this._leftHidden=0===e,this._rightHidden=e===this._tabContainerScrollSize},_onLeftScrollButtonDown:function(){this._scrollToLeft(),this._holdJob=setInterval(this._scrollToLeft.bind(this),this._holdDelay)},_onRightScrollButtonDown:function(){this._scrollToRight(),this._holdJob=setInterval(this._scrollToRight.bind(this),this._holdDelay)},_onScrollButtonUp:function(){clearInterval(this._holdJob),this._holdJob=null},_scrollToLeft:function(){this._affectScroll(-this._step)},_scrollToRight:function(){this._affectScroll(this._step)},_tabChanged:function(t,e){if(!t)return this.$.selectionBar.classList.remove("expand"),this.$.selectionBar.classList.remove("contract"),void this._positionBar(0,0);var i=this.$.tabsContent.getBoundingClientRect(),n=i.width,o=t.getBoundingClientRect(),s=o.left-i.left;if(this._pos={width:this._calcPercent(o.width,n),left:this._calcPercent(s,n)},this.noSlide||null==e)return this.$.selectionBar.classList.remove("expand"),this.$.selectionBar.classList.remove("contract"),void this._positionBar(this._pos.width,this._pos.left);var a=e.getBoundingClientRect(),l=this.items.indexOf(e),c=this.items.indexOf(t),r=5;this.$.selectionBar.classList.add("expand");var h=l<c,d=this._isRTL;d&&(h=!h),h?this._positionBar(this._calcPercent(o.left+o.width-a.left,n)-r,this._left):this._positionBar(this._calcPercent(a.left+a.width-o.left,n)-r,this._calcPercent(s,n)+r),this.scrollable&&this._scrollToSelectedIfNeeded(o.width,s)},_scrollToSelectedIfNeeded:function(t,e){var i=e-this.$.tabsContainer.scrollLeft;i<0?this.$.tabsContainer.scrollLeft+=i:(i+=t-this.$.tabsContainer.offsetWidth,i>0&&(this.$.tabsContainer.scrollLeft+=i))},_calcPercent:function(t,e){return 100*t/e},_positionBar:function(t,e){t=t||0,e=e||0,this._width=t,this._left=e,this.transform("translateX("+e+"%) scaleX("+t/100+")",this.$.selectionBar)},_onBarTransitionEnd:function(t){var e=this.$.selectionBar.classList;e.contains("expand")?(e.remove("expand"),e.add("contract"),this._positionBar(this._pos.width,this._pos.left)):e.contains("contract")&&e.remove("contract")}})</script> </dom-module> <script>!function(){SwarmingBehaviors.BotPageBehavior=[SwarmingBehaviors.CommonBehavior,{_timeDiffApprox:function(e){return e?sk.human.diffDate(e.getTime()):"eons"},_timeDiffExact:function(e,i){return e?(i||(i=new Date),sk.human.strDuration((i.getTime()-e.getTime())/1e3)):"eons"}}]}()</script> <dom-module id="bot-page-data" assetpath="/res/imp/botpage/"> <script>!function(){function t(t){if(!s){var e=t.toString();s=e.substring(e.indexOf("("))}return t.toLocaleString()+" "+s}var e,s,a=400,n=["first_seen_ts","last_seen_ts"],i=["started_ts","completed_ts","abandoned_ts","modified_ts"];Polymer({is:"bot-page-data",behaviors:[SwarmingBehaviors.BotPageBehavior],properties:{auth_headers:{type:Object},bot_id:{type:String},busy:{type:Boolean,computed:"_or(_busy1,_busy2,_busy3)",notify:!0},bot:{type:Object,computed:"_parseBot(_bot)",notify:!0},events:{type:Array,computed:"_parseEvents(_events)",notify:!0},tasks:{type:Array,computed:"_parseTasks(_tasks)",notify:!0},_busy1:{type:Boolean,value:!1},_busy2:{type:Boolean,value:!1},_busy3:{type:Boolean,value:!1},_bot:{type:Object},_events:{type:Object},_tasks:{type:Object}},observers:["request(auth_headers,bot_id)"],request:function(){this.bot_id&&this.auth_headers&&(e&&this.cancelAsync(e),e=this.async(function(){e=void 0;var t="/_ah/api/swarming/v1/bot/"+this.bot_id;this._getJsonAsync("_bot",t+"/get","_busy1",this.auth_headers),this._getJsonAsync("_events",t+"/events?fields=items(event_type%2Cmessage%2Cquarantined%2Ctask_id%2Cts%2Cversion)","_busy2",this.auth_headers),this._getJsonAsync("_tasks",t+"/tasks?fields=items(abandoned_ts%2Cbot_version%2Ccompleted_ts%2Cduration%2Cexit_code%2Cfailure%2Cinternal_failure%2Cmodified_ts%2Cname%2Cstarted_ts%2Cstate%2Ctask_id%2Ctry_number)","_busy3",this.auth_headers)},a))},_parseBot:function(e){if(!e)return{};e.state=e.state||"{}",e.state=JSON.parse(e.state);var s=e.state.disks||{},a=Object.keys(s);if(a.length){e.disks=[];for(var i=0;i<a.length;i++)e.disks.push({id:a[i],mb:s[a[i]].free_mb});e.disks.sort(function(t,e){return e.mb-t.mb})}else e.disks=[{id:"unknown",mb:0}];return e.dimensions=e.dimensions||[],e.dimensions.forEach(function(t){swarming.alias.DIMENSIONS_WITH_ALIASES.indexOf(t.key)!==-1&&t.value.forEach(function(e,s){t.value[s]=swarming.alias.apply(e,t.key)})}),n.forEach(function(s){e[s]&&(e[s]=new Date(e[s]),e["human_"+s]=t(e[s]))}),e},_parseEvents:function(e){if(!e||!e.items)return[];var e=e.items;return e.forEach(function(e){e.ts&&(e.ts=new Date(e.ts),e.human_ts=t(e.ts))}),e.sort(function(t,e){return e.ts-t.ts}),e},_parseTasks:function(e){if(!e||!e.items)return[];var e=e.items;return e.forEach(function(e){if(i.forEach(function(s){e[s]&&(e[s]=new Date(e[s]),e["human_"+s]=t(e[s]))}),e.duration)e.human_duration=sk.human.strDuration(e.duration)||"0s";else{var s=e.completed_ts||e.abandoned_ts||e.modified_ts||new Date;e.human_duration=this._timeDiffExact(e.started_ts,s)}e.state=e.state||"UNKNOWN","COMPLETED"===e.state&&(e.failure?e.state="FAILURE":e.state="SUCCESS")}.bind(this)),e.sort(function(t,e){return e.started_ts-t.started_ts}),e}})}()</script> </dom-module> <dom-module id="bot-page" assetpath="/res/imp/botpage/"> <template> <style include="iron-flex iron-flex-alignment iron-positioning swarming-app-style">.header{max-width:450px}.title{font-size:1.5em;font-weight:700;margin-bottom:5px}.id_input{--paper-input-container-input:{font-size:2em};}.refresh{max-width:50px;max-height:50px;width:initial;height:initial}table{border-collapse:collapse;margin-left:5px;margin-bottom:5px}td,th{border:1px solid #BBB;padding:5px}.failed_task,.quarantined{background-color:#fdd}.bot_died,.dead{background-color:#ccc}.message{white-space:pre-line;font-family:monospace}.bot_state{white-space:pre;font-family:monospace;margin-bottom:10px}.tabs{background-color:#1F78B4;color:#fff;max-width:600px;--paper-checkbox-label-color:#fff;margin-left:5px}.events_table,.tasks_table{border:3px solid #1F78B4}paper-checkbox{--paper-checkbox-label-color:#fff;--paper-checkbox-checked-color:#fff;--paper-checkbox-checkmark-color:#000;--paper-checkbox-unchecked-color:#fff;padding:3px}paper-tab.iron-selected{background-color:#A6CEE3;border:3px solid #1F78B4;color:#000;font-weight:700;text-decoration:underline}paper-dialog{border-radius:6px}</style> <url-param name="id" value="{{bot_id}}"> </url-param> <url-param name="show_all_events" value="{{_show_all}}"> </url-param> <url-param name="selected" value="{{_selected}}"> </url-param> <url-param name="show_state" value="{{_show_state}}"> </url-param> <swarming-app client_id="[[client_id]]" auth_headers="{{_auth_headers}}" permissions="{{_permissions}}" signed_in="{{_signed_in}}" busy="[[_busy]]" name="Swarming Bot Page"> <h2 hidden$="[[_signed_in]]">You must sign in to see anything useful.</h2> <div hidden$="[[_not(_signed_in)]]"> <bot-page-data id="data" auth_headers="[[_auth_headers]]" bot_id="[[bot_id]]" bot="{{_bot}}" busy="{{_busy}}" events="{{_events}}" tasks="{{_tasks}}"> </bot-page-data> <div class="header horizontal layout"> <paper-input class="id_input" label="Bot id" value="{{bot_id}}"></paper-input> <button on-click="_refresh"> <iron-icon class="refresh" icon="icons:refresh"></iron-icon> </button> </div> <div> <table> <tbody><tr class$="[[_isDead(_bot)]]"> <td>Last Seen</td> <td title="[[_bot.human_last_seen_ts]]"> [[_timeDiffExact(_bot.last_seen_ts)]] ago</td> <td> <template is="dom-if" if="[[_canShutdown(_bot,_permissions)]]"> <button class="raised" on-click="_promptShutdown"> Shut Down Gracefully </button> </template> <template is="dom-if" if="[[_canDelete(_bot,_permissions)]]"> <button class="raised" on-click="_promptDelete"> Delete </button> </template> </td> </tr> <template is="dom-if" if="[[_bot.quarantined]]"> <tr class="quarantined"> <td>Quarantined</td> <td colspan="2">[[_quarantineMessage(_bot)]]</td> </tr> </template> <tr> <td>Current Task</td> <td> <a target="_blank" href$="[[_taskLink(_bot.task_id)]]"> [[_task(_bot)]] </a> </td> <td> </td> </tr> <tr> <td rowspan$="[[_numRows(_bot.dimensions)]]">Dimensions</td> </tr> <template is="dom-repeat" items="[[_bot.dimensions]]" as="dim"> <tr> <td>[[dim.key]]</td> <td>[[_concat(dim.value)]]</td> </tr> </template> <tr> <td>External IP</td> <td><a href$="[[_bot.external_ip]]">[[_bot.external_ip]]</a></td> <td></td> </tr> <tr> <td>Swarming Revision</td> <td> <a target="_blank" href$="[[_luciLink(_bot.version)]]">[[_shorten(_bot.version,'8')]]</a> </td> <td></td> </tr> <tr> <td>First seen</td> <td title="[[_bot.human_first_seen_ts]]"> [[_timeDiffApprox(_bot.first_seen_ts)]] ago </td> <td></td> </tr> <tr> <td>Authenticated as</td> <td>[[_bot.authenticated_as]]</td> <td></td> </tr> </tbody></table> <span class="title">State</span> <template is="dom-if" if="[[_not(_show_state)]]"> <button on-click="_toggleState"> <iron-icon icon="icons:add-circle-outline"></iron-icon> </button> </template> <template is="dom-if" if="[[_show_state]]"> <button on-click="_toggleState"> <iron-icon icon="icons:remove-circle-outline"></iron-icon> </button> </template> <iron-collapse id="collapse" opened="[[_show_state]]"> <div class="bot_state">[[_prettyPrint(_bot.state)]]</div> </iron-collapse> </div> <div class="tabs"> <paper-tabs selected="{{_selected}}" no-bar=""> <paper-tab>Tasks</paper-tab> <paper-tab>Events</paper-tab> </paper-tabs> <template is="dom-if" if="[[_selected]]"> <paper-checkbox checked="{{_show_all}}"> Show all events </paper-checkbox> </template> </div> <template is="dom-if" if="[[_not(_selected)]]"> <table class="tasks_table"> <thead> <tr> <th>Task</th> <th>Started</th> <th>Duration</th> <th>Result</th> </tr> </thead> <tbody> <template is="dom-repeat" items="{{_tasks}}" as="task"> <tr class$="[[_taskClass(task)]]"> <td><a target="_blank" href$="[[_taskLink(task.task_id)]]">[[task.name]]</a></td> <td>[[task.human_started_ts]]</td> <td title="[[task.human_completed_ts]]">[[task.human_duration]]</td> <td>[[task.state]]</td> </tr> </template> </tbody> </table> </template> <template is="dom-if" if="[[_selected]]"> <table class="events_table"> <thead> <tr> <th>Message</th> <th>Type</th> <th>Timestamp</th> <th>Task ID</th> <th>Version</th> </tr> </thead> <tbody> <template is="dom-repeat" items="{{_eventList(_events,_show_all)}}" as="event"> <tr> <td class="message">[[event.message]]</td> <td>[[event.event_type]]</td> <td>[[event.human_ts]]</td> <td><a target="_blank" href$="[[_taskLink(event.task_id)]]">[[event.task_id]]</a></td> <td> <a target="_blank" href$="[[_luciLink(event.version)]]">[[_shorten(event.version,'8')]]</a> </td> </tr> </template> </tbody> </table> </template> </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> </template> <script> (function(){
|
|
|
|
|
| Polymer({
|
|
|