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.
|
# If this is an aggregate job, then get its constituents.
|
||||||
my @constituents = $c->model('DB::Builds')->search(
|
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',
|
{ join => 'aggregateconstituents_constituents',
|
||||||
columns => ['id', 'job', 'finished', 'buildstatus'],
|
columns => ['id', 'job', 'finished', 'buildstatus'],
|
||||||
+select => ['aggregateconstituents_constituents.aggregate'],
|
+select => ['aggregateconstituents_constituents.aggregate'],
|
||||||
|
@ -51,11 +51,17 @@ sub overview : Chained('job') PathPart('') Args(0) {
|
||||||
my %constituentJobs;
|
my %constituentJobs;
|
||||||
foreach my $b (@constituents) {
|
foreach my $b (@constituents) {
|
||||||
my $jobName = $b->get_column('job');
|
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};
|
{ id => $b->id, finished => $b->finished, buildstatus => $b->buildstatus};
|
||||||
$constituentJobs{$jobName} = 1;
|
$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->{aggregates} = $aggregates;
|
||||||
$c->stash->{constituentJobs} = [sort (keys %constituentJobs)];
|
$c->stash->{constituentJobs} = [sort (keys %constituentJobs)];
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ BLOCK renderJobsetName %]
|
||||||
|
|
||||||
|
|
||||||
BLOCK renderJobName %]
|
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;
|
[% END;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,51 +28,34 @@
|
||||||
|
|
||||||
<div id="tabs-constituents" class="tab-pane">
|
<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>:
|
||||||
<thead>
|
its success or failure is determined entirely by the result of
|
||||||
<tr>
|
building its <em>constituent jobs</em>. The table below shows
|
||||||
<th>#</th>
|
the status of each constituent job for the [%
|
||||||
[% FOREACH j IN constituentJobs %]
|
aggregates.keys.size %] most recent builds of the
|
||||||
<th>[% HTML.escape(j) %]</th>
|
aggregate.</div>
|
||||||
[% 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>
|
|
||||||
|
|
||||||
<hr/>
|
|
||||||
|
|
||||||
<table class="table table-striped table-condensed">
|
[% aggs = aggregates.keys.nsort.reverse %]
|
||||||
|
<table class="table table-striped table-condensed table-header-rotated">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>#</th>
|
<th>Job</th>
|
||||||
[% FOREACH j IN constituentJobs %]
|
[% FOREACH agg IN aggs %]
|
||||||
<th>[% HTML.escape(j) %]</th>
|
<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 %]
|
[% END %]
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
[% FOREACH agg IN aggregates.keys.nsort.reverse %]
|
[% FOREACH j IN constituentJobs %]
|
||||||
<tr>
|
<tr>
|
||||||
<td><a class="row-link" href="[% c.uri_for('/build' agg) %]">[% agg %]</a></td>
|
<th style="width: 1em;">[% INCLUDE renderJobName project=project.name jobset=jobset.name job=j %]</th>
|
||||||
[% FOREACH j IN constituentJobs %]
|
[% FOREACH agg IN aggs %]
|
||||||
<td>
|
<td>
|
||||||
[% r = aggregates.$agg.$j; IF r.id %]
|
[% r = aggregates.$agg.constituents.$j; IF r.id %]
|
||||||
<a href="[% c.uri_for('/build' r.id) %]">
|
<a href="[% c.uri_for('/build' r.id) %]">
|
||||||
[% INCLUDE renderBuildStatusIcon size=16 build=r %]
|
[% INCLUDE renderBuildStatusIcon size=16 build=r %]
|
||||||
</a>
|
</a>
|
||||||
|
@ -84,7 +67,6 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
[% END %]
|
[% END %]
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
<!-- hydra.css must be included before bootstrap-responsive to
|
<!-- hydra.css must be included before bootstrap-responsive to
|
||||||
make the @media rule work. -->
|
make the @media rule work. -->
|
||||||
<link rel="stylesheet" href="/static/css/hydra.css" type="text/css" />
|
<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" />
|
<link href="/static/bootstrap/css/bootstrap-responsive.min.css" rel="stylesheet" />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -91,3 +91,7 @@ div.news-item:not(:first-child) {
|
||||||
td.nowrap {
|
td.nowrap {
|
||||||
white-space: 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