forked from lix-project/hydra
Transpose the aggregate constituents table
This way, it grows vertically rather than horizontally. Horizontal may be more "logical", but this is more practical.
This commit is contained in:
parent
7725038821
commit
7685596aa8
|
@ -40,7 +40,7 @@ sub overview : Chained('job') PathPart('') Args(0) {
|
|||
|
||||
# If this is an aggregate job, then get its constituents.
|
||||
my @constituents = $c->model('DB::Builds')->search(
|
||||
{ aggregate => { -in => $job->builds->search({}, { columns => ["id"], order_by => "id desc", rows => 10 })->as_query } },
|
||||
{ aggregate => { -in => $job->builds->search({}, { columns => ["id"], order_by => "id desc", rows => 15 })->as_query } },
|
||||
{ join => 'aggregateconstituents_constituents',
|
||||
columns => ['id', 'job', 'finished', 'buildstatus'],
|
||||
+select => ['aggregateconstituents_constituents.aggregate'],
|
||||
|
@ -51,11 +51,17 @@ sub overview : Chained('job') PathPart('') Args(0) {
|
|||
my %constituentJobs;
|
||||
foreach my $b (@constituents) {
|
||||
my $jobName = $b->get_column('job');
|
||||
$aggregates->{$b->get_column('aggregate')}->{$jobName} =
|
||||
$aggregates->{$b->get_column('aggregate')}->{constituents}->{$jobName} =
|
||||
{ id => $b->id, finished => $b->finished, buildstatus => $b->buildstatus};
|
||||
$constituentJobs{$jobName} = 1;
|
||||
}
|
||||
|
||||
foreach my $agg (keys %$aggregates) {
|
||||
# FIXME: could be done in one query.
|
||||
$aggregates->{$agg}->{build} =
|
||||
$c->model('DB::Builds')->find({id => $agg}, {columns => [@buildListColumns]}) or die;
|
||||
}
|
||||
|
||||
$c->stash->{aggregates} = $aggregates;
|
||||
$c->stash->{constituentJobs} = [sort (keys %constituentJobs)];
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ BLOCK renderJobsetName %]
|
|||
|
||||
|
||||
BLOCK renderJobName %]
|
||||
<a [% IF inRow %]class="row-link"[% END %] href="[% c.uri_for('/job' project jobset job) %]"><tt>[% job %]</tt></a>
|
||||
<a [% IF inRow %]class="row-link"[% END %] href="[% c.uri_for('/job' project jobset job) %]">[% job %]</a>
|
||||
[% END;
|
||||
|
||||
|
||||
|
|
|
@ -28,22 +28,34 @@
|
|||
|
||||
<div id="tabs-constituents" class="tab-pane">
|
||||
|
||||
<table class="table table-striped table-condensed">
|
||||
<div class="well well-small">This is an <em>aggregate job</em>:
|
||||
its success or failure is determined entirely by the result of
|
||||
building its <em>constituent jobs</em>. The table below shows
|
||||
the status of each constituent job for the [%
|
||||
aggregates.keys.size %] most recent builds of the
|
||||
aggregate.</div>
|
||||
|
||||
[% aggs = aggregates.keys.nsort.reverse %]
|
||||
<table class="table table-striped table-condensed table-header-rotated">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
[% FOREACH j IN constituentJobs %]
|
||||
<th>[% HTML.escape(j) %]</th>
|
||||
<th>Job</th>
|
||||
[% FOREACH agg IN aggs %]
|
||||
<th class="rotate-45">
|
||||
[% agg_ = aggregates.$agg %]
|
||||
<div><span class="[% agg_.build.finished == 0 ? "text-info" : (agg_.build.buildstatus == 0 ? "text-success" : "text-warning") %] override-link">
|
||||
<a href="[% c.uri_for('/build' agg) %]">[% agg %]</a>
|
||||
</span></div></th>
|
||||
[% END %]
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% FOREACH agg IN aggregates.keys.nsort.reverse %]
|
||||
[% FOREACH j IN constituentJobs %]
|
||||
<tr>
|
||||
<td><a class="row-link" href="[% c.uri_for('/build' agg) %]">[% agg %]</a></td>
|
||||
[% FOREACH j IN constituentJobs %]
|
||||
<td>
|
||||
[% r = aggregates.$agg.$j; IF r.id %]
|
||||
<th style="width: 1em;">[% INCLUDE renderJobName project=project.name jobset=jobset.name job=j %]</th>
|
||||
[% FOREACH agg IN aggs %]
|
||||
<td>
|
||||
[% r = aggregates.$agg.constituents.$j; IF r.id %]
|
||||
<a href="[% c.uri_for('/build' r.id) %]">
|
||||
[% INCLUDE renderBuildStatusIcon size=16 build=r %]
|
||||
</a>
|
||||
|
@ -55,36 +67,6 @@
|
|||
</tbody>
|
||||
</table>
|
||||
|
||||
<hr/>
|
||||
|
||||
<table class="table table-striped table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
[% FOREACH j IN constituentJobs %]
|
||||
<th>[% HTML.escape(j) %]</th>
|
||||
[% END %]
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[% FOREACH agg IN aggregates.keys.nsort.reverse %]
|
||||
<tr>
|
||||
<td><a class="row-link" href="[% c.uri_for('/build' agg) %]">[% agg %]</a></td>
|
||||
[% FOREACH j IN constituentJobs %]
|
||||
<td>
|
||||
[% r = aggregates.$agg.$j; IF r.id %]
|
||||
<a href="[% c.uri_for('/build' r.id) %]">
|
||||
[% INCLUDE renderBuildStatusIcon size=16 build=r %]
|
||||
</a>
|
||||
[% END %]
|
||||
</td>
|
||||
[% END %]
|
||||
</tr>
|
||||
[% END %]
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
[% END %]
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
<!-- hydra.css must be included before bootstrap-responsive to
|
||||
make the @media rule work. -->
|
||||
<link rel="stylesheet" href="/static/css/hydra.css" type="text/css" />
|
||||
<link rel="stylesheet" href="/static/css/rotated-th.css" type="text/css" />
|
||||
<link href="/static/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet" />
|
||||
|
||||
<style>
|
||||
|
|
|
@ -91,3 +91,7 @@ div.news-item:not(:first-child) {
|
|||
td.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.override-link a {
|
||||
color: inherit;
|
||||
}
|
||||
|
|
52
src/root/static/css/rotated-th.css
Normal file
52
src/root/static/css/rotated-th.css
Normal file
|
@ -0,0 +1,52 @@
|
|||
/* Rotated table headers, borrowed from http://jimmybonney.com/articles/column_header_rotation_css */
|
||||
|
||||
.tab-content {
|
||||
margin-right: 5em;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
td.centered {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.table-header-rotated th.rotate-45{
|
||||
height: 80px;
|
||||
width: 40px;
|
||||
min-width: 40px;
|
||||
max-width: 40px;
|
||||
position: relative;
|
||||
vertical-align: bottom;
|
||||
padding: 0;
|
||||
font-size: 100%;
|
||||
line-height: 0.9;
|
||||
}
|
||||
|
||||
.table-header-rotated th.rotate-45 > div {
|
||||
position: relative;
|
||||
top: 0px;
|
||||
left: 40px; /* 80 * tan(45) / 2 = 40 where 80 is the height on the cell and 45 is the transform angle*/
|
||||
height: 100%;
|
||||
-ms-transform:skew(-45deg,0deg);
|
||||
-moz-transform:skew(-45deg,0deg);
|
||||
-webkit-transform:skew(-45deg,0deg);
|
||||
-o-transform:skew(-45deg,0deg);
|
||||
transform:skew(-45deg,0deg);
|
||||
overflow: hidden;
|
||||
border-left: 1px solid #dddddd;
|
||||
}
|
||||
|
||||
.table-header-rotated th.rotate-45 span {
|
||||
-ms-transform:skew(45deg,0deg) rotate(315deg);
|
||||
-moz-transform:skew(45deg,0deg) rotate(315deg);
|
||||
-webkit-transform:skew(45deg,0deg) rotate(315deg);
|
||||
-o-transform:skew(45deg,0deg) rotate(315deg);
|
||||
transform:skew(45deg,0deg) rotate(315deg);
|
||||
position: absolute;
|
||||
bottom: 30px; /* 40 cos(45) = 28 with an additional 2px margin*/
|
||||
left: -25px; /*Because it looked good, but there is probably a mathematical link here as well*/
|
||||
display: inline-block;
|
||||
// width: 100%;
|
||||
width: 85px; /* 80 / cos(45) - 40 cos (45) = 85 where 80 is the height of the cell, 40 the width of the cell and 45 the transform angle*/
|
||||
text-align: left;
|
||||
// white-space: nowrap; /*whether to display in one line or not*/
|
||||
}
|
Loading…
Reference in a new issue