* Move everything up one directory.
22
src/root/all.tt
Normal file
@ -0,0 +1,22 @@
|
||||
[% WRAPPER layout.tt title="All Builds" %]
|
||||
[% PROCESS common.tt %]
|
||||
|
||||
<h1>All Builds
|
||||
[% IF jobName %]for Job [% curProject.name %]:[% jobName %][% ELSE %]
|
||||
[% IF curProject %] for Project <tt>[% curProject.name %]</tt>[% END %][% END %]</h1>
|
||||
|
||||
<p>Showing builds [% (page - 1) * resultsPerPage + 1 %] - [% (page - 1) * resultsPerPage + builds.size %]
|
||||
out of [% totalBuilds %] in order of descending timestamp.</p>
|
||||
|
||||
[% PROCESS renderBuildList %]
|
||||
|
||||
[<a href="[% "$baseUri/1" %]">First</a>]
|
||||
[% IF page > 1 %]
|
||||
[<a href="[% "$baseUri/"; (page - 1) %]">Prev</a>]
|
||||
[% END %]
|
||||
[% IF page * resultsPerPage < totalBuilds %]
|
||||
[<a href="[% "$baseUri/"; (page + 1) %]">Next</a>]
|
||||
[% END %]
|
||||
[<a href="[% "$baseUri/"; (totalBuilds - 1) div resultsPerPage + 1 %]">Last</a>]
|
||||
|
||||
[% END %]
|
311
src/root/build.tt
Normal file
@ -0,0 +1,311 @@
|
||||
[% WRAPPER layout.tt title="Build Information" %]
|
||||
[% PROCESS common.tt %]
|
||||
[% PROCESS "product-list.tt" %]
|
||||
[% USE HTML %]
|
||||
|
||||
<h1>
|
||||
Job <tt>[% build.project.name %]:[% build.attrname %]</tt> build [% id %]
|
||||
[% IF !build.finished %]
|
||||
[% IF build.schedulingInfo.busy %]
|
||||
(currently building)
|
||||
[% ELSE %]
|
||||
(scheduled)
|
||||
[% END %]
|
||||
[% END %]
|
||||
</h1>
|
||||
|
||||
|
||||
[% IF flashMsg %]
|
||||
<p class="error">[% flashMsg %]</p>
|
||||
[% END %]
|
||||
|
||||
|
||||
<h2>Information</h2>
|
||||
|
||||
<table class="layoutTable">
|
||||
<tr>
|
||||
<th>Build ID:</th>
|
||||
<td>[% build.id %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Status:</th>
|
||||
<td>
|
||||
[% IF build.finished %]
|
||||
[% IF build.resultInfo.buildstatus == 0 %]
|
||||
<img src="/static/images/success.gif" alt="Succeeded" />
|
||||
<strong>Success</strong>
|
||||
[% ELSIF build.resultInfo.buildstatus == 1 %]
|
||||
<img src="/static/images/failure.gif" alt="Failed" />
|
||||
<span class="error">Build returned a non-zero exit code</span>
|
||||
[% ELSIF build.resultInfo.buildstatus == 2 %]
|
||||
<img src="/static/images/failure.gif" alt="Failed" />
|
||||
<span class="error">A dependency of the build failed</span>
|
||||
[% ELSE %]
|
||||
<img src="/static/images/failure.gif" alt="Failed" />
|
||||
<span class="error">Build failed</span>
|
||||
(see <a href="#nix-error">below</a>)
|
||||
<form action="[% c.uri_for('/build' build.id 'restart') %]" method="post" class="inline">
|
||||
<button id="delete-project" type="submit">Restart</button>
|
||||
</form>
|
||||
[% END %]
|
||||
[% ELSIF build.schedulingInfo.busy %]
|
||||
<strong>Build in progress</strong>
|
||||
since [% PROCESS renderDateTime timestamp = build.schedulingInfo.starttime %]
|
||||
[% ELSE %]
|
||||
<strong>Scheduled to be built</strong>
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Project:</th>
|
||||
<td><a href="[% c.uri_for('/project' build.project.name) %]"><tt>[% build.project.name %]</tt></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Jobset:</th>
|
||||
<td><tt>[% build.jobset.name %]</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Job name:</th>
|
||||
<td><a href="[% c.uri_for('/project' build.project.name 'job' build.attrname) %]"><tt>[% build.attrname %]</tt></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nix name:</th>
|
||||
<td><tt>[% build.nixname %]</tt></td>
|
||||
</tr>
|
||||
[% IF build.resultInfo.releasename %]
|
||||
<tr>
|
||||
<th>Release name:</th>
|
||||
<td><tt>[% HTML.escape(build.resultInfo.releasename) %]</tt></td>
|
||||
</tr>
|
||||
[% END %]
|
||||
<tr>
|
||||
<th>Short description:</th>
|
||||
<td>[% IF build.description %][% HTML.escape(build.description) %][% ELSE %]<em>(not given)</em>[% END %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Long description:</th>
|
||||
<td>[% IF build.longdescription %][% HTML.escape(build.longdescription) %][% ELSE %]<em>(not given)</em>[% END %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>License:</th>
|
||||
<td>[% IF build.license %][% HTML.escape(build.license) %][% ELSE %]<em>(not given)</em>[% END %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>System:</th>
|
||||
<td><tt>[% build.system %]</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Derivation store path:</th>
|
||||
<td>
|
||||
<tt>[% build.drvpath %]</tt>
|
||||
[% IF drvAvailable %]
|
||||
(<a href="[% c.uri_for('/build' build.id 'buildtime-deps') %]">build-time dependencies</a>)
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Output store path:</th>
|
||||
<td>
|
||||
<tt>[% build.outpath %]</tt>
|
||||
[% IF available %]
|
||||
(<a href="[% c.uri_for('/build' build.id 'runtime-deps') %]">runtime dependencies</a>)
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Time added:</th>
|
||||
<td>[% PROCESS renderDateTime timestamp = build.timestamp %]</td>
|
||||
</tr>
|
||||
[% IF build.finished %]
|
||||
<tr>
|
||||
<th>Build started:</th>
|
||||
<td>[% IF build.resultInfo.starttime %][% PROCESS renderDateTime timestamp = build.resultInfo.starttime %][% ELSE %]<em>(cached build)</em>[% END %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Build finished:</th>
|
||||
<td>[% IF build.resultInfo.stoptime %][% PROCESS renderDateTime timestamp = build.resultInfo.stoptime %][% ELSE %]<em>(cached build)</em>[% END %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Duration (seconds):</th>
|
||||
<td>
|
||||
[% IF build.resultInfo.iscachedbuild %]
|
||||
<em>(cached build)</em>
|
||||
[% ELSE %]
|
||||
[% build.resultInfo.stoptime - build.resultInfo.starttime %]
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
[% IF build.resultInfo.logfile %]
|
||||
<tr>
|
||||
<th>Logfile:</th>
|
||||
<td>
|
||||
<a href="[% c.uri_for('/build' build.id 'log') %]"><strong>Available</strong></a>
|
||||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
[% ELSE %]
|
||||
<tr>
|
||||
<th>Priority:</th>
|
||||
<td>[% build.schedulingInfo.priority %]</td>
|
||||
</tr>
|
||||
[% IF build.schedulingInfo.busy %]
|
||||
<tr>
|
||||
<th>Logfile:</th>
|
||||
<td><tt>[% build.schedulingInfo.logfile %]</tt></td>
|
||||
</tr>
|
||||
[% END %]
|
||||
[% END %]
|
||||
</table>
|
||||
|
||||
|
||||
<h2>Build inputs</h2>
|
||||
|
||||
<table class="tablesorter">
|
||||
<thead>
|
||||
<tr><th>Name</th><th>Type</th><th>Value</th><th>Revision</th><th>Store path</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% FOREACH input IN build.inputs -%]
|
||||
<tr>
|
||||
<td><tt>[% input.name %]</tt></td>
|
||||
<td><tt>[% type = input.type; inputTypes.$type %]</tt></td>
|
||||
<td>
|
||||
[% IF input.type == "build" %]
|
||||
<a href="[% c.uri_for('/build' input.dependency.id) %]">Job <tt>[% input.dependency.project.name %]:[% input.dependency.attrname %]</tt> build [% input.dependency.id %]</a>
|
||||
[% ELSIF input.type == "string" || input.type == "boolean" %]
|
||||
<tt>"[% input.value %]"</tt>
|
||||
[% ELSE %]
|
||||
<tt>[% input.uri %]</tt>
|
||||
[% END %]
|
||||
</td>
|
||||
<td>[% IF input.revision %][% input.revision %][% END %]</td>
|
||||
<td><tt>[% input.path %]</tt></td>
|
||||
</tr>
|
||||
[% END -%]
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
[% IF build.buildsteps %]
|
||||
|
||||
<h2 id="buildsteps">Build steps</h2>
|
||||
|
||||
<table class="tablesorter">
|
||||
<thead>
|
||||
<tr><th>Nr</th><th>What</th><th>Duration</th><th>Status</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% FOREACH step IN build.buildsteps -%]
|
||||
[% log = c.uri_for('/build' build.id 'nixlog' step.stepnr) %]
|
||||
<tr class="[% IF step.logfile %]clickable[% END %]"
|
||||
[% IF step.logfile %] onclick="window.location = '[% log %]'" [% END %]>
|
||||
<td>[% step.stepnr %]</td>
|
||||
<td>
|
||||
[% IF step.type == 0 %]
|
||||
Build of <tt>[% step.outpath %]</tt>
|
||||
[% ELSE %]
|
||||
Substitution of <tt>[% step.outpath %]</tt>
|
||||
[% END %]
|
||||
</td>
|
||||
<td>
|
||||
[% IF step.busy == 0 %]
|
||||
[% step.stoptime - step.starttime %]s
|
||||
[% ELSE %]
|
||||
[% IF build.finished %]
|
||||
[% build.resultInfo.stoptime - step.starttime %]s
|
||||
[% ELSE %]
|
||||
[% curTime - step.starttime %]s
|
||||
[% END %]
|
||||
[% END %]
|
||||
</td>
|
||||
<td>
|
||||
[% IF step.busy == 1 %]
|
||||
[% IF build.finished %]
|
||||
<span class="error">Aborted</span>
|
||||
[% ELSE %]
|
||||
<strong>Building</strong>
|
||||
[% END %]
|
||||
[% ELSIF step.status == 0 %]
|
||||
Succeeded
|
||||
[% ELSE %]
|
||||
<span class="error">Failed: [% HTML.escape(step.errormsg) %]</span>
|
||||
[% END %]
|
||||
[% IF step.logfile %]
|
||||
(<a href="[% log %]">log</a>)
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
[% IF build.finished %]
|
||||
|
||||
|
||||
[% IF build.resultInfo.errormsg %]
|
||||
|
||||
<h2 id="nix-error">Nix error output</h2>
|
||||
|
||||
<pre class="buildlog">
|
||||
[% HTML.escape(build.resultInfo.errormsg) -%]
|
||||
</pre>
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
[% IF build.buildproducts %]
|
||||
|
||||
<h2>Build products</h2>
|
||||
|
||||
[% IF !available %]
|
||||
<p class="error">Note: this build is no longer available.</p>
|
||||
[% END %]
|
||||
|
||||
[% PROCESS renderProductList %]
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
[% IF build.dependents %]
|
||||
|
||||
<h2>Used by</h2>
|
||||
|
||||
<p>The following builds have used this build as an input:</p>
|
||||
|
||||
<table class="tablesorter">
|
||||
<thead>
|
||||
<tr><th>Build</th><th>Input name</th><th>System</th><th>Timestamp</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% FOREACH input IN build.dependents -%]
|
||||
<tr>
|
||||
<td><a href="[% c.uri_for('/build' input.build.id) %]">Job <tt>[% input.build.project.name %]:[% input.build.attrname %]</tt> build [% input.build.id %]</a></td>
|
||||
<td><tt>[% input.name %]</tt></td>
|
||||
<td><tt>[% input.build.system %]</tt></td>
|
||||
<td>[% PROCESS renderDateTime timestamp = input.build.timestamp %]</td>
|
||||
</tr>
|
||||
[% END -%]
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
[% ELSIF build.schedulingInfo.busy %]
|
||||
|
||||
|
||||
<h2>Log</h2>
|
||||
|
||||
<pre class="buildlog">
|
||||
[% HTML.escape(logtext) -%]
|
||||
</pre>
|
||||
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
[% END %]
|
||||
|
78
src/root/channel-contents.tt
Normal file
@ -0,0 +1,78 @@
|
||||
[% WRAPPER layout.tt title="Channel ${channelName}" %]
|
||||
[% PROCESS common.tt %]
|
||||
[% USE HTML %]
|
||||
|
||||
<h1>Channel <tt>[% channelName %]</tt></h1>
|
||||
|
||||
<p>This page provides a <em>channel</em> for the <a
|
||||
href="http://nixos.org/">Nix package manager</a>. If you have Nix
|
||||
installed, you can subscribe to this channel by once executing</p>
|
||||
|
||||
<pre>
|
||||
$ nix-channel --add [% curUri %]
|
||||
$ nix-channel --update</pre>
|
||||
|
||||
<p>You can then query and install packages in the normal way, e.g.,</p>
|
||||
|
||||
<pre>
|
||||
$ nix-env -qa '*'
|
||||
$ nix-env -i foo</pre>
|
||||
|
||||
<p>You can update to the latest versions of the packages in this channel by executing</p>
|
||||
|
||||
<pre>
|
||||
$ nix-channel --update
|
||||
$ nix-env -u '*'</pre>
|
||||
|
||||
<p>Alternatively, if you have associated the
|
||||
<tt>application/nix-package</tt> MIME type with the
|
||||
<tt>nix-install-package</tt> program in your web browser, you can
|
||||
install the package simply by clicking on the packages below.</p>
|
||||
|
||||
|
||||
<h2>Packages</h2>
|
||||
|
||||
<p>This channel contains the following packages.</p>
|
||||
|
||||
<table class="tablesorter">
|
||||
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Name</th>
|
||||
<th>System</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
[% odd = 0 %]
|
||||
|
||||
[% FOREACH pkg IN nixPkgs %]
|
||||
|
||||
[% build = pkg.build %]
|
||||
[% uri = "${curUri}/pkg/${pkg.name}.nixpkg" %]
|
||||
|
||||
<tr class="clickable [% IF odd %] odd [% END; odd = !odd %]" onclick="window.location = '[% uri %]'">
|
||||
<td><a href="[% c.uri_for('/build' build.id) %]">[% build.id %]</a></td>
|
||||
<td><a href="[% uri %]"><tt>[% build.resultInfo.releasename || build.nixname %]</tt></a></td>
|
||||
<td><tt>[% build.system %]</tt></td>
|
||||
<td>
|
||||
[% IF build.homepage -%]
|
||||
<a [% HTML.attributes(href => build.homepage) %]>[% HTML.escape(build.description) %]</a>
|
||||
[% ELSE -%]
|
||||
[% HTML.escape(build.description) -%]
|
||||
[% END -%]
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
|
||||
[% END %]
|
110
src/root/common.tt
Normal file
@ -0,0 +1,110 @@
|
||||
[% USE date %]
|
||||
|
||||
|
||||
[% inputTypes =
|
||||
{ "svn" = "Subversion checkout"
|
||||
, "cvs" = "CVS checkout"
|
||||
, "tarball" = "Download of a tarball"
|
||||
, "string" = "String value"
|
||||
, "boolean" = "Boolean"
|
||||
, "path" = "Local path"
|
||||
, "build" = "Build output"
|
||||
}
|
||||
%]
|
||||
|
||||
|
||||
[% BLOCK renderDateTime %]
|
||||
[% date.format(timestamp, '%Y-%m-%d %H:%M:%S') -%]
|
||||
[% END %]
|
||||
|
||||
|
||||
[% BLOCK renderBuildList %]
|
||||
<table class="buildList tablesorter">
|
||||
<thead>
|
||||
<tr>
|
||||
[% IF !hideResultInfo %]
|
||||
<th></th>
|
||||
[% END %]
|
||||
<th>#</th>
|
||||
[% IF showSchedulingInfo %]
|
||||
<th>Priority</th>
|
||||
[% END %]
|
||||
<th>Project</th>
|
||||
<th>Job</th>
|
||||
<th>Name</th>
|
||||
<th>System</th>
|
||||
<th>Timestamp</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% odd = 0 %]
|
||||
[% FOREACH build IN builds -%]
|
||||
<tr class="clickable
|
||||
[% IF showSchedulingInfo -%]
|
||||
[% IF build.schedulingInfo.busy %]runningBuild[% END %] [% IF build.schedulingInfo.disabled == 1 || build.project.enabled == 0 %]disabledBuild[% END -%]
|
||||
[% ELSE -%]
|
||||
[% IF odd %] odd [% END; odd = !odd -%]
|
||||
[% END %]"
|
||||
onclick="window.location = '[% c.uri_for('/build' build.id) %]'">
|
||||
[% IF !hideResultInfo %]
|
||||
<td>
|
||||
[% IF build.resultInfo.buildstatus == 0 %]
|
||||
<img src="/static/images/success.gif" alt="Succeeded" />
|
||||
[% ELSE %]
|
||||
<img src="/static/images/failure.gif" alt="Failed" />
|
||||
[% END %]
|
||||
</td>
|
||||
[% END %]
|
||||
<td><a href="[% c.uri_for('/build' build.id) %]">[% build.id %]</a></td>
|
||||
[% IF showSchedulingInfo %]
|
||||
<td>[% build.schedulingInfo.priority %]</td>
|
||||
[% END %]
|
||||
<td><a href="[% c.uri_for('/project' build.get_column("project")) %]"><tt>[% build.get_column("project") %]</tt></a></td>
|
||||
<td><a href="[% c.uri_for('/project' build.get_column("project") 'job' build.attrname) %]"><tt>[% build.attrname %]</tt></a></td>
|
||||
<td>[% build.resultInfo.releasename ? build.resultInfo.releasename : build.nixname %]</td>
|
||||
<td><tt>[% build.system %]</tt></td>
|
||||
<td>[% date.format(build.timestamp, '%Y-%m-%d %H:%M:%S') %]</td>
|
||||
<td>[% build.description %]</td>
|
||||
</tr>
|
||||
[% END -%]
|
||||
</tbody>
|
||||
</table>
|
||||
[% END %]
|
||||
|
||||
|
||||
[% BLOCK showBuildStats %]
|
||||
|
||||
<table class="layoutTable">
|
||||
<tr>
|
||||
<th>Finished builds:</th>
|
||||
<td>[% finishedBuilds %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><img src="/static/images/success.gif" alt="Succeeded" /> Succeeded builds:</th>
|
||||
<td>[% succeededBuilds %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th><img src="/static/images/failure.gif" alt="Failed" /> Failed builds:</th>
|
||||
<td>[% finishedBuilds - succeededBuilds %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Total build time:</th>
|
||||
<td>[% totalBuildTime %]s</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Scheduled builds:</th>
|
||||
<td>[% scheduledBuilds %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Currently executing builds:</th>
|
||||
<td>[% busyBuilds %]</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
[% BLOCK renderReleaseJobName -%]
|
||||
[% IF job.description; HTML.escape(job.description); ELSE %]<tt>[% job.job %]</tt> ([% job.attrs %])[% END -%]
|
||||
[% END -%]
|
102
src/root/edit-releaseset.tt
Normal file
@ -0,0 +1,102 @@
|
||||
[% WRAPPER layout.tt title=(create ? "New Release Set" : "Release Set ‘$curProject.name:$releaseSet.name’") %]
|
||||
[% PROCESS common.tt %]
|
||||
[% USE HTML %]
|
||||
|
||||
<h1>[% IF create %]New Release Set[% ELSE %]Release Set <tt>[% curProject.name %]:[% releaseSet.name %]</tt>[% END %]</h1>
|
||||
|
||||
|
||||
[% BLOCK renderJob %]
|
||||
<tr id="[% id %]" >
|
||||
<td>
|
||||
<button type="button" onclick='$(this).parents("tr").remove()'>
|
||||
<img src="/static/images/failure.gif" alt="Delete job" />
|
||||
</button>
|
||||
</td>
|
||||
<td><input type="radio" id="[% "$baseName-primary" %]" name="primary" [% IF job.isprimary %]
|
||||
checked="checked" [% END %] [% HTML.attributes(value => "$n") %] /></td>
|
||||
<td><input type="text" class="string" [% HTML.attributes(id => "$baseName-name", name => "$baseName-name", value => job.job) %] /></td>
|
||||
<td><input type="text" class="string" [% HTML.attributes(id => "$baseName-description", name => "$baseName-description", value => job.description) %] /></td>
|
||||
<td><input type="text" class="string" [% HTML.attributes(id => "$baseName-attrs", name => "$baseName-attrs", value => job.attrs) %] /></td>
|
||||
</tr>
|
||||
[% END %]
|
||||
|
||||
|
||||
<form action="[% IF create %][% c.uri_for('/create_releaseset' curProject.name 'submit') %][% ELSE %][% c.uri_for('/releases' curProject.name releaseSet.name 'submit') %][% END %]" method="post">
|
||||
|
||||
<table class="layoutTable">
|
||||
<tr>
|
||||
<th>Identifier:</th>
|
||||
<td><input type="text" class="string" name="name" [% HTML.attributes(value => releaseSet.name) %] /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Description:</th>
|
||||
<td><input type="text" class="string" name="description" [% HTML.attributes(value => releaseSet.description) %] /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table class="tablesorter">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Primary job</th>
|
||||
<th>Job name</th>
|
||||
<th>Description</th>
|
||||
<th>Constraint</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% n = 0 %]
|
||||
[% FOREACH job IN jobs %]
|
||||
[% INCLUDE renderJob baseName="job-$n" %]
|
||||
[% n = n + 1 %]
|
||||
[% END %]
|
||||
<tr>
|
||||
<td colspan="5"><button type="button" class="add-job">Add a new job</button></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p><button type="submit"><img src="/static/images/success.gif" />[%IF create %]Create[% ELSE %]Apply changes[% END %]</button></p>
|
||||
|
||||
</form>
|
||||
|
||||
|
||||
<table class="template"> <!-- dummy wrapper needed because “hidden” trs are visible anyway -->
|
||||
[% INCLUDE renderJob job="" id="job-template" baseName="job-template" %]
|
||||
</table>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
var id = [% n %];
|
||||
|
||||
$(".add-job").click(function() {
|
||||
var newnr = id++;
|
||||
var newid = "job-" + newnr;
|
||||
var x = $("#job-template").clone(true).attr("id", "").insertBefore($(this).parents("tr")).show();
|
||||
$("#job-template-name", x).attr("name", newid + "-name");
|
||||
$("#job-template-description", x).attr("name", newid + "-description");
|
||||
$("#job-template-attrs", x).attr("name", newid + "-attrs");
|
||||
$("#job-template-primary", x).attr("value", newnr);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
[% IF !create %]
|
||||
|
||||
<form action="[% c.uri_for('/releases' curProject.name releaseSet.name 'delete') %]" method="post">
|
||||
<p><button id="delete-project" type="submit"><img src="/static/images/failure.gif" />Delete this release set</button></p>
|
||||
</form>
|
||||
|
||||
<script type="text/javascript">
|
||||
$("#delete-project").click(function() {
|
||||
return confirm("Are you sure you want to delete this release set?");
|
||||
});
|
||||
</script>
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
[% END %]
|
14
src/root/error.tt
Normal file
@ -0,0 +1,14 @@
|
||||
[% WRAPPER layout.tt title="Error" %]
|
||||
[% USE HTML %]
|
||||
|
||||
<h1>[% IF httpStatus %][% httpStatus %][% ELSE %]Error[% END %]</h1>
|
||||
|
||||
<p>I'm very sorry, but the following error(s) occurred:</p>
|
||||
|
||||
<ul>
|
||||
[% FOREACH error IN errors %]
|
||||
<li><div class="error-msg">[% HTML.escape(error) %]</div></li>
|
||||
[% END %]
|
||||
</ul>
|
||||
|
||||
[% END %]
|
13
src/root/index.tt
Normal file
@ -0,0 +1,13 @@
|
||||
[% WRAPPER layout.tt title="Overview" %]
|
||||
[% PROCESS common.tt %]
|
||||
|
||||
|
||||
<h1>Hydra Overview</h1>
|
||||
|
||||
|
||||
<h2>Statistics</h2>
|
||||
|
||||
[% PROCESS showBuildStats %]
|
||||
|
||||
|
||||
[% END %]
|
10
src/root/jobstatus.tt
Normal file
@ -0,0 +1,10 @@
|
||||
[% WRAPPER layout.tt title="Job Status" %]
|
||||
[% PROCESS common.tt %]
|
||||
|
||||
<h1>Job Status[% IF curProject %] of Project <tt>[% curProject.name %]</tt>[% END %]</h1>
|
||||
|
||||
<p>Below are the latest builds for each job.</p>
|
||||
|
||||
[% PROCESS renderBuildList builds=latestBuilds %]
|
||||
|
||||
[% END %]
|
161
src/root/layout.tt
Normal file
@ -0,0 +1,161 @@
|
||||
[% USE date -%]
|
||||
[% USE HTML -%]
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
[% PROCESS common.tt %]
|
||||
|
||||
[% BLOCK makeLinkWrapped %]
|
||||
<li [% IF curUri == uri %]class="active"[% END %]>
|
||||
<div class="title"><a href="[% uri %]">[% title %]</a></div>
|
||||
[% content %]
|
||||
</li>
|
||||
[% END %]
|
||||
|
||||
[% BLOCK makeLink -%]
|
||||
[% INCLUDE makeLinkWrapped content="" -%]
|
||||
[% END %]
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
|
||||
<head>
|
||||
<title>Hydra - [% title %]</title>
|
||||
<link rel="stylesheet" href="/static/css/hydra.css" type="text/css" />
|
||||
<link rel="stylesheet" href="/static/css/logfile.css" type="text/css" />
|
||||
<script type="text/javascript" src="/static/js/jquery-pack.js"></script>
|
||||
<script type="text/javascript" src="/static/js/tablesorter/jquery.tablesorter.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
|
||||
/*** Sortable tables. ***/
|
||||
|
||||
$("table.tablesorter").tablesorter();
|
||||
|
||||
|
||||
/*** Tree toggles in logfiles. ***/
|
||||
|
||||
/* Set the appearance of the toggle depending on whether the
|
||||
corresponding subtree is initially shown or hidden. */
|
||||
$(".logTreeToggle").map(function() {
|
||||
if ($(this).siblings("ul:hidden").length == 0) {
|
||||
$(this).text("-");
|
||||
} else {
|
||||
$(this).text("+");
|
||||
}
|
||||
});
|
||||
|
||||
/* When a toggle is clicked, show or hide the subtree. */
|
||||
$(".logTreeToggle").click(function() {
|
||||
if ($(this).siblings("ul:hidden").length != 0) {
|
||||
$(this).siblings("ul").show();
|
||||
$(this).text("-");
|
||||
} else {
|
||||
$(this).siblings("ul").hide();
|
||||
$(this).text("+");
|
||||
}
|
||||
});
|
||||
|
||||
/* Implementation of the expand all link. */
|
||||
$(".logTreeExpandAll").click(function() {
|
||||
$(".logTreeToggle", $(this).siblings(".toplevel")).map(function() {
|
||||
$(this).siblings("ul").show();
|
||||
$(this).text("-");
|
||||
});
|
||||
});
|
||||
|
||||
/* Implementation of the collapse all link. */
|
||||
$(".logTreeCollapseAll").click(function() {
|
||||
$(".logTreeToggle", $(this).siblings(".toplevel")).map(function() {
|
||||
$(this).siblings("ul").hide();
|
||||
$(this).text("+");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="container">
|
||||
|
||||
<div id="leftnavbar">
|
||||
<div id="logo"><img src="/static/images/hydra.png" alt="Hydra" /></div>
|
||||
|
||||
<ul class="menu">
|
||||
<li>
|
||||
<div class="title">Hydra</div>
|
||||
<ul class="submenu">
|
||||
[% INCLUDE makeLink uri = c.uri_for('/') title = "Overview" %]
|
||||
[% INCLUDE makeLink uri = c.uri_for('/queue') title = "Queue" %]
|
||||
[% INCLUDE makeLink uri = c.uri_for('/jobstatus') title = "Job status" %]
|
||||
[% INCLUDE makeLink uri = c.uri_for('/all') title = "All builds" %]
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<div class="title">Projects</div>
|
||||
<ul class="submenu">
|
||||
[% FOREACH project IN projects %]
|
||||
<li [% IF curUri == c.uri_for('/project' project.name) %]class="active"[% END %]>
|
||||
<div class="title"><a href="[% c.uri_for('/project' project.name) %]">[% HTML.escape(project.displayname) %]</a></div>
|
||||
[% IF curProject.name == project.name %]
|
||||
<ul class="subsubmenu">
|
||||
[% INCLUDE makeLink uri = c.uri_for('/project' project.name 'jobstatus') title = "Job status" %]
|
||||
[% INCLUDE makeLink uri = c.uri_for('/project' project.name 'all') title = "All builds" %]
|
||||
[% WRAPPER makeLinkWrapped uri = c.uri_for('/releasesets' project.name) title = "Releases" %]
|
||||
[% IF project.releasesets && project.releasesets.size > 0 %]
|
||||
<ul class="subsubsubmenu">
|
||||
[% FOREACH releaseset IN project.releasesets %]
|
||||
[% myUri = c.uri_for('/releases' project.name releaseset.name) %]
|
||||
<li [% IF curUri == myUri %]class="active"[% END %]>
|
||||
<div class="title"><a href="[% myUri %]">
|
||||
[% HTML.escape(releaseset.description ? releaseset.description : releaseset.name) %]
|
||||
</a></div>
|
||||
</li>
|
||||
[% END %]
|
||||
</ul>
|
||||
[% END %]
|
||||
[% END %]
|
||||
|
||||
|
||||
[% INCLUDE makeLink uri = c.uri_for('/project' project.name 'edit') title = "Edit" %]
|
||||
</ul>
|
||||
[% END %]
|
||||
</li>
|
||||
[% END %]
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<div class="title">Admin</div>
|
||||
<ul class="submenu">
|
||||
[% IF c.user_exists %]
|
||||
[% INCLUDE makeLink uri = c.uri_for('/logout') title = "Logout" %]
|
||||
[% ELSE %]
|
||||
[% INCLUDE makeLink uri = c.uri_for('/login') title = "Login" %]
|
||||
[% END %]
|
||||
[% INCLUDE makeLink uri = c.uri_for('/create-project') title = "Create project" %]
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
[% content %]
|
||||
<div id="footer">
|
||||
<hr />
|
||||
Generated on [% PROCESS renderDateTime %].
|
||||
[% IF c.user_exists %]
|
||||
You are logged in as <tt>[% c.user.username %]</tt>.
|
||||
[% END %]
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
9
src/root/log.tt
Normal file
@ -0,0 +1,9 @@
|
||||
[% WRAPPER layout.tt title="Logfile" %]
|
||||
|
||||
<h1>Logfile for <tt>[% build.project.name %]:[% build.attrname %]</tt> build [% build.id %][%IF step %], step [% step.stepnr %] (<tt>[% step.outpath %]</tt>)[% END %]</h1>
|
||||
|
||||
<div class="buildlog">
|
||||
[% logtext -%]
|
||||
</div>
|
||||
|
||||
[% END %]
|
39
src/root/login.tt
Normal file
@ -0,0 +1,39 @@
|
||||
[% WRAPPER layout.tt title="Login to Hydra" %]
|
||||
[% PROCESS common.tt %]
|
||||
|
||||
<h1>Login</h1>
|
||||
|
||||
[% IF c.user_exists %]
|
||||
<p>
|
||||
You are already logged in as <tt>[% c.user.username %]</tt>.
|
||||
You can <a href="[% c.uri_for('/logout') %]">logout</a> here.
|
||||
</p>
|
||||
[% ELSE %]
|
||||
|
||||
[% IF errorMsg %]
|
||||
<p class="error">Error: [% errorMsg %]</p>
|
||||
[% END %]
|
||||
|
||||
<form method="post" action="[% c.uri_for('/login') %]">
|
||||
|
||||
<table class="layoutTable">
|
||||
<tr>
|
||||
<td>Username:</td>
|
||||
<td><input type="text" name="username" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password:</td>
|
||||
<td><input type="password" name="password" /></td>
|
||||
</tr>
|
||||
<tr colspan="2">
|
||||
<td>
|
||||
<input type="submit" name="login" value="Login" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
|
||||
[% END %]
|
||||
|
||||
[% END %]
|
170
src/root/product-list.tt
Normal file
@ -0,0 +1,170 @@
|
||||
[% USE mibs=format("%.2f") %]
|
||||
|
||||
[% BLOCK renderProductList -%]
|
||||
|
||||
<ul class="productList">
|
||||
|
||||
[% FOREACH product IN build.buildproducts -%]
|
||||
|
||||
[% uri = c.uri_for('/build' build.id 'download' product.productnr product.name) %]
|
||||
|
||||
[% SWITCH product.type %]
|
||||
|
||||
[% CASE "nix-build" %]
|
||||
|
||||
<li class="product">
|
||||
[% uri = c.uri_for('/build' build.id 'nix' 'pkg' "${build.nixname}-${build.system}.nixpkg") %]
|
||||
<a href="[% uri %]">
|
||||
<img src="/static/images/nix-build.png" alt="Source" />
|
||||
One-click install of Nix package <tt>[% build.nixname %]</tt>
|
||||
</a>
|
||||
[<a class="productDetailsToggle" href="javascript:">help</a>]
|
||||
<div class="help productDetails">
|
||||
<p>If you have Nix installed on your machine, you can
|
||||
install this package and all its dependencies automatically
|
||||
by clicking on the link above. This requires that you have
|
||||
the <tt>application/nix-package</tt> MIME type associated
|
||||
with the <tt>nix-install-package</tt> program in your web
|
||||
browser. Alternatively, you can install it from the
|
||||
command-line:</p>
|
||||
|
||||
<pre>$ nix-install-package --non-interactive --url [% uri %]</pre>
|
||||
|
||||
<p>If you get an error message “Permission denied”, you
|
||||
should make sure that you have sufficient access rights to
|
||||
the Nix store, e.g., run the command as <tt>root</tt>.
|
||||
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="product">
|
||||
|
||||
[% filename = "${build.nixname}.closure.gz" %]
|
||||
[% uri = c.uri_for('/build' build.id 'nix' 'closure' filename ) %]
|
||||
|
||||
<a href="[% uri %]">
|
||||
<img src="/static/images/nix-build.png" alt="Source" />
|
||||
Nix closure of path <tt>[% product.path %]</tt>
|
||||
</a>
|
||||
|
||||
[<a class="productDetailsToggle" href="javascript:">help</a>]
|
||||
<div class="help productDetails">
|
||||
<p>If you have Nix installed on your machine, this build and
|
||||
all its dependencies can be unpacked into your local Nix
|
||||
store by doing:</p>
|
||||
|
||||
<pre>$ gunzip < [% filename %] | nix-store --import</pre>
|
||||
|
||||
<p>or to download and unpack in one command:</p>
|
||||
|
||||
<pre>$ curl [% uri %] | gunzip | nix-store --import</pre>
|
||||
|
||||
<p>The package can then be found in the path <tt>[%
|
||||
product.path %]</tt>. You’ll probably also want to do</p>
|
||||
|
||||
<pre>$ nix-env -i [% product.path %]</pre>
|
||||
|
||||
<p>to actually install the package in your Nix user environment.</p>
|
||||
|
||||
<p>If you get the error message “imported
|
||||
archive lacks a signature”, you should make sure that you have
|
||||
sufficient access rights to the Nix store, e.g., run the
|
||||
command as <tt>root</tt>.</p>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
|
||||
|
||||
[% CASE "file" %]
|
||||
|
||||
<li class="product">
|
||||
<a href="[% uri %]">
|
||||
[% SWITCH product.subtype %]
|
||||
[% CASE "source-dist" %]
|
||||
<img src="/static/images/source-dist.png" alt="Source" /> Source distribution <tt>[% product.name %]</tt>
|
||||
[% CASE "rpm" %]
|
||||
<img src="/static/images/rpm.png" alt="RPM" /> RPM package <tt>[% product.name %]</tt>
|
||||
[% CASE "deb" %]
|
||||
<img src="/static/images/debian.png" alt="RPM" /> Debian package <tt>[% product.name %]</tt>
|
||||
[% CASE "iso" %]
|
||||
<img src="/static/images/iso.png" alt="ISO" /> ISO-9660 CD/DVD image <tt>[% product.name %]</tt>
|
||||
[% CASE DEFAULT %]
|
||||
File <tt>[% product.name %]</tt> of type <tt>[% product.subtype %]</tt>
|
||||
[% END %]
|
||||
</a>
|
||||
[<a class="productDetailsToggle" href="javascript:">details</a>]
|
||||
<div class="productDetails">
|
||||
<table>
|
||||
<tr>
|
||||
<th>URL:</th>
|
||||
<td>
|
||||
<a href="[% uri %]">
|
||||
<tt>[% uri %]</tt>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><th>File size:</th><td>[% product.filesize %] bytes ([% mibs(product.filesize / (1024 * 1024)) %] MiB)</td></tr>
|
||||
<tr><th>SHA-1 hash:</th><td><tt>[% product.sha1hash %]</tt></td></tr>
|
||||
<tr><th>SHA-256 hash:</th><td><tt>[% product.sha256hash %]</tt></td></tr>
|
||||
<tr><th>Full path:</th><td><tt>[% product.path %]</tt></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
[% CASE "report" %]
|
||||
|
||||
<li class="product">
|
||||
<a href="[% uri %]">
|
||||
<img src="/static/images/report.png" alt="Report" />
|
||||
[% SWITCH product.subtype %]
|
||||
[% CASE "coverage" %]
|
||||
Code coverage analysis report
|
||||
[% CASE DEFAULT %]
|
||||
Report of type <tt>[% product.subtype %]</tt>
|
||||
[% END %]
|
||||
</a>
|
||||
</li>
|
||||
|
||||
[% CASE "doc" %]
|
||||
|
||||
<li class="product">
|
||||
<a href="[% uri %]">
|
||||
<img src="/static/images/document.png" alt="Document" />
|
||||
[% SWITCH product.subtype %]
|
||||
[% CASE "readme" %]
|
||||
“README” file
|
||||
[% CASE "manual" %]
|
||||
Manual
|
||||
[% CASE "release-notes" %]
|
||||
Release notes
|
||||
[% CASE DEFAULT %]
|
||||
Documentation of type <tt>[% product.subtype %]</tt>
|
||||
[% END %]
|
||||
</a>
|
||||
</li>
|
||||
|
||||
[% CASE DEFAULT %]
|
||||
|
||||
<li class="product">
|
||||
Something of type <tt>[% product.type %]</tt>
|
||||
</li>
|
||||
|
||||
[% END %]
|
||||
|
||||
[% END -%]
|
||||
|
||||
</ul>
|
||||
|
||||
[% END %]
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.productDetailsToggle').toggle(
|
||||
function () { $(".productDetails", $(this).parents(".product")).fadeIn(); },
|
||||
function () { $(".productDetails", $(this).parents(".product")).hide(); }
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
295
src/root/project.tt
Normal file
@ -0,0 +1,295 @@
|
||||
[% WRAPPER layout.tt title=(edit ? (create ? "New Project" : "Editing Project ‘$curProject.name’") : "Project ‘$curProject.name’") %]
|
||||
[% PROCESS common.tt %]
|
||||
[% USE HTML %]
|
||||
|
||||
|
||||
[% BLOCK renderSelection %]
|
||||
[% IF edit %]
|
||||
<select [% HTML.attributes(id => param, name => param) %]>
|
||||
[% FOREACH name IN options.keys.sort %]
|
||||
<option [% HTML.attributes(value => name) %] [% IF name == curValue; "selected='selected'"; END %]>[% options.$name %]</option>
|
||||
[% END %]
|
||||
</select>
|
||||
[% ELSE %]
|
||||
[% options.$curValue %]
|
||||
[% END %]
|
||||
[% END %]
|
||||
|
||||
|
||||
[% BLOCK maybeEditString;
|
||||
IF edit -%]
|
||||
<input type="text" class="string [% extraClass %]" [% HTML.attributes(id => param, name => param, value => value) %] />
|
||||
[% ELSE;
|
||||
HTML.escape(value);
|
||||
END -%]
|
||||
[% END -%]
|
||||
|
||||
|
||||
[% BLOCK renderInputAlt %]
|
||||
[% IF edit %]
|
||||
<button type="button" onclick='$(this).parents(".inputalt").remove()'><img src="/static/images/failure.gif" alt="Delete value" /></button>
|
||||
[% INCLUDE maybeEditString param=param value=alt.value %]
|
||||
<br />
|
||||
[% ELSE %]
|
||||
[% INCLUDE maybeEditString param=param value=alt.value %]
|
||||
[% END %]
|
||||
[% END %]
|
||||
|
||||
|
||||
[% BLOCK renderInput %]
|
||||
|
||||
<tr class="input [% extraClass %]" [% IF id %]id="[% id %]"[% END %]>
|
||||
<td>
|
||||
[% IF edit %]<button type="button" onclick='$(this).parents(".input").remove()'><img src="/static/images/failure.gif" alt="Delete input" /></button>[% END -%]
|
||||
<tt>[% INCLUDE maybeEditString param="$baseName-name" value=input.name extraClass="shortString" %]</tt>
|
||||
</td>
|
||||
<td>
|
||||
[% INCLUDE renderSelection curValue=input.type param="$baseName-type" options=inputTypes %]
|
||||
</td>
|
||||
<td class="inputalts" id="[% baseName %]">
|
||||
[% FOREACH alt IN input.jobsetinputalts -%]
|
||||
<tt class="inputalt">
|
||||
[% IF input.type == "string" && !edit %]
|
||||
"[% HTML.escape(alt.value) %]"
|
||||
[% ELSE %]
|
||||
[% INCLUDE renderInputAlt alt=alt param="$baseName-values" %]
|
||||
[% END %]
|
||||
</tt>
|
||||
[% END %]
|
||||
[% IF edit %]<button type="button" onclick='return false' class="add-inputalt">+</button>[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
[% BLOCK renderJobset %]
|
||||
|
||||
<div class="jobset[% IF edit %] jobset-edit[% END %]" id="[% "jobset-$baseName" %]">
|
||||
|
||||
<h3>
|
||||
[% IF edit %]<button type="button" onclick='$(this).parents(".jobset").remove()'><img src="/static/images/failure.gif" alt="Delete value" /></button>[% END %]
|
||||
[% IF jobset %]Jobset <tt>[% jobset.name %]</tt>[% ELSE %]New jobset[% END %]
|
||||
</h3>
|
||||
|
||||
<h4>Information</h4>
|
||||
|
||||
<table class="layoutTable">
|
||||
[% IF edit %]
|
||||
<tr>
|
||||
<th>Identifier:</th>
|
||||
<td>[% INCLUDE maybeEditString param="jobset-$baseName-name" value=jobset.name %]</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
<tr>
|
||||
<th>Description:</th>
|
||||
<td>[% INCLUDE maybeEditString param="jobset-$baseName-description" value=jobset.description %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nix expression:</th>
|
||||
<td>
|
||||
<tt>[% INCLUDE maybeEditString param="jobset-$baseName-nixexprpath" value=jobset.nixexprpath extraClass="shortString" %]</tt> in input
|
||||
<tt>[% INCLUDE maybeEditString param="jobset-$baseName-nixexprinput" value=jobset.nixexprinput extraClass="shortString" %]</tt>
|
||||
</td>
|
||||
</tr>
|
||||
[% IF !edit %]
|
||||
<tr>
|
||||
<th>Last checked:</th>
|
||||
<td>
|
||||
[% IF jobset.lastcheckedtime %]
|
||||
[% PROCESS renderDateTime timestamp = jobset.lastcheckedtime %]
|
||||
[% ELSE %]
|
||||
<em>never</em>
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
[% IF !edit && jobset.errormsg %]
|
||||
<tr>
|
||||
<th>Last evaluation error:</th>
|
||||
<td>
|
||||
<em>On [% PROCESS renderDateTime timestamp = jobset.errortime %]:</em>
|
||||
<pre class="multiLineMsg error">[% HTML.escape(jobset.errormsg) %]</pre>
|
||||
</td>
|
||||
</tr>
|
||||
[% END %]
|
||||
</table>
|
||||
|
||||
<h4>Inputs</h4>
|
||||
|
||||
<table class="tablesorter">
|
||||
<thead>
|
||||
<tr><th>Input name</th><th>Type</th><th>Values</th></tr>
|
||||
</thead>
|
||||
<tbody class="inputs">
|
||||
[% FOREACH input IN jobset.jobsetinputs -%]
|
||||
[% INCLUDE renderInput input=input baseName="jobset-$baseName-input-$input.name" %]
|
||||
[% END %]
|
||||
[% IF edit %]
|
||||
<tr>
|
||||
<td colspan="3"><button type="button" class="add-input">Add a new input</button></td>
|
||||
</tr>
|
||||
[% END %]
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
[% IF edit %]
|
||||
<form action="[% IF create %][% c.uri_for('/create-project/submit') %][% ELSE %][% c.uri_for('/project' curProject.name 'submit') %][% END %]" method="post">
|
||||
[% END %]
|
||||
|
||||
|
||||
[% IF create %]
|
||||
<h1>New Project</h1>
|
||||
[% ELSE %]
|
||||
<h1>Project <tt>[% curProject.name %]</tt></h1>
|
||||
[% END %]
|
||||
|
||||
|
||||
<h2>General information</h2>
|
||||
|
||||
<table class="layoutTable">
|
||||
[% IF edit %]
|
||||
<tr>
|
||||
<th>Identifier:</th>
|
||||
<td><tt>[% INCLUDE maybeEditString param="name" value=curProject.name %]</tt></td>
|
||||
</tr>
|
||||
[% END %]
|
||||
<tr>
|
||||
<th>Display name:</th>
|
||||
<td>[% INCLUDE maybeEditString param="displayname" value=curProject.displayname %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Description:</th>
|
||||
<td>[% INCLUDE maybeEditString param="description" value=curProject.description %]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Homepage:</th>
|
||||
<td>
|
||||
[% IF edit %]
|
||||
[% INCLUDE maybeEditString param="homepage" value=curProject.homepage %]
|
||||
[% ELSE %]
|
||||
[% IF curProject.homepage %]
|
||||
<a [% HTML.attributes(href => curProject.homepage) %]>[% HTML.escape(curProject.homepage) %]</a>
|
||||
[% ELSE %]
|
||||
<em>(not specified)</em>
|
||||
[% END %]
|
||||
[% END %]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Owner:</th>
|
||||
<td><tt>[% INCLUDE maybeEditString param="owner" value=curProject.owner.username edit=(edit && c.check_user_roles('admin')) %]</tt></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Enabled:</th>
|
||||
<td>
|
||||
[% INCLUDE renderSelection param="enabled" curValue=curProject.enabled options={"1" = "Yes", "0" = "No"} %]
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
[% IF !edit %]
|
||||
|
||||
<h2>Statistics</h2>
|
||||
|
||||
[% PROCESS showBuildStats %]
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
<h2>Jobsets</h2>
|
||||
|
||||
[% IF curProject.jobsets && curProject.jobsets.size > 0 || edit %]
|
||||
|
||||
[% IF edit %]
|
||||
<p><button type="button" id="add-jobset">Add a new jobset</button></p>
|
||||
|
||||
<div id="jobset-template" class="template">
|
||||
[% INCLUDE renderJobset jobset="" baseName="template" %]
|
||||
</div>
|
||||
|
||||
<table class="template"> <!-- dummy wrapper needed because “hidden” trs are visible anyway -->
|
||||
[% INCLUDE renderInput input="" extraClass="template" id="input-template" baseName="input-template" %]
|
||||
</table>
|
||||
|
||||
<tt class="inputalt template" id="inputalt-template">
|
||||
[% INCLUDE renderInputAlt alt=alt %]
|
||||
</tt>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
var id = 0;
|
||||
|
||||
$("#add-jobset").click(function() {
|
||||
var newid = "jobset-" + id++;
|
||||
var x = $("#jobset-template").clone(true).attr("id", newid).insertAfter($("#jobset-template")).slideDown("fast");
|
||||
$("#jobset-template", x).attr("id", newid);
|
||||
$("#jobset-template-name", x).attr("name", newid + "-name");
|
||||
$("#jobset-template-description", x).attr("name", newid + "-description");
|
||||
$("#jobset-template-nixexprpath", x).attr("name", newid + "-nixexprpath");
|
||||
$("#jobset-template-nixexprinput", x).attr("name", newid + "-nixexprinput");
|
||||
return false;
|
||||
});
|
||||
|
||||
$(".add-input").click(function() {
|
||||
var jobset = $(this).parents(".jobset");
|
||||
var inputid = jobset.attr("id");
|
||||
var newid = inputid + "-input-" + id++;
|
||||
var x = $("#input-template").clone(true).attr("id", "").insertBefore($(this).parents("tr")).show();
|
||||
$("#input-template-name", x).attr("name", newid + "-name");
|
||||
$("#input-template-type", x).attr("name", newid + "-type");
|
||||
$("#input-template", x).attr("id", newid);
|
||||
return false;
|
||||
});
|
||||
|
||||
$(".add-inputalt").click(function() {
|
||||
var x = $("#inputalt-template").clone(true).insertBefore($(this)).attr("id", "").show();
|
||||
$("input", x).attr("name", x.parents(".inputalts").attr("id") + "-values");
|
||||
});
|
||||
});
|
||||
</script>
|
||||
[% END %]
|
||||
|
||||
[% FOREACH jobset IN curProject.jobsets -%]
|
||||
[% INCLUDE renderJobset jobset=jobset baseName=jobset.name %]
|
||||
[% END -%]
|
||||
|
||||
[% ELSE %]
|
||||
|
||||
<p>No jobsets have been defined yet.</p>
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
[% IF edit %]
|
||||
|
||||
<hr />
|
||||
|
||||
<p><button type="submit"><img src="/static/images/success.gif" />[%IF create %]Create[% ELSE %]Apply changes[% END %]</button></p>
|
||||
|
||||
</form>
|
||||
|
||||
[% IF !create %]
|
||||
|
||||
<form action="[% c.uri_for('/project' curProject.name 'delete') %]" method="post">
|
||||
<p><button id="delete-project" type="submit"><img src="/static/images/failure.gif" />Delete this project</button></p>
|
||||
</form>
|
||||
|
||||
<script type="text/javascript">
|
||||
$("#delete-project").click(function() {
|
||||
return confirm("Are you sure you want to delete this project?");
|
||||
});
|
||||
</script>
|
||||
|
||||
[% END %]
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
[% END %]
|
20
src/root/queue.tt
Normal file
@ -0,0 +1,20 @@
|
||||
[% WRAPPER layout.tt title="Queue" %]
|
||||
[% PROCESS common.tt %]
|
||||
|
||||
<h1>Hydra Queue</h1>
|
||||
|
||||
[% IF scheduled.size == 0 %]
|
||||
|
||||
<p>The queue is empty.</p>
|
||||
|
||||
[% ELSE %]
|
||||
|
||||
<p>Note: Builds in <span class="runningBuild">red</span> are
|
||||
currently executing. Builds in <span
|
||||
class="disabledBuild">grey</span> are currently disabled.</p>
|
||||
|
||||
[% PROCESS renderBuildList builds=queue showSchedulingInfo=1 hideResultInfo=1 %]
|
||||
|
||||
[% END %]
|
||||
|
||||
[% END %]
|
43
src/root/release.tt
Normal file
@ -0,0 +1,43 @@
|
||||
[% releaseName = (release.releasename || "(No name)") -%]
|
||||
[% WRAPPER layout.tt title="Release $releaseName" %]
|
||||
[% PROCESS common.tt %]
|
||||
[% PROCESS "product-list.tt" %]
|
||||
[% USE HTML %]
|
||||
|
||||
<h1>Release <tt>[% releaseName %]</tt></h1>
|
||||
|
||||
[% IF release.status == 1 %]
|
||||
<p class="error">This is a failed release. One of its jobs has failed. See below for details.</p>
|
||||
[% ELSIF release.status == 2 %]
|
||||
<p class="error">This is an incomplete release. One of its jobs has not been built (yet). See below for details.</p>
|
||||
[% END %]
|
||||
|
||||
[% FOREACH job IN release.jobs %]
|
||||
|
||||
<h2>
|
||||
[% IF job.build %]<a href="[% c.uri_for('/build' job.build.id) %]">[% END %]
|
||||
[% INCLUDE renderReleaseJobName job=job.job %]
|
||||
[% IF job.build %]</a>[% END %]
|
||||
</h2>
|
||||
|
||||
[% IF job.build %]
|
||||
|
||||
[% IF job.build.resultInfo.buildstatus == 0 %]
|
||||
|
||||
[% INCLUDE renderProductList build=job.build %]
|
||||
|
||||
[% ELSE %]
|
||||
|
||||
<p class="error">Build failed</p>
|
||||
|
||||
[% END %]
|
||||
|
||||
[% ELSE %]
|
||||
|
||||
<p class="error">Build not (yet) performed.</p>
|
||||
|
||||
[% END %]
|
||||
|
||||
[% END %]
|
||||
|
||||
[% END %]
|
65
src/root/releases.tt
Normal file
@ -0,0 +1,65 @@
|
||||
[% WRAPPER layout.tt title="Release Set ‘$releaseSet.project.name:$releaseSet.name’" %]
|
||||
[% PROCESS common.tt %]
|
||||
[% USE HTML %]
|
||||
|
||||
<h1>Release Set <tt>[% releaseSet.project.name %]:[% releaseSet.name %]</tt></h1>
|
||||
|
||||
<p>
|
||||
[<a href="[% c.uri_for('/releases' curProject.name releaseSet.name "edit") %]">Edit</a>]
|
||||
[<a href="[% c.uri_for('/release' curProject.name releaseSet.name "latest") %]">Latest</a>]
|
||||
</p>
|
||||
|
||||
<table class="tablesorter">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>#</th>
|
||||
<th>Release</th>
|
||||
<th>Date</th>
|
||||
[% FOREACH job IN jobs %]
|
||||
<th class="releaseSetJobName">[% PROCESS renderReleaseJobName %]</th>
|
||||
[% END %]
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
[% FOREACH release IN releases %]
|
||||
[% link = c.uri_for('/release' releaseSet.project.name releaseSet.name release.id) %]
|
||||
<tr class="clickable" onclick="window.location = '[% link %]'">
|
||||
<td>
|
||||
[% IF release.status == 0 %]
|
||||
<img src="/static/images/success.gif" />
|
||||
[% ELSIF release.status == 1 %]
|
||||
<img src="/static/images/failure.gif" />
|
||||
[% ELSIF release.status == 2 %]
|
||||
<img src="/static/images/question-mark.png" />
|
||||
[% END %]
|
||||
</td>
|
||||
<td><a href="[% link %]">[% release.id %]</a></td>
|
||||
<td>
|
||||
[% IF release.releasename %]
|
||||
<tt>[% release.releasename %]</tt>
|
||||
[% ELSE %]
|
||||
<em>No name</em>
|
||||
[% END %]
|
||||
</td>
|
||||
<td>[% INCLUDE renderDateTime timestamp=release.timestamp %]</td>
|
||||
[% FOREACH job IN release.jobs %]
|
||||
<td class="centered">
|
||||
[% IF job.build %]
|
||||
<a href="[% c.uri_for('/build' job.build.id) %]">
|
||||
[% IF job.build.resultInfo.buildstatus == 0 %]
|
||||
<img src="/static/images/success.gif" />
|
||||
[% ELSE %]
|
||||
<img src="/static/images/failure.gif" />
|
||||
[% END %]
|
||||
</a>
|
||||
[% END %]
|
||||
</td>
|
||||
[% END %]
|
||||
</tr>
|
||||
[% END %]
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
[% END %]
|
28
src/root/releasesets.tt
Normal file
@ -0,0 +1,28 @@
|
||||
[% WRAPPER layout.tt title="Release Sets" %]
|
||||
[% PROCESS common.tt %]
|
||||
|
||||
<h1>Release Sets</h1>
|
||||
|
||||
[% IF releaseSets.size > 0 %]
|
||||
|
||||
<p>Project <tt>[% curProject.name %]</tt> has the following release sets:</p>
|
||||
|
||||
<ul>
|
||||
[% FOREACH releaseSet IN releaseSets %]
|
||||
<li>
|
||||
<a href="[% c.uri_for('/releases' curProject.name releaseSet.name) %]"><tt>[% releaseSet.name %]</tt></a>
|
||||
[<a href="[% c.uri_for('/releases' curProject.name releaseSet.name "edit") %]">Edit</a>]
|
||||
</li>
|
||||
[% END %]
|
||||
</ul>
|
||||
|
||||
[% ELSE %]
|
||||
|
||||
<p>Project <tt>[% curProject.name %]</tt> has no release sets.</p>
|
||||
|
||||
[% END %]
|
||||
|
||||
|
||||
<p>[<a href="[% c.uri_for('/create_releaseset' curProject.name) %]">Create a new release set</a>]</p>
|
||||
|
||||
[% END %]
|
447
src/root/static/css/hydra.css
Normal file
@ -0,0 +1,447 @@
|
||||
body {
|
||||
font-family: sans-serif;
|
||||
background: white;
|
||||
margin: 2em 1em 2em 1em;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
font-weight: bold;
|
||||
color: #005aa0;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 220%;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 130%;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
table {
|
||||
empty-cells: show;
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0px;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
tr.clickable:hover {
|
||||
background-color: #a0a0f0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
tr.odd {
|
||||
background: #f4f4ff;
|
||||
}
|
||||
|
||||
.layoutTable td, .layoutTable th {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
td, th {
|
||||
padding: 2px 5px;
|
||||
border: solid black 1px;
|
||||
}
|
||||
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
td.centered {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.layoutTable th {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
th {
|
||||
vertical-align: center;
|
||||
background: #ffffc0;
|
||||
}
|
||||
|
||||
td.pkgname {
|
||||
font-size: 140%;
|
||||
font-weight: bold;
|
||||
color: #005aa0;
|
||||
background: #ffffe0;
|
||||
}
|
||||
|
||||
td.pkgname table {
|
||||
border: none;
|
||||
border-spacing: 0px;
|
||||
}
|
||||
|
||||
td.pkgname table td {
|
||||
border: none;
|
||||
}
|
||||
|
||||
td.pkgname td.pkgname {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
td.reltype {
|
||||
font-weight: bold;
|
||||
color: #400000;
|
||||
}
|
||||
|
||||
td.date, span.date, span.svnrev {
|
||||
color: #400000;
|
||||
}
|
||||
|
||||
a:link { color: #0048b3; }
|
||||
a:visited { color: #002a6a; }
|
||||
a:hover { background: #ffffcd; }
|
||||
|
||||
span.relname {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
span.filename, span.command {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
span.md5 {
|
||||
font-family: monospace;
|
||||
color: #400000;
|
||||
}
|
||||
|
||||
.failurewarning {
|
||||
font-weight: bold;
|
||||
color: red;
|
||||
}
|
||||
|
||||
p.failurewarning {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
span.system {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover, a:visited:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
img {
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
.error-msg {
|
||||
color: red;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre.buildlog {
|
||||
border: 1px solid black;
|
||||
padding: 0.3em;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
div.buildlog {
|
||||
border: 1px solid black;
|
||||
padding: 0.3em;
|
||||
}
|
||||
|
||||
.multiLineMsg {
|
||||
padding: 0em;
|
||||
margin: 0em;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
ul.productList {
|
||||
list-style: none;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
ul.productList li {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.runningBuild {
|
||||
background-color: #ff3030;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.disabledBuild {
|
||||
background-color: #b0b0b0;
|
||||
}
|
||||
|
||||
.productDetails {
|
||||
display: none;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
margin-left: 3em;
|
||||
}
|
||||
|
||||
.template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.jobset {
|
||||
border: solid black 1px;
|
||||
-moz-border-radius: 1em;
|
||||
border-radius: 1em;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
div.jobset-edit {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
div.jobset-edit h3, div.jobset h3 {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
||||
div.help {
|
||||
border: solid black 1px;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
div.help pre {
|
||||
padding-left: 1.5em;
|
||||
color: #400000;
|
||||
}
|
||||
|
||||
|
||||
/* Sortable tables */
|
||||
|
||||
table.tablesorter {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
table.tablesorter thead tr .header {
|
||||
background-image: url(/static/js/tablesorter/themes/blue/bg.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center right;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
table.tablesorter thead tr .headerSortUp {
|
||||
background-image: url(/static/js/tablesorter/themes/blue/asc.gif);
|
||||
}
|
||||
|
||||
table.tablesorter thead tr .headerSortDown {
|
||||
background-image: url(/static/js/tablesorter/themes/blue/desc.gif);
|
||||
}
|
||||
|
||||
table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
|
||||
background-color: #ffe000;
|
||||
}
|
||||
|
||||
table.tablesorter thead tr th {
|
||||
padding-right: 1.5em;
|
||||
}
|
||||
|
||||
|
||||
/* Overriding tablesorter... */
|
||||
|
||||
th.releaseSetJobName {
|
||||
font-size: 60%;
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
|
||||
|
||||
/* Navbar */
|
||||
|
||||
#leftnavbar {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
width: 13em;
|
||||
border-right: 1px solid gray;
|
||||
}
|
||||
|
||||
#logo {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#logo img {
|
||||
width: 11em;
|
||||
border: 1px;
|
||||
}
|
||||
|
||||
#content {
|
||||
position: absolute;
|
||||
left: 13em;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 0em;
|
||||
}
|
||||
|
||||
#leftnavbar ul.menu {
|
||||
display: block;
|
||||
padding: 0 0 0 0;
|
||||
margin: 0 0 0 0;
|
||||
margin-left: 1em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
#leftnavbar ul.menu a {
|
||||
color: #005aa0;
|
||||
}
|
||||
|
||||
#leftnavbar ul.menu > li {
|
||||
list-style: none;
|
||||
margin: 0 0 0 0;
|
||||
padding: 0 0 0 0;
|
||||
margin-bottom: 1.5em;
|
||||
}
|
||||
|
||||
#leftnavbar ul.menu > li > div.title {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
border-width: 0px;
|
||||
border-bottom-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #c0c0c0;
|
||||
padding-bottom: 0.5em;
|
||||
}
|
||||
|
||||
#leftnavbar ul.submenu {
|
||||
padding: 0 0 0 0;
|
||||
margin-left: 0em;
|
||||
margin-right: 0em;
|
||||
}
|
||||
|
||||
#leftnavbar ul.submenu > li {
|
||||
font-size: 90%;
|
||||
list-style: none;
|
||||
border-width: 0px;
|
||||
border-bottom-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #c0c0c0;
|
||||
margin: 0 0 0 0;
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
|
||||
#leftnavbar ul.submenu > li > div.title {
|
||||
padding-left: 1.3em;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
background-image: url(/static/images/arrow-right.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0.3em center;
|
||||
}
|
||||
|
||||
#leftnavbar ul.submenu > li.active > div.title {
|
||||
background-image: url(/static/images/arrow-right-active.gif);
|
||||
background-color: #eef2ff;
|
||||
font-weight: bold;
|
||||
color: #606060;
|
||||
}
|
||||
|
||||
#leftnavbar ul.subsubmenu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#leftnavbar ul.subsubmenu > li {
|
||||
font-size: 90%;
|
||||
list-style: none;
|
||||
margin: 0 0 0 0;
|
||||
padding: 0 0 0 0;
|
||||
border-width: 0px;
|
||||
border-top-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #c0c0c0;
|
||||
}
|
||||
|
||||
#leftnavbar ul.subsubmenu > li > div.title {
|
||||
padding-left: 3.3em;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
background-image: url(/static/images/arrow-right.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 2.3em center;
|
||||
}
|
||||
|
||||
#leftnavbar ul.subsubmenu > li.active > div.title {
|
||||
background-image: url(/static/images/arrow-right-active.gif);
|
||||
background-color: #eef2ff;
|
||||
font-weight: bold;
|
||||
color: #606060;
|
||||
}
|
||||
|
||||
#leftnavbar ul.subsubsubmenu {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#leftnavbar ul.subsubsubmenu > li {
|
||||
font-size: 90%;
|
||||
list-style: none;
|
||||
margin: 0 0 0 0;
|
||||
padding: 0 0 0 0;
|
||||
border-width: 0px;
|
||||
border-top-width: 1px;
|
||||
border-style: solid;
|
||||
border-color: #c0c0c0;
|
||||
}
|
||||
|
||||
#leftnavbar ul.subsubsubmenu > li > div.title {
|
||||
padding-left: 5.3em;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
background-image: url(/static/images/arrow-right.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 4.3em center;
|
||||
}
|
||||
|
||||
#leftnavbar ul.subsubsubmenu > li.active > div.title {
|
||||
background-image: url(/static/images/arrow-right-active.gif);
|
||||
background-color: #eef2ff;
|
||||
font-weight: bold;
|
||||
color: #606060;
|
||||
}
|
||||
|
||||
#footer {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
|
||||
/* Editing */
|
||||
|
||||
input.string {
|
||||
font-family: sans-serif;
|
||||
font-size: 100%;
|
||||
background-color: #fffff0;
|
||||
width: 20em;
|
||||
}
|
||||
|
||||
input.shortString {
|
||||
width: 7em;
|
||||
}
|
||||
|
||||
select {
|
||||
background-color: #fffff0;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #f0f0e0;
|
||||
}
|
||||
|
||||
form.inline {
|
||||
display: inline;
|
||||
}
|
90
src/root/static/css/logfile.css
Normal file
@ -0,0 +1,90 @@
|
||||
ul.nesting, ul.toplevel {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ul.toplevel {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.line, .head {
|
||||
padding-top: 0em;
|
||||
}
|
||||
|
||||
ul.nesting li.line, ul.nesting li.lastline {
|
||||
position: relative;
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
ul.nesting li.line {
|
||||
padding-left: 2.0em;
|
||||
}
|
||||
|
||||
ul.nesting li.lastline {
|
||||
padding-left: 2.1em; /* for the 0.1em border-left in .lastline > .lineconn */
|
||||
}
|
||||
|
||||
li.line {
|
||||
border-left: 0.1em solid #6185a0;
|
||||
}
|
||||
|
||||
li.line > span.lineconn, li.lastline > span.lineconn {
|
||||
position: absolute;
|
||||
height: 0.65em;
|
||||
left: 0em;
|
||||
width: 1.5em;
|
||||
border-bottom: 0.1em solid #6185a0;
|
||||
}
|
||||
|
||||
li.lastline > span.lineconn {
|
||||
border-left: 0.1em solid #6185a0;
|
||||
}
|
||||
|
||||
|
||||
em.storeref {
|
||||
color: #500000;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
em.storeref:hover {
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
*.popup {
|
||||
display: none;
|
||||
/* background: url('http://losser.st-lab.cs.uu.nl/~mbravenb/menuback.png') repeat; */
|
||||
background: #ffffcd;
|
||||
border: solid #555555 1px;
|
||||
position: absolute;
|
||||
top: 0em;
|
||||
left: 0em;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
em.storeref:hover span.popup {
|
||||
display: inline;
|
||||
width: 40em;
|
||||
}
|
||||
|
||||
|
||||
.logTreeToggle {
|
||||
text-decoration: none;
|
||||
font-family: monospace;
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
.errorLine {
|
||||
color: #ff0000;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.prio3 {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
code {
|
||||
white-space: pre-wrap;
|
||||
}
|
BIN
src/root/static/images/arrow-right-active.gif
Normal file
After Width: | Height: | Size: 103 B |
BIN
src/root/static/images/arrow-right.gif
Normal file
After Width: | Height: | Size: 100 B |
BIN
src/root/static/images/debian.png
Normal file
After Width: | Height: | Size: 422 B |
BIN
src/root/static/images/document.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
src/root/static/images/failure.gif
Normal file
After Width: | Height: | Size: 233 B |
BIN
src/root/static/images/hydra.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
src/root/static/images/iso.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
src/root/static/images/nix-build.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
src/root/static/images/question-mark.png
Normal file
After Width: | Height: | Size: 586 B |
BIN
src/root/static/images/report.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
src/root/static/images/rpm-fedora.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
src/root/static/images/rpm.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
src/root/static/images/source-dist.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
src/root/static/images/success.gif
Normal file
After Width: | Height: | Size: 164 B |