summaryrefslogtreecommitdiffstats
path: root/non-puppet/qtmetrics2
diff options
context:
space:
mode:
authorJuha Sippola <juhasippola@outlook.com>2015-08-05 09:58:23 +0300
committerTony Sarajärvi <tony.sarajarvi@theqtcompany.com>2015-09-16 07:33:38 +0000
commitaff63b3f963ac69f8bce856f1ea88e1834e7df0b (patch)
tree33890bfa4e51258b53a13f5e49c10e3640bc645e /non-puppet/qtmetrics2
parentf6371c61dffb03a2d3d5e1b8c6d3e3086f9f5afc (diff)
Qt Metrics 2 (v0.13): Configuration page
New configuration page. Added configuration links to related project pages. New routes for the configuration page. Build project (Qt5) view shows all data while the testset project view shows only the testset results (failures only for usability and performance reasons). Change-Id: I833c9481d16f26082570b8b1664ddfe452476f67 Reviewed-by: Tony Sarajärvi <tony.sarajarvi@theqtcompany.com>
Diffstat (limited to 'non-puppet/qtmetrics2')
-rw-r--r--non-puppet/qtmetrics2/index.php135
-rw-r--r--non-puppet/qtmetrics2/templates/about.html6
-rw-r--r--non-puppet/qtmetrics2/templates/build_project.html57
-rw-r--r--non-puppet/qtmetrics2/templates/conf.html576
-rw-r--r--non-puppet/qtmetrics2/templates/testset_project.html7
5 files changed, 699 insertions, 82 deletions
diff --git a/non-puppet/qtmetrics2/index.php b/non-puppet/qtmetrics2/index.php
index e183991..704960f 100644
--- a/non-puppet/qtmetrics2/index.php
+++ b/non-puppet/qtmetrics2/index.php
@@ -34,8 +34,8 @@
/**
* Qt Metrics API
- * @version 0.8
- * @since 01-07-2015
+ * @version 0.9
+ * @since 21-07-2015
* @author Juha Sippola
*/
@@ -60,11 +60,11 @@ $app = new Slim\Slim(array(
$app->get('/', function() use($app)
{
$ini = Factory::conf();
- $platformRoute = str_replace('/:targetOs', '', Slim\Slim::getInstance()->urlFor('buildproject_platform'));
+ $buildProjectPlatformRoute = str_replace('/:targetOs', '', Slim\Slim::getInstance()->urlFor('buildproject_platform'));
$app->render('home.html', array(
'root' => Slim\Slim::getInstance()->urlFor('root'),
'overviewRoute' => Slim\Slim::getInstance()->urlFor('overview'),
- 'platformRoute' => $platformRoute,
+ 'platformRoute' => $buildProjectPlatformRoute,
'topRoute' => Slim\Slim::getInstance()->urlFor('top'),
'flakyRoute' => Slim\Slim::getInstance()->urlFor('flaky'),
'refreshed' => Factory::db()->getDbRefreshed() . ' (GMT)',
@@ -115,19 +115,18 @@ $app->get('/buildproject', function() use($app)
array('name' => 'home', 'link' => Slim\Slim::getInstance()->urlFor('root')),
array('name' => 'overview', 'link' => Slim\Slim::getInstance()->urlFor('overview'))
);
- $platformRoute = str_replace('/:targetOs', '', Slim\Slim::getInstance()->urlFor('buildproject_platform'));
- $confRoute = str_replace('/:conf', '', Slim\Slim::getInstance()->urlFor('buildproject_conf'));
+ $buildProjectPlatformRoute = str_replace('/:targetOs', '', Slim\Slim::getInstance()->urlFor('buildproject_platform'));
+ $confRoute = str_replace('/:conf', '', Slim\Slim::getInstance()->urlFor('conf'));
$app->render('build_project.html', array(
'root' => Slim\Slim::getInstance()->urlFor('root'),
'breadcrumb' => $breadcrumb,
- 'platformRoute' => $platformRoute,
+ 'buildPlatformRoute' => $buildProjectPlatformRoute,
'confRoute' => $confRoute,
'refreshed' => Factory::db()->getDbRefreshed() . ' (GMT)',
'masterProject' => $ini['master_build_project'],
'masterState' => $ini['master_build_state'],
'platforms' => Factory::db()->getTargetPlatformOs(),
'targetOs' => '',
- 'conf' => '',
'latestProjectRuns' => Factory::db()->getLatestProjectBranchBuildResults(
$ini['master_build_project'],
$ini['master_build_state']),
@@ -161,19 +160,18 @@ $app->get('/buildproject/platform/:targetOs', function($targetOs) use($app)
array('name' => 'overview', 'link' => Slim\Slim::getInstance()->urlFor('overview')),
array('name' => $ini['master_build_project'], 'link' => $buildProjectRoute)
);
- $platformRoute = str_replace('/:targetOs', '', Slim\Slim::getInstance()->urlFor('buildproject_platform'));
- $confRoute = str_replace('/:conf', '', Slim\Slim::getInstance()->urlFor('buildproject_conf'));
+ $buildProjectPlatformRoute = str_replace('/:targetOs', '', Slim\Slim::getInstance()->urlFor('buildproject_platform'));
+ $confRoute = str_replace('/:conf', '', Slim\Slim::getInstance()->urlFor('conf'));
$app->render('build_project.html', array(
'root' => Slim\Slim::getInstance()->urlFor('root'),
'breadcrumb' => $breadcrumb,
- 'platformRoute' => $platformRoute,
+ 'buildPlatformRoute' => $buildProjectPlatformRoute,
'confRoute' => $confRoute,
'refreshed' => Factory::db()->getDbRefreshed() . ' (GMT)',
'masterProject' => $ini['master_build_project'],
'masterState' => $ini['master_build_state'],
'platforms' => Factory::db()->getTargetPlatformOs(),
'targetOs' => $targetOs,
- 'conf' => '',
'latestProjectRuns' => Factory::db()->getLatestProjectBranchBuildResults(
$ini['master_build_project'],
$ini['master_build_state']),
@@ -193,11 +191,45 @@ $app->get('/buildproject/platform/:targetOs', function($targetOs) use($app)
})->name('buildproject_platform');
/**
- * UI route: /buildproject/:project/conf (GET)
- * Similar to /buildproject but filtered with conf
+ * UI route: /testsetproject (GET)
+ */
+
+$app->get('/testsetproject/:project', function($project) use($app)
+{
+ $project = strip_tags($project);
+ $ini = Factory::conf();
+ $breadcrumb = array(
+ array('name' => 'home', 'link' => Slim\Slim::getInstance()->urlFor('root')),
+ array('name' => 'overview', 'link' => Slim\Slim::getInstance()->urlFor('overview'))
+ );
+ $confRoute = str_replace('/:conf', '', Slim\Slim::getInstance()->urlFor('conf'));
+ $app->render('testset_project.html', array(
+ 'root' => Slim\Slim::getInstance()->urlFor('root'),
+ 'breadcrumb' => $breadcrumb,
+ 'confRoute' => $confRoute,
+ 'refreshed' => Factory::db()->getDbRefreshed() . ' (GMT)',
+ 'masterProject' => $ini['master_build_project'],
+ 'masterState' => $ini['master_build_state'],
+ 'project' => $project,
+ 'latestTestsetRuns' => Factory::db()->getLatestTestsetProjectBranchTestsetResults(
+ $project,
+ $ini['master_build_project'],
+ $ini['master_build_state']),
+ 'projectBuilds' => Factory::db()->getProjectBuildsByBranch(
+ $ini['master_build_project'],
+ $ini['master_build_state']),
+ 'confBuilds' => Factory::db()->getTestsetProjectResultsByBranchConf(
+ $project,
+ $ini['master_build_project'],
+ $ini['master_build_state'])
+ ));
+})->name('testsetproject');
+
+/**
+ * UI route: /conf/:conf (GET)
*/
-$app->get('/buildproject/conf/:conf', function($conf) use($app)
+$app->get('/conf/:conf', function($conf) use($app)
{
$conf = strip_tags($conf);
$ini = Factory::conf();
@@ -207,69 +239,82 @@ $app->get('/buildproject/conf/:conf', function($conf) use($app)
array('name' => 'overview', 'link' => Slim\Slim::getInstance()->urlFor('overview')),
array('name' => $ini['master_build_project'], 'link' => $buildProjectRoute)
);
- $platformRoute = str_replace('/:targetOs', '', Slim\Slim::getInstance()->urlFor('buildproject_platform'));
- $confRoute = str_replace('/:conf', '', Slim\Slim::getInstance()->urlFor('buildproject_conf'));
- $app->render('build_project.html', array(
+ $testsetRoute = str_replace('/:testset/:project', '', Slim\Slim::getInstance()->urlFor('testset'));
+ $testsetProjectRoute = str_replace('/:project', '', Slim\Slim::getInstance()->urlFor('testsetproject'));
+ $app->render('conf.html', array(
'root' => Slim\Slim::getInstance()->urlFor('root'),
'breadcrumb' => $breadcrumb,
- 'platformRoute' => $platformRoute,
- 'confRoute' => $confRoute,
+ 'testsetRoute' => $testsetRoute,
+ 'testsetProjectRoute' => $testsetProjectRoute,
'refreshed' => Factory::db()->getDbRefreshed() . ' (GMT)',
'masterProject' => $ini['master_build_project'],
'masterState' => $ini['master_build_state'],
- 'platforms' => Factory::db()->getTargetPlatformOs(),
- 'targetOs' => '',
- 'conf' => $conf,
- 'latestProjectRuns' => Factory::db()->getLatestProjectBranchBuildResults(
- $ini['master_build_project'],
- $ini['master_build_state']),
'projectBuilds' => Factory::db()->getProjectBuildsByBranch(
$ini['master_build_project'],
$ini['master_build_state']),
- 'project' => Factory::createProject(
+ 'testsetProject' => '',
+ 'latestConfRuns' => Factory::db()->getLatestConfBranchBuildResults(
+ $conf,
$ini['master_build_project'],
+ $ini['master_build_state']),
+ 'conf' => Factory::createConf(
+ $conf,
$ini['master_build_project'],
$ini['master_build_state']), // managed as object
'confRuns' => Factory::createConfRuns(
$ini['master_build_project'],
$ini['master_build_state'],
'',
- $conf) // managed as objects
+ $conf), // managed as objects
+ 'testsetRuns' => Factory::createTestsetRunsInConf(
+ $conf,
+ '',
+ $ini['master_build_project'],
+ $ini['master_build_state']) // managed as objects
));
-})->name('buildproject_conf');
+})->name('conf');
/**
- * UI route: /testsetproject (GET)
+ * UI route: /conf/:conf/:testsetproject (GET)
*/
-$app->get('/testsetproject/:project', function($project) use($app)
+$app->get('/conf/:conf/:testsetproject', function($conf, $testsetProject) use($app)
{
- $project = strip_tags($project);
+ $conf = strip_tags($conf);
+ $testsetProject = strip_tags($testsetProject);
$ini = Factory::conf();
+ $testsetProjectRoute = str_replace('/:project', '', Slim\Slim::getInstance()->urlFor('testsetproject'));
$breadcrumb = array(
array('name' => 'home', 'link' => Slim\Slim::getInstance()->urlFor('root')),
- array('name' => 'overview', 'link' => Slim\Slim::getInstance()->urlFor('overview'))
+ array('name' => 'overview', 'link' => Slim\Slim::getInstance()->urlFor('overview')),
+ array('name' => $testsetProject, 'link' => $testsetProjectRoute . '/' . $testsetProject)
);
- $app->render('testset_project.html', array(
+ $testsetRoute = str_replace('/:testset/:project', '', Slim\Slim::getInstance()->urlFor('testset'));
+ $app->render('conf.html', array(
'root' => Slim\Slim::getInstance()->urlFor('root'),
'breadcrumb' => $breadcrumb,
+ 'testsetRoute' => $testsetRoute,
+ 'testsetProjectRoute' => $testsetProjectRoute,
'refreshed' => Factory::db()->getDbRefreshed() . ' (GMT)',
'masterProject' => $ini['master_build_project'],
'masterState' => $ini['master_build_state'],
- 'project' => $project,
- 'latestTestsetRuns' => Factory::db()->getLatestTestsetProjectBranchTestsetResults(
- $project,
- $ini['master_build_project'],
- $ini['master_build_state']),
'projectBuilds' => Factory::db()->getProjectBuildsByBranch(
$ini['master_build_project'],
$ini['master_build_state']),
- 'confBuilds' => Factory::db()->getTestsetProjectResultsByBranchConf(
- $project,
+ 'testsetProject' => $testsetProject,
+ 'latestConfRuns' => null, // not used
+ 'conf' => Factory::createConf(
+ $conf,
$ini['master_build_project'],
- $ini['master_build_state'])
+ $ini['master_build_state']), // managed as object
+ 'confRuns' => null, // not used
+ 'testsetRuns' => Factory::createTestsetRunsInConf(
+ $conf,
+ $testsetProject,
+ $ini['master_build_project'],
+ $ini['master_build_state']) // managed as objects
));
-})->name('testsetproject');
+})->name('conf_testsetproject');
/**
* UI route: /test/top (GET)
@@ -296,7 +341,7 @@ $app->get('/test/top', function() use($app)
'testsets' => Factory::createTestsets(
Factory::LIST_FAILURES,
$ini['master_build_project'],
- $ini['master_build_state']) // managed as objects
+ $ini['master_build_state']) // managed as objects
));
})->name('top');
@@ -323,7 +368,7 @@ $app->get('/test/flaky', function() use($app)
'testsets' => Factory::createTestsets(
Factory::LIST_FLAKY,
null,
- null) // managed as objects
+ null) // managed as objects
));
})->name('flaky');
diff --git a/non-puppet/qtmetrics2/templates/about.html b/non-puppet/qtmetrics2/templates/about.html
index 245bf8f..4ec8095 100644
--- a/non-puppet/qtmetrics2/templates/about.html
+++ b/non-puppet/qtmetrics2/templates/about.html
@@ -34,8 +34,8 @@
/**
* About window content
- * @version 0.12.2
- * @since 10-07-2015
+ * @version 0.13
+ * @since 21-07-2015
* @author Juha Sippola
*/
@@ -44,4 +44,4 @@
<p>This is Qt Metrics revision 2 with redesigned UI and database.</p>
<p>These pages are still <strong>under construction</strong> and therefore the views and functionality is limited.</p>
<p>See the <a href="https://wiki.qt.io/Qt_Metrics_2_Backlog" target="_blank">backlog</a> for development items currently identified or in progress.</p>
-<p><small>Version 0.12.2 (10-Jul-2015)</small></p>
+<p><small>Version 0.13 (21-Jul-2015)</small></p>
diff --git a/non-puppet/qtmetrics2/templates/build_project.html b/non-puppet/qtmetrics2/templates/build_project.html
index c2fe11c..e4c841e 100644
--- a/non-puppet/qtmetrics2/templates/build_project.html
+++ b/non-puppet/qtmetrics2/templates/build_project.html
@@ -34,8 +34,8 @@
/**
* Build project page
- * @version 0.3
- * @since 10-07-2015
+ * @version 0.4
+ * @since 20-07-2015
* @author Juha Sippola
*/
@@ -43,9 +43,6 @@
{% include "header.html" %}
-{# Failed/passed bar area size in px #}
-{% set BAR_AREA = 120 %}
-
{# project as Project object
/**
* @var Project[] project
@@ -62,12 +59,10 @@
{% for link in breadcrumb %}
<li><a href="{{ link.link }}">{{ link.name }}</a></li>
{% endfor %}
-{% if targetOs == '' and conf == '' %}
+{% if targetOs == '' %}
<li class="active">{{ project.getName }}</li>
-{% elseif targetOs != '' %}
+{% else %}
<li class="active">{{ targetOs }}</li>
-{% elseif conf != '' %}
-<li class="active">{{ conf }}</li>
{% endif %}
</ol>
@@ -102,15 +97,9 @@
{% set buttonStyle = 'btn-default' %}
{% endif %}
<div class="btn-group">
-<a class="btn {{ buttonStyle }} btn-xs" href="{{ platformRoute }}/{{ platform.os }}" role="button">{{ platform.os }}</a>
+<a class="btn {{ buttonStyle }} btn-xs" href="{{ buildPlatformRoute }}/{{ platform.os }}" role="button">{{ platform.os }}</a>
</div>
{% endfor %}
-{% if conf != '' %}
-{% set link = confRoute ~ '/' ~ conf|url_encode %}
-<div class="btn-group">
-<a class="btn btn-info btn-xs" href="{{ link }}" role="button">{{ conf }}</a>
-</div>
-{% endif %}
</div>
<hr>
@@ -126,11 +115,16 @@ and the <strong>branch</strong> results across all configurations (both show fai
in one or in several builds).</li>
<li><strong>Results in Branches</strong> shows the {{ project.getName }} run results by branch
and their configuration on <strong>{{ masterProject }} {{ masterState }}</strong> builds
-(<span class="glyphicon glyphicon-ok green"></span> = {{ constant('ConfRun::RESULT_SUCCESS') }},
-<span class="glyphicon glyphicon-ok-sign green"></span> = {{ constant('ConfRun::RESULT_SUCCESS') }} as forcesuccess,
+<ul>
+<li>flags: <span class="label label-success">f</span> = forcesuccess and
+<span class="label label-default">i</span> = insignificant flag set for the configuration on the latest build</li>
+<li>results: <span class="glyphicon glyphicon-ok green"></span> = {{ constant('ConfRun::RESULT_SUCCESS') }},
+<span class="glyphicon glyphicon-ok-sign green"></span> = {{ constant('ConfRun::RESULT_SUCCESS') }} as forcesucces,
<span class="glyphicon glyphicon-remove red"></span> = {{ constant('ConfRun::RESULT_FAILURE') }},
-<span class="glyphicon glyphicon-ban-circle gray"></span> = {{ constant('ConfRun::RESULT_UNDEF') }});
-details on the runs are available as tooltip on result icon.</li>
+<span class="glyphicon glyphicon-ban-circle gray"></span> = {{ constant('ConfRun::RESULT_ABORTED') }}/{{ constant('ConfRun::RESULT_UNDEF') }}</li>
+</ul>
+</li>
+<li>Details on the runs are available as tooltip on result icon</li>
</ul>
</div>
</div>
@@ -246,7 +240,8 @@ title="<table>
<table class="table table-striped">
<thead>
<tr>
-<th class="bold rightBorder">{{ project.getName }}</th>
+<th class="bold">{{ project.getName }}</th>
+<th class="bold rightBorder">flags</th>
{% for key, buildKey in buildKeys %}
<th class="center">
{% if buildKey|length > 6 %}
@@ -278,17 +273,17 @@ title="<table>
</tr>
{% endif %}
<tr>
-{% if conf == '' %}
-{% set link = confRoute ~ '/' ~ run.getName|url_encode %}
-{% set tooltip = 'click to filter this configuration' %}
-<td class="rightBorder">
-<a href="{{ link }}"><small><span data-toggle="tooltip" data-placement="top" title="{{ tooltip }}">{{ run.getName }}</span></small></a>
-</td>
-{% else %}
-<td class="rightBorder">
-<small>{{ run.getName }}</small>
-</td>
+{% set link = confRoute ~ '/' ~ run.getName|url_encode %}
+<td><a href="{{ link }}"><small>{{ run.getName }}</small></a></td>
+{# Flags for the latest build #}
+<td class="center rightBorder">
+{% if run.getForcesuccess %}
+<span class="label label-success">f</span>
{% endif %}
+{% if run.getInsignificant %}
+<span class="label label-default">i</span>
+{% endif %}
+</td>
{% set buildKeyIndexPrinted = -1 %}
{% endif %}
diff --git a/non-puppet/qtmetrics2/templates/conf.html b/non-puppet/qtmetrics2/templates/conf.html
new file mode 100644
index 0000000..3908be0
--- /dev/null
+++ b/non-puppet/qtmetrics2/templates/conf.html
@@ -0,0 +1,576 @@
+{#
+#############################################################################
+##
+## Copyright (C) 2015 The Qt Company Ltd.
+## Contact: http://www.qt.io/licensing/
+##
+## This file is part of the Quality Assurance module of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL21$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see http://www.qt.io/terms-conditions. For further
+## information use the contact form at http://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 2.1 or version 3 as published by the Free
+## Software Foundation and appearing in the file LICENSE.LGPLv21 and
+## LICENSE.LGPLv3 included in the packaging of this file. Please review the
+## following information to ensure the GNU Lesser General Public License
+## requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## As a special exception, The Qt Company gives you certain additional
+## rights. These rights are described in The Qt Company LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+/**
+ * Configuration page
+ * @version 0.1
+ * @since 21-07-2015
+ * @author Juha Sippola
+ */
+
+#}
+
+{% include "header.html" %}
+
+{# conf as Conf object
+/**
+ * @var Conf[] confs
+ */
+#}
+
+{# confRuns as ConfRun objects
+/**
+ * @var ConfRun[] confRuns
+ */
+#}
+
+{# testsetRuns as TestsetRun objects
+/**
+ * @var TestsetRun[] testsetRuns
+ */
+#}
+
+<ol class="breadcrumb">
+{% for link in breadcrumb %}
+<li><a href="{{ link.link }}">{{ link.name }}</a></li>
+{% endfor %}
+<li class="active">{{ conf.getName }}</li>
+</ol>
+
+<div class="container-fluid">
+<div class="row">
+
+<div class="col-sm-12 col-md-12 main">
+
+{##### Title #####}
+
+<h1 class="page-header">
+{{ conf.getName }}<br>
+<button type="button" class="btn btn-xs btn-info" data-toggle="collapse" data-target="#info" aria-expanded="false" aria-controls="info">
+<span class="glyphicon glyphicon-info-sign"></span>
+</button>
+<small>{{ refreshed }}</small>
+</h1>
+
+{##### Info well #####}
+
+<div class="collapse" id="info">
+<div class="well infoWell">
+{% if testsetProject == '' %}
+<span class="glyphicon glyphicon-info-sign"></span> <strong>Configuration</strong> (for build project <strong>{{ masterProject }}</strong>)<br>
+{% else %}
+<span class="glyphicon glyphicon-info-sign"></span> <strong>Configuration</strong> (for testset project <strong>{{ testsetProject }}</strong>)<br>
+{% endif %}
+<ul>
+{% if testsetProject == '' %}
+<li>In <strong>Latest Status</strong>, the <strong>latest result</strong> shows the overall configuration
+status based on the latest <strong>{{ masterProject }} {{ masterState }}</strong> builds across all branches,
+and the <strong>branch</strong> results in each branch (both show failed if failed in one or in several builds).</li>
+{% endif %}
+{% if testsetProject == '' %}
+<li><strong>Build Results in Branches</strong> shows the results of {{ conf.getName }} builds by branch on
+<strong>{{ masterProject }} {{ masterState }}</strong> builds
+<ul>
+<li>flags: <span class="label label-success">f</span> = forcesuccess and
+<span class="label label-default">i</span> = insignificant flag set for the configuration on the latest build</li>
+<li>results: <span class="glyphicon glyphicon-ok green"></span> = {{ constant('ConfRun::RESULT_SUCCESS') }},
+<span class="glyphicon glyphicon-ok-sign green"></span> = {{ constant('ConfRun::RESULT_SUCCESS') }} as forcesucces,
+<span class="glyphicon glyphicon-remove red"></span> = {{ constant('ConfRun::RESULT_FAILURE') }},
+<span class="glyphicon glyphicon-ban-circle gray"></span> = {{ constant('ConfRun::RESULT_ABORTED') }}/{{ constant('ConfRun::RESULT_UNDEF') }}</li>
+</ul>
+</li>
+{% endif %}
+<li><strong>Testset Results in Branches</strong> shows the testset <strong>failures</strong> in {{ conf.getName }}
+by branch on <strong>{{ masterProject }} {{ masterState }}</strong> builds
+<ul>
+<li>flags: <span class="label label-default">i</span> = insignificant flag set for the testset on the latest build</li>
+<li>results: <span class="glyphicon glyphicon-remove red"></span> = {{ constant('TestsetRun::RESULT_FAILURE') }}</li>
+</ul>
+</li>
+<li>Details on the runs are available as tooltip on result icon</li>
+</ul>
+</div>
+</div>
+
+{##### Latest Status #####}
+
+{# Check if any runs available #}
+{% set latestRunsAvailable = 0 %}
+{% for run in latestConfRuns %}
+{% set latestRunsAvailable = 1 %}
+{% endfor %}
+
+{% if latestRunsAvailable %}
+
+<div class="panel panel-primary">
+<div class="panel-heading">
+<h4 class="panel-title bold">Latest Status</h4>
+</div>
+<div class="panel-body">
+<div class="table-responsive">
+<table class="table table-striped">
+<thead>
+<tr>
+<th>configuration</th>
+<th class="rightBorder">latest result</th>
+{% for branch in latestConfRuns %}
+<th class="center">{{ branch.name }}</th>
+{% endfor %}
+</tr>
+</thead>
+<tbody>
+<tr>
+{# Conf name #}
+<td>{{ conf.getName }}</td>
+
+{# Conf status according to the latest build results #}
+{% if conf.getStatus == constant('ConfRun::RESULT_SUCCESS') %}
+{% set resultIcon = 'glyphicon glyphicon-ok green' %}
+{% elseif conf.getStatus == constant('ConfRun::RESULT_FAILURE') %}
+{% set resultIcon = 'glyphicon glyphicon-remove red' %}
+{% else %}
+{% set resultIcon = 'glyphicon glyphicon-ban-circle gray' %}
+{% endif %}
+<td class="rightBorder"><span class="spaceHorizontal {{ resultIcon }}"></span>{{ conf.getStatus }}</td>
+
+{# Result (by branch) #}
+{% set flagIcon = 'glyphicon glyphicon-exclamation-sign' %}
+{% for run in latestConfRuns %}
+{% set forcesuccess = '' %}
+{% if run.result == constant('ConfRun::RESULT_SUCCESS') %}
+{% if not run.forcesuccess %}
+{# - success #}
+{% set resultIcon = 'glyphicon glyphicon-ok green' %}
+{% else %}
+{# - success - forcesuccess #}
+{% set resultIcon = 'glyphicon glyphicon-ok-sign green' %}
+{% set forcesuccess = ' (as forcesuccess)' %}
+{% endif %}
+{% elseif run.result == constant('ConfRun::RESULT_FAILURE') %}
+{# - failure #}
+{% set resultIcon = 'glyphicon glyphicon-remove red' %}
+{% else %}
+{# - aborted / undefined #}
+{% set resultIcon = 'glyphicon glyphicon-ban-circle gray' %}
+{% endif %}
+<td class="center">
+<span class="spaceHorizontal {{ resultIcon }} clickOnTouch" data-toggle="tooltip" data-placement="top" data-html="true"
+title="<table>
+<tr><th>Branch: </th><td>{{ run.name }}</td></tr>
+<tr><th>Build key: </th><td>{{ run.buildKey }}</td></tr>
+<tr><th>Timestamp: </th><td>{{ run.timestamp }}</td></tr>
+<tr><th>Result: </th><td>{{ run.result }} {{ forcesuccess }}</td></tr>
+<tr><th>Forcesuccess: </th><td>{% if run.forcesuccess %}yes{% else %}no{% endif %}</td></tr>
+<tr><th>Insignificant: </th><td>{% if run.insignificant %}yes{% else %}no{% endif %}</td></tr>
+<tr><th>Duration: </td><td>{{ run.duration}}</td></tr></table>"></span>
+{% if run.forcesuccess %}
+<span class="label label-success clickOnTouch" data-toggle="tooltip" data-placement="top" data-html="true"
+title="forcesuccess">f</span>
+{% endif %}
+{% if run.insignificant %}
+<span class="label label-default clickOnTouch" data-toggle="tooltip" data-placement="top" data-html="true"
+title="insignificant">i</span>
+{% endif %}
+</td>
+{% endfor %}{# run #}
+</tr>
+</tbody>
+</table>
+</div> {# .table-responsive #}
+</div> {# .panel-body #}
+</div> {# .panel... #}
+{% endif %}{# latestRunsAvailable #}
+
+{##### Build Results in Branches #####}
+
+{# Get branches #}
+{% set branches = [] %}
+{% for run in projectBuilds %}
+{% if run.branch not in branches %}
+{% set branches = branches|merge([run.branch]) %}
+{% endif %}
+{% endfor %}
+
+{# Check if any runs available #}
+{% set confRunsAvailable = 0 %}
+{% for run in confRuns %}
+{% set confRunsAvailable = 1 %}
+{% endfor %}
+
+{% if confRunsAvailable %}
+
+<div class="panel panel-primary">
+<div class="panel-heading">
+<h4 class="panel-title bold">Build Results in Branches</h4>
+</div>
+</div>
+
+{# Loop all the branches #}
+{% for branch in branches %}
+
+{# Get all build keys #}
+{% set buildKey = '' %}
+{% set buildKeys = [] %}
+{% set dates = [] %}
+{% for run in projectBuilds %}
+{% if run.branch == branch %}
+{% if buildKey != run.buildKey %}
+{% set buildKey = run.buildKey %}
+{% set buildKeys = buildKeys|merge([run.buildKey]) %}
+{% set dates = dates|merge([run.timestamp]) %}
+{% endif %}
+{% endif %}
+{% endfor %}
+
+{# Check if conf run for this branch #}
+{% set confBranch = 0 %}
+{% for run in confRuns if run.getBranchName == branch %}
+{% set confBranch = 1 %}
+{% endfor %}
+
+{# Show branch if testset run for it #}
+{% if confBranch %}
+<div class="panel panel-info">
+<div class="panel-heading">
+<h4 class="panel-title bold">{{ branch }}</h4>
+</div>
+<div class="panel-body">
+<div class="table-responsive">
+<table class="table table-striped">
+<thead>
+<tr>
+<th class="bold">configuration</th>
+<th class="bold rightBorder">flags</th>
+{% for key, buildKey in buildKeys %}
+<th class="center">
+{% if buildKey|length > 6 %}
+<span class="clickOnTouch" data-toggle="tooltip" data-placement="top" title="{{ buildKey }}">{{ buildKey|slice(0, 4) }}...</span><br>
+{% else %}
+{{ buildKey }}<br>
+{% endif %}
+<span class="gray"><small>{{ dates[key]|date("m-d") }}</small></span>
+</th>
+{% endfor %}
+</tr>
+</thead>
+<tbody>
+{% set prevRowName = '' %}
+{% set buildKeyIndexPrinted = -1 %}
+{% set buildKeyFound = 0 %}
+{% for run in confRuns if run.getBranchName == branch %}
+
+{# New row for each conf #}
+{% if prevRowName != run.getName %}
+{# Close previous row #}
+{% if prevRowName != '' %}
+{# Fill empty cells at the end of the row #}
+{% for key, buildKey in buildKeys %}
+{% if key > buildKeyIndexPrinted %}
+<td></td>
+{% endif %}
+{% endfor %}
+</tr>
+{% endif %}
+<tr>
+{# Conf name #}
+<td><small>{{ conf.getName }}</small></td>
+{# Flags for the latest build #}
+<td class="center rightBorder">
+{% if run.getForcesuccess %}
+<span class="label label-success">f</span>
+{% endif %}
+{% if run.getInsignificant %}
+<span class="label label-default">i</span>
+{% endif %}
+</td>
+{% set buildKeyIndexPrinted = -1 %}
+{% endif %}
+
+{# Result per build key #}
+{% set buildKeyFound = 0 %}
+{% for key, buildKey in buildKeys %}
+{# Print each column only once (checked based on column index key and buildKeyFound flag) #}
+{% if key > buildKeyIndexPrinted and not buildKeyFound %}
+{% if buildKey == run.getBuildKey %}
+{% set forcesuccess = '' %}
+{% if run.getResult == constant('ConfRun::RESULT_SUCCESS') %}
+{% if not run.getForcesuccess %}
+{% set resultIcon = 'glyphicon glyphicon-ok green' %}
+{% else %}
+{% set resultIcon = 'glyphicon glyphicon-ok-sign green' %}
+{% set forcesuccess = ' (as forcesuccess)' %}
+{% endif %}
+{% elseif run.getResult == constant('ConfRun::RESULT_FAILURE') %}
+{% set resultIcon = 'glyphicon glyphicon-remove red' %}
+{% elseif run.getResult == constant('ConfRun::RESULT_ABORTED') %}
+{% set resultIcon = 'glyphicon glyphicon-ban-circle gray' %}
+{% elseif run.getResult == constant('ConfRun::RESULT_UNDEF') %}
+{% set resultIcon = 'glyphicon glyphicon-ban-circle gray' %}
+{% else %}
+{% set resultIcon = '' %}
+{% endif %}
+{% if (run.getDuration / 10) > 60 %}
+{% set durationFormatted = ' (00:' ~ (run.getDuration/10)|date("i:s") ~ ')' %}
+{% else %}
+{% set durationFormatted = '' %}
+{% endif %}
+{# Print result #}
+<td class="center">
+<span class="spaceHorizontal {{ resultIcon }} clickOnTouch" data-toggle="tooltip" data-placement="top" data-html="true"
+title="<table>
+<tr><th>Build key: </th><td>{{ buildKey }}</td></tr>
+<tr><th>Configuration: </th><td>{{ run.getName }}</td></tr>
+<tr><th>Timestamp: </th><td>{{ run.getTimestamp }}</td></tr>
+<tr><th>Result: </th><td>{{ run.getResult }} {{ forcesuccess }}</td></tr>
+<tr><th>Forcesuccess: </th><td>{% if run.getForcesuccess %}yes{% else %}no{% endif %}</td></tr>
+<tr><th>Insignificant: </th><td>{% if run.getInsignificant %}yes{% else %}no{% endif %}</td></tr>
+<tr><th>Duration: </td><td>{{ run.getDuration}}</td></tr></table>"></span></td>
+{% set buildKeyFound = 1 %}
+{% else %}
+{# Print empty cell #}
+<td></td>
+{% endif %}
+{% set buildKeyIndexPrinted = key %}
+{% endif %}{# key #}
+{% endfor %}{# key #}
+{% set prevRowName = run.getName %}
+{% endfor %}{# run #}
+
+{# Close last row (also fill empty cells at the end of the row) #}
+{% for key, buildKey in buildKeys %}
+{% if key > buildKeyIndexPrinted %}
+<td></td>
+{% endif %}
+{% endfor %}{# key #}
+</tr>
+</tbody>
+</table>
+</div> {# .table-responsive #}
+</div> {# .panel-body #}
+</div> {# .panel... #}
+{% endif %}{# confBranch #}
+{% endfor %}{# branch #}
+{% endif %}{# confRunsAvailable #}
+
+{##### Testset Results in Branches #####}
+
+{# Check if any runs available #}
+{% set testsetRunsAvailable = 0 %}
+{% set testsetsAvailable = 0 %}
+{% for run in testsetRuns %}
+{% set testsetRunsAvailable = 1 %}
+{% endfor %}
+
+{% if testsetRunsAvailable %}
+
+<div class="panel panel-primary">
+<div class="panel-heading">
+<h4 class="panel-title bold">Testset Results in Branches <small>(failures only)</small></h4>
+</div>
+</div>
+
+{# Loop all the branches #}
+{% for branch in branches %}
+
+{# Get all build keys #}
+{% set buildKey = '' %}
+{% set buildKeys = [] %}
+{% set dates = [] %}
+{% for run in projectBuilds %}
+{% if run.branch == branch %}
+{% if buildKey != run.buildKey %}
+{% set buildKey = run.buildKey %}
+{% set buildKeys = buildKeys|merge([run.buildKey]) %}
+{% set dates = dates|merge([run.timestamp]) %}
+{% endif %}
+{% endif %}
+{% endfor %}
+
+{# Check if testset run for this branch #}
+{% set testsetBranch = 0 %}
+{% for run in testsetRuns if run.getBranchName == branch %}
+{% set testsetBranch = 1 %}
+{% endfor %}
+
+{# Show branch if testset run for it #}
+{% if testsetBranch %}
+{% set testsetsAvailable = 1 %}
+<div class="panel panel-info">
+<div class="panel-heading">
+<h4 class="panel-title bold">{{ branch }}</h4>
+</div>
+<div class="panel-body">
+<div class="table-responsive">
+<table class="table table-striped">
+<thead>
+<tr>
+<th class="bold">testset</th>
+<th class="bold">project</th>
+<th class="bold rightBorder">flags</th>
+{% for key, buildKey in buildKeys %}
+<th class="center">
+{% if buildKey|length > 6 %}
+<span class="clickOnTouch" data-toggle="tooltip" data-placement="top" title="{{ buildKey }}">{{ buildKey|slice(0, 4) }}...</span><br>
+{% else %}
+{{ buildKey }}<br>
+{% endif %}
+<span class="gray"><small>{{ dates[key]|date("m-d") }}</small></span>
+</th>
+{% endfor %}
+</tr>
+</thead>
+<tbody>
+{% set prevRowName = '' %}
+{% set buildKeyIndexPrinted = -1 %}
+{% set buildKeyFound = 0 %}
+{% for run in testsetRuns if run.getBranchName == branch %}
+
+{# New row for each testset #}
+{% if prevRowName != run.getName %}
+{# Close previous row #}
+{% if prevRowName != '' %}
+{# Fill empty cells at the end of the row #}
+{% for key, buildKey in buildKeys %}
+{% if key > buildKeyIndexPrinted %}
+<td></td>
+{% endif %}
+{% endfor %}
+</tr>
+{% endif %}
+<tr>
+{# Testset and project name #}
+<td><a href="{{ testsetRoute }}/{{ run.getName }}/{{ run.getTestsetProjectName }}"><small>{{ run.getName }}</small></a></td>
+<td><a href="{{ testsetProjectRoute }}/{{ run.getTestsetProjectName }}"><small>{{ run.getTestsetProjectName }}</small></a></td>
+{# Flags for the latest build #}
+<td class="center rightBorder">
+{% if run.getInsignificant %}
+<span class="label label-default">i</span>
+{% endif %}
+</td>
+{% set buildKeyIndexPrinted = -1 %}
+{% endif %}
+
+{# Result per build key #}
+{% set buildKeyFound = 0 %}
+{% for key, buildKey in buildKeys %}
+{# Print each column only once (checked based on column index key and buildKeyFound flag) #}
+{% if key > buildKeyIndexPrinted and not buildKeyFound %}
+{% if buildKey == run.getBuildKey %}
+{# Print result #}
+{% set flaky = '' %}
+{% if run.getResult == constant('TestsetRun::RESULT_SUCCESS') %}
+{% if run.getRun == 1 %}
+{% set resultIcon = 'glyphicon glyphicon-ok green' %}
+{% else %}
+{% set resultIcon = 'glyphicon glyphicon-ok-sign green' %}
+{% set flaky = ' (on run ' ~ run.getRun ~ ' as flaky)' %}
+{% endif %}
+{% elseif run.getResult == constant('TestsetRun::RESULT_FAILURE') %}
+{% set resultIcon = 'glyphicon glyphicon-remove red' %}
+{% else %}
+{% set resultIcon = '' %}
+{% endif %}
+{% if (run.getDuration / 10) > 60 %}
+{% set durationFormatted = ' (00:' ~ (run.getDuration/10)|date("i:s") ~ ')' %}
+{% else %}
+{% set durationFormatted = '' %}
+{% endif %}
+<td class="center">
+<span class="spaceHorizontal {{ resultIcon }} clickOnTouch" data-toggle="tooltip" data-placement="top" data-html="true"
+title="<table>
+<tr><th>Build key: </th><td>{{ buildKey }}</td></tr>
+<tr><th>Testset: </th><td>{{ run.getName }}</td></tr>
+<tr><th>Timestamp: </th><td>{{ run.getTimestamp }}</td></tr>
+<tr><th>Result: </th><td>{{ run.getResult }} {{ flaky }}</td></tr>
+<tr><th>Duration: </th><td>{{ run.getDuration / 10 }} s {{ durationFormatted }}</td></tr>
+<tr><th>Run #: </th><td>{{ run.getRun }}</td></tr>
+<tr><th>Insignificant: </th><td>{% if run.getInsignificant %}yes{% else %}no{% endif %}</td></tr></table>"></span></td>
+{% set buildKeyFound = 1 %}
+{% else %}
+{# Print empty cell #}
+<td></td>
+{% endif %}
+{% set buildKeyIndexPrinted = key %}
+{% endif %}{# key #}
+{% endfor %}{# key #}
+{% set prevRowName = run.getName %}
+{% endfor %}{# run #}
+
+{# Close last row (also fill empty cells at the end of the row) #}
+{% for key, buildKey in buildKeys %}
+{% if key > buildKeyIndexPrinted %}
+<td></td>
+{% endif %}
+{% endfor %}{# key #}
+</tr>
+</tbody>
+</table>
+</div> {# .table-responsive #}
+</div> {# .panel-body #}
+</div> {# .panel... #}
+{% endif %}{# testsetBranch #}
+{% endfor %}{# branch #}
+{% endif %}{# testsetRunsAvailable #}
+
+{# Notifications when data not available #}
+{% if testsetProject == '' %}
+{% if not confRunsAvailable %}
+<div class="alert alert-danger" role="alert">
+No data available for configuration {{ conf.getName }}!
+</div>
+{% else %}
+{% if not testsetsAvailable %}
+<div class="alert alert-success" role="alert">
+No failed testsets for configuration {{ conf.getName }}!
+</div>
+{% endif %}
+{% endif %}
+{% else %}
+{% if not testsetsAvailable %}
+<div class="alert alert-success" role="alert">
+No failed testsets in project {{ testsetProject }} for configuration {{ conf.getName }}!
+</div>
+{% endif %}
+{% endif %}
+
+</div> {# .col... #}
+</div> {# .row #}
+</div> {# /container-fluid #}
+
+{% include "footer.html" %}
+
+{# Local scripts for this page #}
+<script src="scripts/tooltip.js"></script>
+
+{% include "close.html" %}
diff --git a/non-puppet/qtmetrics2/templates/testset_project.html b/non-puppet/qtmetrics2/templates/testset_project.html
index 485985d..6583738 100644
--- a/non-puppet/qtmetrics2/templates/testset_project.html
+++ b/non-puppet/qtmetrics2/templates/testset_project.html
@@ -34,8 +34,8 @@
/**
* Testset project page
- * @version 0.2
- * @since 10-07-2015
+ * @version 0.3
+ * @since 20-07-2015
* @author Juha Sippola
*/
@@ -258,7 +258,8 @@ details are available as tooltip on result icon.</li>
</tr>
{% endif %}
<tr>
-<td class="rightBorder"><small>{{ run.conf }}</small></td>
+{% set link = confRoute ~ '/' ~ run.conf|url_encode ~ '/' ~ project|url_encode %}
+<td class="rightBorder"><a href="{{ link }}"><small>{{ run.conf }}</small></a></td>
{% set buildKeyIndexPrinted = -1 %}
{% endif %}