blob: 0ba68419cad78e4245cc7054e8344d4a75020335 [file] [log] [blame]
<!-- The <push-selection-sk> custom element declaration.
Presents a dialog of package choices and generates an event when the user has
made a selection. It is a custom element used by <push-server-sk>.
Attributes:
'choices'
The list of packages that are available.
'choice'
The selected package.
Events:
'change'
A 'change' event is generated when the user selects a package to push.
The change event has the following attributes:
event.detail.name - The full name of the package selected.
Methods:
toggle()
Toggles the visibility of the selection dialog.
-->
<style type="text/css" media="screen">
html /deep/ .pushSelection {
font-family: monospace;
padding: 0.5em;
cursor: pointer;
}
html /deep/ .pushSelection:hover {
background: #eee;
}
html /deep/ .built {
color: #D95F02;
display:inline;
}
html /deep/ .userid {
color: #7570B3;
display:inline;
}
</style>
<polymer-element name="push-selection-sk">
<template>
<paper-action-dialog id=chooser heading="Choose a release package to push">
<core-selector id=newChoice>
<template repeat="{{p in choices}}">
<div class=pushSelection name="{{p.Name}}">
<core-icon icon="{{choice == p.Name ? 'check' : ''}}" title="Currently installed"></core-icon>
<a href="https://github.com/google/skia-buildbot/compare/{{p.Hash}}...HEAD">{{p.Hash | short}}</a>
<pre class=built> {{p.Built | humanDiffDate }} </pre>
<pre class=userid title="{{p.UserID}}"> {{p.UserID | short}} </pre>
{{p.Note}}
<core-icon icon="{{p.Dirty ? 'warning' : ''}}" title="Uncommited changes when the package was built."></core-icon>
</div>
</template>
</core-selector>
<paper-button dismissive>Cancel</paper-button>
</paper-action-dialog>
</template>
<script>
(function() {
var deltas = [
{ units: "w", delta: 7*24*60*60 },
{ units: "d", delta: 24*60*60 },
{ units: "h", delta: 60*60 },
{ units: "m", delta: 60 },
{ units: "s", delta: 1 },
];
Polymer({
publish: {
choices: {
value: [],
reflect: false
},
choice: {
value: '',
reflect: false
}
},
ready: function() {
var that = this;
this.$.newChoice.addEventListener('core-activate', function(e) {
that.toggle();
var detail = {name: that.$.newChoice.selected};
that.dispatchEvent(new CustomEvent('change', {detail: detail}));
});
},
toggle: function() {
this.$.chooser.toggle();
},
// short is a utility function used in templates to truncate strings.
short: function(s) {
return s.slice(0, 8);
},
humanDiffDate: function(s) {
var diff = (Date.now() - Date.parse(s))/1000;
for (var i=0; i<deltas.length; i++) {
if (deltas[i].delta < diff) {
var s = Math.round(diff/deltas[i].delta)+deltas[i].units;
while (s.length < 4) {
s = ' ' + s;
}
return s;
}
}
return diff + "s";
}
});
})();
</script>
</polymer-element>
<!-- The <push-server-sk> custom element declaration.
Displays the server configurations, along with the ability to modify application selections.
Attributes:
servers: Map of server names to the apps and their versions. Such as:
[
{
Name: 'skia-monitoring',
Installed: [
'pull/pull:jcgregorio@jcgregorio.cnc.corp.google.com:2014-12-08T02:09:58Z:79f6b17ea316c5d877f4f1e3fa9c7a4ea950916c.deb',
'logserver/',
]
},
{
Name: 'skia-testing-b',
Installed: []
}
]
Note that an entry in Installed can either be a full package path, or
just a shortened '{appname}/' version which indicates which app is
expected but also signals that no specific release package has been
chosen or deployed yet.
packages: Map of app names to the list of available versions, sorted from newest to oldest. Such as:
{
'pull': [
{
Name: 'pull:jcgregorio@jcgregorio.cnc.corp.google.com:2014-12-08T02:09:58Z:79f6b17ea316c5d877f4f1e3fa9c7a4ea950916c.deb',
Hash: '79f6b17ea316c5d877f4f1e3fa9c7a4ea950916c',
UserID: 'jcgregorio@jcgregorio.cnc.corp.google.com',
Built: '2014-12-08T02:09:58Z',
Dirty: true,
Note: 'some reason for a push'
},
{
Name: 'pull:jcgregorio@jcgregorio.cnc.corp.google.com:2014-12-08T01:39:47Z:323894732847ace1289a9a90192123213.deb',
Hash: '323894732847ace1289a9a90192123213',
UserID: 'jcgregorio@jcgregorio.cnc.corp.google.com',
Built: '2014-12-08T01:39:47Z',
Dirty: false,
Note: 'no reason'
}
],
'logserver': [
]
}
Events:
'change'
A 'change' event is generated when the user selects a package to push.
The change event has the following attributes:
event.detail.server - The name of the server.
event.detail.name - The full name of the package to push.
Methods:
setConfig(servers, packages)
Clicking on an app brings up a selection dialog with all available options,
the current one already selected. A selection will update and push.
-->
<polymer-element name="push-server-sk">
<template>
<style type="text/css" media="screen">
table {
margin-left: 3em;
}
h2 {
color: #33A02C;
margin-left: 1em;
display: inline;
padding-right: 1em;
}
.appName {
padding-right: 2em;
}
td core-icon {
padding-right: 1em;
}
paper-button {
color: #1f78b4;
}
paper-button:hover {
background: #eee;
}
</style>
<template repeat="{{server in servers}}">
<section>
<h2>{{server.Name}}</h2> [<a target=_blank href="http://{{ip[server.Name]}}:10114">monit</a>] [<a target=_blank href="http://{{ip[server.Name]}}:10115">logs</a>]
<table>
<template repeat="{{id in server.Installed}}">
<tr>
<td>
<paper-button class=application data-server="{{server.Name}}" data-name="{{id}}" data-app="{{id | prefixOf}}"><core-icon icon="create" title="Edit which package is installed."></core-icon></paper-button>
</td>
<td><span class=appName>{{id | prefixOf}}</span></td>
<td><span class=appName><a href="https://github.com/google/skia-buildbot/compare/{{id | fullHash}}...HEAD">{{id | short}}</a></span></td>
<td><core-icon icon="{{packageLookup[id].Latest ? '' : 'alarm'}}" title="Out of date."></core-icon></td>
<td><core-icon icon="{{packageLookup[id].Dirty ? 'warning' : ''}}" title="Uncommited changes when the package was built."></core-icon></td>
</tr>
</template>
</table>
</section>
</template>
<push-selection-sk id=extChooser></push-selection-sk>
</template>
<script>
Polymer({
publish: {
servers: {
value: {},
reflect: false
},
packages: {
value: {},
reflect: false
},
ip: {
value: {},
reflect: false
},
packageLookup: {
value: {},
reflect: false
},
server: {
value: '',
reflect: false
}
},
ready: function() {
var that = this;
this.addEventListener('click', function(e) {
this.server = '';
var id = '';
var app = '';
// Bump up the parent path until we find our containing .application element.
for (var i=0; i<e.path.length; i++) {
if (e.path[i]["classList"] && e.path[i].classList.contains('application')) {
this.server = e.path[i].dataset.server;
id = e.path[i].dataset.name;
app = e.path[i].dataset.app;
break;
}
}
if (app != "") {
this.$.extChooser.choices = this.packages[app];
this.$.extChooser.choice = id;
this.$.extChooser.toggle();
}
});
// When the push-selection-sk dialog notifies us of a selection
// we fill in some more details and pass that along as another
// CustomEvent.
this.$.extChooser.addEventListener('change', function(e) {
var detail = {
name: e.detail.name,
server: that.server
};
that.dispatchEvent(new CustomEvent('change', {detail: detail}));
});
},
setConfig: function(servers, packages, ip) {
this.servers = servers;
this.packages = packages;
this.ip = ip;
for (appName in this.packages) {
var that = this;
var latest = true;
this.packages[appName].forEach(function(details) {
that.packageLookup[details.Name] = details;
that.packageLookup[details.Name].Latest = latest;
latest = false;
});
}
},
// prefixOf is a helper used in templates that returns all the text
// that appears before the first '/'.
prefixOf: function(s) {
return s.split('/')[0];
},
// fullHash is a utility function used in templates to extract the full git hash
// from a package name.
fullHash: function(s) {
return s.slice(s.length-44, s.length-4)
},
// short is a utility function used in templates to truncate strings.
short: function(s) {
return this.fullHash(s).slice(0, 6);
},
});
</script>
</polymer-element>