blob: 95dfefa7d05b31d5c26aff2a8bb0ad813aa5fe36 [file] [log] [blame]
<!-- The <commits-panel-sk> custom element declaration.
An element to display information on one or more commits.
Attributes:
progress - Boolean, if true then display the percent complete
for the first hash.
selection - Boolean, if true then selections are displayed, i.e. the user
click on a commit and select it.
selector - The iron-selector element that wraps the commits.
mailbox - The sk.Mailbox name to listen for the data to populate
the element. This is in addition to the 'commits' mailbox
described below.
repo - The URL of the underlying git repo. This assumes a
googlesource repo when deriving URLs from this value.
commitinfo - A list of commits that are passed to setCommitInfo (see below).
This is the direct way to set commits.
Methods:
setCommitInfo - Sets the commit info, an array of *types.Commit. See the
description for the commits Mailbox for more details.
selectHash - Forces the selection of the given hash.
Events:
commit-selected - Event produced when a commit is selected. The event
detail contains:
{
description: "fixed lengh string descripting the commit",
hash: "1213982193 (the commit hash)",
}
Mailboxes:
commits - The sk.Mailbox name to listen for the data to populate
the element. The mailbox data needs to be a serialized slice
of []*types.Commit. If not set then the data must be supplied
by the setCommitInfo method.
[
{
commit_time: 1439649751,
author: "reed (reed@chromium.org)",
hash: "bb886749feb444edfd8fbf053a9ea815e3605f8a",
},
{
author: "reed (reed@chromium.org)",
commit_time: 1439648914,
hash: "e02716908fe82c7c4ae9b415793277620a22bcd6",
},
]
Note that the hashes need to be in order, but not necessarily
contiguous. Note that they also need to be supplied in time ascending
order, that is, the commit at index 0 needs to be the oldest commit, and
the last commit in the array needs to be the newest commit.
-->
<link rel="stylesheet" href="/res/common/css/md.css">
<link rel="import" href="/res/imp/bower_components/iron-selector/iron-selector.html">
<link rel="import" href="commit.html">
<dom-module id="commits-panel-sk">
<template>
<style type="text/css" media="screen">
div {
margin-bottom: 0.5em;
}
commit-sk {
display: block;
padding-right: 2em;
}
pre {
font-size: 14px;
margin: 0.2em 0;
padding: 0.3em;
}
.iron-selected {
background: #eee;
}
:host {
display: block;
}
</style>
<template is="dom-if" if="{{progress}}">
<div>
<a target="_blank" href$="{{_statusHref(_firstHash)}}">Buildbot Percent Complete: <span>{{_commitPercent(_percent)}}</span>%</a>
</div>
</template>
<iron-selector id=selector>
<template is="dom-repeat" items="{{_commitinfo}}" as="c">
<commit-sk data-hash$="{{c.hash}}" hash="{{c.hash}}" commit="{{c}}" repo="{{repo}}"></commit-sk>
</template>
</iron-selector>
</template>
<script>
Polymer({
is: 'commits-panel-sk',
properties: {
progress: {
type: Boolean,
value: false,
reflectToAttribute: true,
},
selection: {
type: Boolean,
value: false,
reflectToAttribute: true,
observer: "_selectionChanged",
},
mailbox: {
value: "",
reflectToAttribute: true
},
repo: {
type: String,
value: "https://skia.googlesource.com/skia",
notify: true
},
commitinfo: {
type: Array,
value: null,
observer: "setCommitInfo"
}
},
listeners: {
"selector.iron-select": "_selectorTap",
},
ready: function () {
this._percent = -1.0;
this._firstHash = '';
this.selector = this.$.selector;
sk.Mailbox.subscribe('commits', this.setCommitInfo.bind(this));
if (this.mailbox != "") {
sk.Mailbox.subscribe(this.mailbox, this.setCommitInfo.bind(this));
}
},
setCommitInfo: function(commitinfo) {
if (commitinfo) {
this._commitinfo = commitinfo;
this._processCommitInfo();
}
},
selectHash: function(hash) {
// Clear the selection.
this.selector.selected = null;
// If the commits have been set then use them to find the hash. This
// avoids timing issues if the commit-sk elements haven't rendered yet.
if (this._commitinfo && (this._commitinfo.length > 0)) {
var idx = this._commitinfo.findIndex(function(c) { return c.hash === hash; });
if (idx >= 0) {
this.selector.select(idx);
}
return;
}
$$('commit-sk', this).forEach(function(ele) {
if (ele.dataset.hash === hash) {
this.selector.select(this.selector.indexOf(ele));
}
}.bind(this));
},
_selectorTap: function(e) {
var detail = {
description: e.detail.item.asString(),
commit: e.detail.item.commit,
};
this.dispatchEvent(new CustomEvent('commit-selected', { detail: detail, bubbles: true }));
},
_selectionChanged: function() {
this.$.selector.selectedClass = this.selection ? "iron-selected" : "no-matching-class";
},
_processCommitInfo: function () {
if (this._commitinfo && this._commitinfo.length) {
var lastHash = this._commitinfo[0].hash;
this._firstHash = this._commitinfo[this._commitinfo.length - 1].hash;
if (!this._commitinfo[0].message) {
var url = this.repo + '/+log/' + this._firstHash + '~' + 1 + '..' + lastHash + '?format=json';
// The git hashes are in time order, but not contiguous, so request
// the log range and them populate messages by matching git hashes.
sk.get(url).then(this._removeSecurityHeader).then(JSON.parse).then(function (json) {
var len = this._commitinfo.length;
for (var i = 0; i < json.log.length; i++) {
var commit = json.log[i].commit;
// The git hash of this log meesage.
for (var j = 0; j < len; j++) {
if (this._commitinfo[j].hash == commit) {
this.set('_commitinfo.'+j+'.message', json.log[i].message.slice(0, 60));
break;
}
}
}
// This can go away once we start filling in the message on the server side.
$$('commit-sk', this).forEach(function(ele) {
ele.refresh();
});
this.fire('commits-loaded', {});
}.bind(this)).catch(sk.errorMessage);
} else {
// Fire the message even when the commit messages were cached.
this.fire('commits-loaded', {});
}
if (this.progress) {
var url = 'https://status.skia.org/json/skia/buildProgress?commit=' + this._firstHash;
// The status server returns JSON of the form:
//
// {
// "commit": "e9e3ee33f30c14c31afd5fc3fe4dda7f15783c75",
// "finishedTasks": 111,
// "finishedProportion": 0.7762237762237763,
// "totalTasks": 143
// }
sk.get(url).then(JSON.parse).then(function (json) {
this._percent = json.finishedProportion;
}.bind(this)).catch(sk.errorMessage);
}
}
},
// _removeSecurityHeader strips the first 4 chars from the input. Needed
// since googlesource.com prefixes all JSON responses with )]}' as an
// XSS defense.
_removeSecurityHeader: function (s) {
return s.slice(4, s.length);
},
_commitPercent: function (p) {
if (p == -1.0) {
return "[calculating]";
}
return Math.round(p * 100);
},
_statusHref: function (hash) {
return 'https://status.skia.org/?commit=' + hash + '&commitLabel=author&filter=all';
},
});
</script>
</dom-module>