blob: 7c3570b291030d6f1ff7fd791974301d0dd335d2 [file] [log] [blame]
<!-- The <trybot-controls-sk> custom element declaration.
Shows an overview of the patchsets that have been run for a CL.
It color codes bots according to their state (running, failed etc.)
and exposes links to view the digests associated individual
patchsets.
Attributes:
None
Events:
state-change - Fires when the state of control variables changes. This
should result in a reload of the page. The 'detail' field of the
event object contains the new state object.
state-update - Fires when the state is updated. This reflects a state that
is already represented on the current page and should NOT result in
a page reload but an update of the URL.
Methods:
setState(state) - Sets the state of the variables controlled by the
UI elements. This should be called at least once before 'setIssue',
usually the state is extracted from the URL.
setIssue(issue) - Sets the current issue as returned by the /json/search endpoint.
If issue is null the element does not show and is usually the result of search
that was not querying for an issue.
Mailboxes:
None
-->
<link rel="import" href="bower_components/polymer/polymer.html">
<link rel="import" href="bower_components/iron-flex-layout/iron-flex-layout-classes.html">
<link rel="import" href="bower_components/paper-toggle-button/paper-toggle-button.html">
<link rel="import" href="bower_components/paper-dropdown-menu/paper-dropdown-menu.html">
<link rel="import" href="bower_components/paper-listbox/paper-listbox.html">
<link rel="import" href="bower_components/paper-item/paper-item.html">
<link rel="import" href="bower_components/iron-icons/iron-icons.html">
<link rel="import" href="bower_components/paper-button/paper-button.html">
<link rel="import" href="shared-styles.html">
<dom-module id="trybot-controls-sk">
<template>
<style include="iron-flex iron-flex-alignment"></style>
<style include="shared-styles">
.scheduledTryjob {
background-color: #E0E0E0;
}
.runningTryjob {
background-color: #FFEB3B;
}
.completeTryjob {
background-color: #8BC34A;
}
.ingestedTryjob {
background-color: #8BC34A;
color: white;
}
.ingestedTryjob:after {
content: "\2714";
}
.failedTryjob {
background-color: #F44336;
color: white;
}
.tryjobStatus {
padding-right: .5em;
padding-left: .5em;
margin-left: 0.5em;
margin-right: 0.5em;
margin-top: 0.3em;
margin-bottom: 0.3em;
padding: 0.2em 1em 0.2em 1em;
float: left;
}
.tryjobContainer {
max-width: 80%;
margin-top: 1em;
margin-bottom: 1em;
}
.issueHeader, .issueHeader a {
font-weight: bold;
font-size: medium;
}
.issueHeader {
margin-right: 2em;
}
.issueHeader.triagelogLink a {
color:#1f78b4;
}
.currentPatchset::after {
content: "*";
}
.triagelogLink {
font-size: smaller;
}
.masterToggle {
margin-left: 5em;
}
.controlsContainer {
margin:1em 0 1em 0;
}
.legend {
font-weight: bolder;
}
.legendContainer {
border: 1px solid #CCCC;
float: right;
}
</style>
<template is="dom-if" if={{_issue}}>
<div class="layout horizontal">
<div class="issueHeader">Issue:</div>
<div class="issueHeader">
<a href$="{{_issue.url}}" target="_blank" rel="noopener">
{{_issue.subject}}
</a>
</div>
<div class="issueHeader">{{_issue.owner}}</div>
<div class="issueHeader triagelogLink">
<a href$="/triagelog?issue=[[_issue.id]]"><iron-icon icon="icons:find-in-page"></iron-icon>Triagelog</a>
</div>
</div>
<div class="controlsContainer layout horizontal">
<paper-dropdown-menu id="patchsetDropDown" label="Patchset" horizontal-align="left">
<paper-listbox id="itemMenu" class="dropdown-content" selected="{{_state.patchsets}}" attr-for-selected="value">
<template is="dom-repeat" items="{{_patchsets}}">
<paper-item value="[[item.val]]">[[item.label]]</paper-item>
</template>
</paper-listbox>
</paper-dropdown-menu>
<paper-toggle-button class="masterToggle" checked="{{_state.master}}">Include Master</paper-toggle-button>
</div>
<div class="tryjobContainer horizontal layout wrap" hidden$="[[!_tryjobs]]">
<template is="dom-repeat" items={{_tryjobs}} as="tryjob">
<div class$="{{tryjob.status}}Tryjob tryjobStatus" title$="Status: [[tryjob.status]]">{{tryjob.builder}}</div>
</template>
</div>
<div class="legendContainer" hidden$="[[!_tryjobs]]">
<div class="tryjobContainer horizontal layout">
<div class="tryjobStatus legend">Legend:</div>
<div class="scheduledTryjob tryjobStatus">scheduled</div>
<div class="runningTryjob tryjobStatus">running</div>
<div class="completeTryjob tryjobStatus">complete</div>
<div class="ingestedTryjob tryjobStatus">ingested</div>
</div>
</div>
<div class="horizontal layout" hidden$="[[_tryjobs]]">
No Tryjobs for Patchset [[_state.patchsets]].
</div>
</template>
</template>
<script>
Polymer({
is: "trybot-controls-sk",
behaviors: [gold.PageStateBehavior],
properties: {
_issue: {
type: Object,
value: null
},
_state: {
type: Object,
value: null
},
},
observers: [
'_fireStateChange(_state.*)'
],
ready: function() {
this._setDefaultState(gold.defaultSearchState, true);
},
setState: function(state) {
this._noFire = true;
this.set('_state', sk.object.shallowCopy(state));
},
setIssue: function(issue) {
this._noFire = true;
this._setPatchsetInfo(issue);
this.set("_issue", issue);
},
_setPatchsetInfo: function(issue) {
if (!issue || !issue.patchsets) {
return;
}
var currSelected = (issue.queryPatchsets && issue.queryPatchsets.length && issue.queryPatchsets[0]) || -1;
var patchsets = [];
var group = [];
var tryjobs = [];
for(var i=0; i < issue.patchsets.length; i++) {
group.push(issue.patchsets[i]);
if (issue.patchsets[i].tryjobs) {
patchsets.push(this._getPatchsetInfo(group));
group = [];
if (issue.patchsets[i].id === currSelected) {
tryjobs.push.apply(tryjobs, issue.patchsets[i].tryjobs);
}
}
}
if (group.length > 0) {
patchsets.push(this._getPatchsetInfo(group));
}
tryjobs.sort(function(a,b) {
return (a.builder < b.builder) ? -1 : ((a.builder === b.builder)? 0 : 1);
});
this.set('_patchsets', patchsets);
this.set('_state.patchsets', currSelected);
this.set('_tryjobs', tryjobs);
this.fire('state-update', sk.object.shallowCopy(this._state));
},
_fireStateChange: function(observer) {
// Do not fire when element is first initialized (null) or when it was
// explicitly requested to not fire the event (_noFire).
if ((observer.value === null) || (this._noFire)) {
this._noFire = false;
return;
}
this.fire('state-change', sk.object.shallowCopy(this._state));
},
_getPatchsetInfo: function(group) {
return {
label: 'Patchset ' + group[0].id + ((group.length>1) ? ' - ' +group[group.length-1].id:''),
val: group[group.length-1].id
};
},
_patchsetHref: function(patchset) {
return this._baseUrl + patchset.id;
},
_isCurr: function(patchset) {
return (this._issue.queryPatchsets.indexOf(patchset.id) !== -1) ? 'currentPatchset' : '';
},
_plusOne: function(index) {
return index+1;
}
});
</script>
</dom-module>