summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuha Sippola <juhasippola@outlook.com>2015-09-28 15:04:28 +0300
committerTony Sarajärvi <tony.sarajarvi@theqtcompany.com>2015-09-29 09:00:31 +0000
commita99056159d16122d18cb65189a4b50e76ef388ee (patch)
tree7f0e0521649a16a6a315e491cbad3de92f1404b9
parent204862cddbdeb09b96996a7a4f0867c6b4dc8bad (diff)
Qt Metrics 2 (v0.36): Dashboard
New page to show the success rate of the latest Qt5 builds based on the configuration build results and the test results in branches as speedo charts using the d3.js library. Change-Id: I8af65fe16eefd56f5f2883abaf2dfcf2d016563b Reviewed-by: Tony Sarajärvi <tony.sarajarvi@theqtcompany.com>
-rw-r--r--non-puppet/qtmetrics2/index.php33
-rw-r--r--non-puppet/qtmetrics2/scripts/speedo.js157
-rw-r--r--non-puppet/qtmetrics2/src/Database.php108
-rw-r--r--non-puppet/qtmetrics2/src/test/DatabaseTest.php58
-rw-r--r--non-puppet/qtmetrics2/styles/qtmetrics.css32
-rw-r--r--non-puppet/qtmetrics2/styles/qtmetrics_svg.css80
-rw-r--r--non-puppet/qtmetrics2/templates/about.html4
-rw-r--r--non-puppet/qtmetrics2/templates/dashboard.html219
-rw-r--r--non-puppet/qtmetrics2/templates/header.html3
-rw-r--r--non-puppet/qtmetrics2/templates/home.html7
10 files changed, 691 insertions, 10 deletions
diff --git a/non-puppet/qtmetrics2/index.php b/non-puppet/qtmetrics2/index.php
index a3a9e26..3ab7952 100644
--- a/non-puppet/qtmetrics2/index.php
+++ b/non-puppet/qtmetrics2/index.php
@@ -34,7 +34,7 @@
/**
* Qt Metrics API
- * @since 24-09-2015
+ * @since 28-09-2015
* @author Juha Sippola
*/
@@ -69,6 +69,7 @@ $app->get('/', function() use($app)
'dbStatus' => $dbStatus,
'refreshed' => $dbStatus['refreshed'] . ' (GMT)',
'overviewRoute' => Slim\Slim::getInstance()->urlFor('overview'),
+ 'dashboardRoute' => Slim\Slim::getInstance()->urlFor('dashboard'),
'platformRoute' => $buildProjectPlatformRoute,
'topRoute' => Slim\Slim::getInstance()->urlFor('top'),
'flakyRoute' => Slim\Slim::getInstance()->urlFor('flaky'),
@@ -83,6 +84,36 @@ $app->get('/', function() use($app)
})->name('root');
/**
+ * UI route: /dashboard (GET)
+ */
+
+$app->get('/dashboard', function() use($app)
+{
+ $ini = Factory::conf();
+ $dbStatus = Factory::db()->getDbRefreshStatus();
+ $breadcrumb = array(
+ array('name' => 'home', 'link' => Slim\Slim::getInstance()->urlFor('root'))
+ );
+ $overviewRoute = Slim\Slim::getInstance()->urlFor('overview');
+ $buildProjectRoute = Slim\Slim::getInstance()->urlFor('buildproject');
+ $app->render('dashboard.html', array(
+ 'root' => Slim\Slim::getInstance()->urlFor('root'),
+ 'refreshed' => $dbStatus['refreshed'] . ' (GMT)',
+ 'breadcrumb' => $breadcrumb,
+ 'overviewRoute' => $overviewRoute,
+ 'buildProjectRoute' => $buildProjectRoute,
+ 'masterProject' => $ini['master_build_project'],
+ 'masterState' => $ini['master_build_state'],
+ 'latestConfRuns' => Factory::db()->getLatestConfBranchBuildResultsSum(
+ $ini['master_build_project'],
+ $ini['master_build_state']),
+ 'latestTestsetRuns' => Factory::db()->getLatestProjectBranchTestsetResultsSum(
+ $ini['master_build_project'],
+ $ini['master_build_state'])
+ ));
+})->name('dashboard');
+
+/**
* UI route: /overview (GET)
*/
diff --git a/non-puppet/qtmetrics2/scripts/speedo.js b/non-puppet/qtmetrics2/scripts/speedo.js
new file mode 100644
index 0000000..92b1acc
--- /dev/null
+++ b/non-puppet/qtmetrics2/scripts/speedo.js
@@ -0,0 +1,157 @@
+/*
+#############################################################################
+##
+## 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$
+##
+#############################################################################
+
+/**
+ * Speedo chart functions
+ * @since 27-09-2015
+ * @author Juha Sippola
+ */
+
+$(function () {
+
+ // Get all div ids on a page
+ var divs = [];
+ $(".chartSpeedo").find("div").each(function(){ divs.push(this.id); });
+
+ // Draw the charts
+ jQuery.each( divs, function( i, val ) {
+ var percent = Math.round(($("#" + val + "Value").html()/100) * 100) / 100;
+ drawSpeedo("#" + val, percent);
+ });
+
+});
+
+function drawSpeedo(divId, percent) {
+
+ var Needle, arc, arcEndRad, arcStartRad, barWidth, chart, chartInset,
+ degToRad, el, endPadRad, height, margin, needle, numSections, padRad,
+ percToDeg, percToRad, radius, sectionIndx, sectionPerc, startPadRad,
+ svg, totalPercent, width, _i;
+
+ console.log(divId + ": " + percent);
+
+ barWidth = 30;
+ numSections = 10;
+ sectionPerc = 1 / numSections / 2;
+ padRad = 0.05;
+ chartInset = 0;
+ totalPercent = 0.75;
+
+ el = d3.select(divId);
+
+ margin = {
+ top: 90,
+ right: 0,
+ bottom: 0,
+ left: 0
+ };
+
+ // width = el[0][0].offsetWidth + margin.left;
+ // height = el[0][0].offsetWidth + margin.top;
+ // radius = Math.min(width, height) / 2;
+ width = 150;
+ height = 150;
+ radius = 75;
+
+ percToDeg = function(perc) {
+ return perc * 360;
+ };
+
+ percToRad = function(perc) {
+ return degToRad(percToDeg(perc));
+ };
+
+ degToRad = function(deg) {
+ return deg * Math.PI / 180;
+ };
+
+ svg = el.append('svg').attr('width', width + margin.left + margin.right).attr('height', height);
+ chart = svg.append('g').attr('transform', "translate(" + ((width / 2) + margin.left) + ", " + margin.top + ")");
+ for (sectionIndx = _i = 1; 1 <= numSections ? _i <= numSections : _i >= numSections; sectionIndx = 1 <= numSections ? ++_i : --_i) {
+ arcStartRad = percToRad(totalPercent);
+ arcEndRad = arcStartRad + percToRad(sectionPerc);
+ totalPercent += sectionPerc;
+ startPadRad = sectionIndx === 0 ? 0 : padRad / 2;
+ endPadRad = sectionIndx === numSections ? 0 : padRad / 2;
+ arc = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth).startAngle(arcStartRad + startPadRad).endAngle(arcEndRad - endPadRad);
+ chart.append('path').attr('class', "arc chart-color" + sectionIndx).attr('d', arc);
+ }
+
+ Needle = (function() {
+
+ function Needle(len, radius) {
+ this.len = len;
+ this.radius = radius;
+ }
+
+ Needle.prototype.drawOn = function(el, perc) {
+ el.append('circle').attr('class', 'needle-center').attr('cx', 0).attr('cy', 0).attr('r', this.radius);
+ return el.append('path').attr('class', 'needle').attr('d', this.mkCmd(perc));
+ };
+
+ Needle.prototype.animateOn = function(el, perc) {
+ var self;
+ self = this;
+ return el.transition().delay(500).ease('elastic').duration(4000).selectAll('.needle').tween('progress', function() {
+ return function(percentOfPercent) {
+ var progress;
+ progress = percentOfPercent * perc;
+ return d3.select(this).attr('d', self.mkCmd(progress));
+ };
+ });
+ };
+
+ Needle.prototype.mkCmd = function(perc) {
+ var centerX, centerY, leftX, leftY, rightX, rightY, thetaRad, topX, topY;
+ thetaRad = percToRad(perc / 2);
+ centerX = 0;
+ centerY = 0;
+ topX = centerX - this.len * Math.cos(thetaRad);
+ topY = centerY - this.len * Math.sin(thetaRad);
+ leftX = centerX - this.radius * Math.cos(thetaRad - Math.PI / 2);
+ leftY = centerY - this.radius * Math.sin(thetaRad - Math.PI / 2);
+ rightX = centerX - this.radius * Math.cos(thetaRad + Math.PI / 2);
+ rightY = centerY - this.radius * Math.sin(thetaRad + Math.PI / 2);
+ return "M " + leftX + " " + leftY + " L " + topX + " " + topY + " L " + rightX + " " + rightY;
+ };
+
+ return Needle;
+
+ })();
+
+ needle = new Needle(85, 8);
+ needle.drawOn(chart, 0);
+ needle.animateOn(chart, percent);
+
+}
diff --git a/non-puppet/qtmetrics2/src/Database.php b/non-puppet/qtmetrics2/src/Database.php
index 57f7e42..e621ca8 100644
--- a/non-puppet/qtmetrics2/src/Database.php
+++ b/non-puppet/qtmetrics2/src/Database.php
@@ -34,7 +34,7 @@
/**
* Database class
- * @since 25-09-2015
+ * @since 27-09-2015
* @author Juha Sippola
*/
@@ -425,6 +425,59 @@ class Database {
}
/**
+ * Get the latest configuration result sum by branch for given project and state
+ * Similar to getLatestProjectBranchTestsetResultsSum but for configurations.
+ * @param string $runProject
+ * @param string $runState
+ * @return array (string branch, int buildKey, string timestamp, int passed, int failed, int aborted, int undef)
+ */
+ public function getLatestConfBranchBuildResultsSum($runProject, $runState)
+ {
+ $result = array();
+ $builds = self::getLatestProjectBranchBuildKeys($runProject, $runState);
+ foreach ($builds as $build) {
+ $query = $this->db->prepare("
+ SELECT
+ branch.name AS branch,
+ project_run.build_key,
+ project_run.timestamp,
+ COUNT(CASE WHEN conf_run.result = 'SUCCESS' THEN conf_run.result END) AS passed,
+ COUNT(CASE WHEN conf_run.result = 'FAILURE' THEN conf_run.result END) AS failed,
+ COUNT(CASE WHEN conf_run.result = 'ABORTED' THEN conf_run.result END) AS aborted,
+ COUNT(CASE WHEN conf_run.result = 'undef' THEN conf_run.result END) AS undef
+ FROM conf_run
+ INNER JOIN project_run ON conf_run.project_run_id = project_run.id
+ INNER JOIN branch ON project_run.branch_id = branch.id
+ WHERE
+ project_run.project_id = (SELECT id FROM project WHERE name = ?) AND
+ project_run.state_id = (SELECT id FROM state WHERE name = ?) AND
+ project_run.branch_id = (SELECT id from branch WHERE name = ?) AND
+ project_run.build_key = ? AND
+ branch.archived = 0;
+ ");
+ $query->execute(array(
+ $runProject,
+ $runState,
+ $build['name'],
+ $build['key']
+ ));
+
+ while($row = $query->fetch(PDO::FETCH_ASSOC)) {
+ $result[] = array(
+ 'branch' => $row['branch'],
+ 'buildKey' => $row['build_key'],
+ 'timestamp' => $row['timestamp'],
+ 'passed' => $row['passed'],
+ 'failed' => $row['failed'],
+ 'aborted' => $row['aborted'],
+ 'undef' => $row['undef']
+ );
+ }
+ }
+ return $result;
+ }
+
+ /**
* Get the latest testset result by branch for given project and state
* @param string $runProject
* @param string $runState
@@ -480,6 +533,59 @@ class Database {
}
/**
+ * Get the latest testset result sum by branch for given project and state
+ * Similar to getLatestProjectBranchTestsetResults but without testset project grouping.
+ * @param string $runProject
+ * @param string $runState
+ * @return array (string branch, int buildKey, string timestamp, int passed, int failed)
+ */
+ public function getLatestProjectBranchTestsetResultsSum($runProject, $runState)
+ {
+ $result = array();
+ $builds = self::getLatestProjectBranchBuildKeys($runProject, $runState);
+ foreach ($builds as $build) {
+ $query = $this->db->prepare("
+ SELECT
+ branch.name AS branch,
+ project_run.build_key,
+ project_run.timestamp,
+ COUNT(CASE WHEN testset_run.result LIKE '%passed' THEN testset_run.result END) AS passed,
+ COUNT(CASE WHEN testset_run.result LIKE '%failed' THEN testset_run.result END) AS failed
+ FROM testset_run
+ INNER JOIN testset ON testset_run.testset_id = testset.id
+ INNER JOIN project ON testset.project_id = project.id
+ INNER JOIN conf_run ON testset_run.conf_run_id = conf_run.id
+ INNER JOIN conf ON conf_run.conf_id = conf.id
+ INNER JOIN project_run ON conf_run.project_run_id = project_run.id
+ INNER JOIN branch ON project_run.branch_id = branch.id
+ WHERE
+ project_run.project_id = (SELECT id FROM project WHERE name = ?) AND
+ project_run.state_id = (SELECT id FROM state WHERE name = ?) AND
+ project_run.branch_id = (SELECT id from branch WHERE name = ?) AND
+ project_run.build_key = ? AND
+ branch.archived = 0;
+ ");
+ $query->execute(array(
+ $runProject,
+ $runState,
+ $build['name'],
+ $build['key']
+ ));
+
+ while($row = $query->fetch(PDO::FETCH_ASSOC)) {
+ $result[] = array(
+ 'branch' => $row['branch'],
+ 'buildKey' => $row['build_key'],
+ 'timestamp' => $row['timestamp'],
+ 'passed' => $row['passed'],
+ 'failed' => $row['failed']
+ );
+ }
+ }
+ return $result;
+ }
+
+ /**
* Get the latest testset result by branch for given project and state, for selected testset project.
* Similar to getLatestProjectBranchTestsetResults but listing only the selected testset project.
* @param string $testsetProject
diff --git a/non-puppet/qtmetrics2/src/test/DatabaseTest.php b/non-puppet/qtmetrics2/src/test/DatabaseTest.php
index fcc95ef..2c79adf 100644
--- a/non-puppet/qtmetrics2/src/test/DatabaseTest.php
+++ b/non-puppet/qtmetrics2/src/test/DatabaseTest.php
@@ -38,7 +38,7 @@ require_once(__DIR__.'/../Factory.php');
* Database unit test class
* Some of the tests require the test data as inserted into database with qtmetrics_insert.sql
* @example To run (in qtmetrics root directory): php <path-to-phpunit>/phpunit.phar ./src/test
- * @since 24-09-2015
+ * @since 27-09-2015
* @author Juha Sippola
*/
@@ -402,6 +402,35 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
}
/**
+ * Test getLatestConfBranchBuildResultsSum
+ * @dataProvider testGetLatestConfBranchBuildResultsSumData
+ */
+ public function testGetLatestConfBranchBuildResultsSum($runProject, $runState, $exp_branches, $exp_achived_branches)
+ {
+ $confs = array();
+ $db = Factory::db();
+ $result = $db->getLatestConfBranchBuildResultsSum($runProject, $runState);
+ $this->assertNotEmpty($result);
+ foreach($result as $row) {
+ $this->assertArrayHasKey('branch', $row);
+ $this->assertArrayHasKey('buildKey', $row);
+ $this->assertArrayHasKey('timestamp', $row);
+ $this->assertArrayHasKey('passed', $row);
+ $this->assertArrayHasKey('failed', $row);
+ $this->assertArrayHasKey('aborted', $row);
+ $this->assertArrayHasKey('undef', $row);
+ $this->assertContains($row['branch'], $exp_branches);
+ $this->assertNotContains($row['branch'], $exp_achived_branches);
+ }
+ }
+ public function testGetLatestConfBranchBuildResultsSumData()
+ {
+ return array(
+ array('Qt5', 'state', array('dev', 'stable', 'master'), array('release'))
+ );
+ }
+
+ /**
* Test getLatestProjectBranchTestsetResults
* @dataProvider testGetLatestProjectBranchTestsetResultsData
*/
@@ -430,6 +459,33 @@ class DatabaseTest extends PHPUnit_Framework_TestCase
}
/**
+ * Test getLatestProjectBranchTestsetResultsSum
+ * @dataProvider testGetLatestProjectBranchTestsetResultsSumData
+ */
+ public function testGetLatestProjectBranchTestsetResultsSum($runProject, $runState, $exp_branches, $exp_achived_branches)
+ {
+ $confs = array();
+ $db = Factory::db();
+ $result = $db->getLatestProjectBranchTestsetResultsSum($runProject, $runState);
+ $this->assertNotEmpty($result);
+ foreach($result as $row) {
+ $this->assertArrayHasKey('branch', $row);
+ $this->assertArrayHasKey('buildKey', $row);
+ $this->assertArrayHasKey('timestamp', $row);
+ $this->assertArrayHasKey('passed', $row);
+ $this->assertArrayHasKey('failed', $row);
+ $this->assertContains($row['branch'], $exp_branches);
+ $this->assertNotContains($row['branch'], $exp_achived_branches);
+ }
+ }
+ public function testGetLatestProjectBranchTestsetResultsSumData()
+ {
+ return array(
+ array('Qt5', 'state', array('dev', 'stable', 'master'), array('release'))
+ );
+ }
+
+ /**
* Test getLatestTestsetProjectBranchTestsetResults
* @dataProvider testGetLatestTestsetProjectBranchTestsetResultsData
*/
diff --git a/non-puppet/qtmetrics2/styles/qtmetrics.css b/non-puppet/qtmetrics2/styles/qtmetrics.css
index 2154532..f27ea52 100644
--- a/non-puppet/qtmetrics2/styles/qtmetrics.css
+++ b/non-puppet/qtmetrics2/styles/qtmetrics.css
@@ -35,7 +35,7 @@
/**
* Qt Metrics style sheet
- * @since 22-09-2015
+ * @since 27-09-2015
* @author Juha Sippola
*/
@@ -208,3 +208,33 @@ thead {
.hidden {
visibility: hidden;
}
+
+/*
+ * Speedo chart
+ * (Note: The SVG style definitions are in qtmetrics_svg.css)
+ */
+.chartSpeedo {
+ float: left;
+ margin: 2px 10px 2px 10px;
+ text-align: center;
+}
+.chartSpeedo p {
+ font-size: 1em;
+ float: left;
+ width: 100%;
+}
+.chartSpeedo p em {
+ font-size: 3em;
+ clear: both;
+ width: 100%;
+}
+
+.chartSpeedo .chartArea {
+ margin: 0px 0px -40px 0px;
+}
+
+.chartSpeedo .label {
+ color: #464A4F;
+ background-color: white;
+ border: 1px solid #464A4F;
+}
diff --git a/non-puppet/qtmetrics2/styles/qtmetrics_svg.css b/non-puppet/qtmetrics2/styles/qtmetrics_svg.css
new file mode 100644
index 0000000..be86a5d
--- /dev/null
+++ b/non-puppet/qtmetrics2/styles/qtmetrics_svg.css
@@ -0,0 +1,80 @@
+/*
+#############################################################################
+##
+## 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$
+##
+#############################################################################
+*/
+
+/**
+ * Qt Metrics style definitions for SVG (scalable vector graphics)
+ * @since 27-09-2015
+ * @author Juha Sippola
+ */
+
+/*
+ * Speedo chart
+ * (Note: The normal CSS style definitions are in qtmetrics.css)
+ */
+
+.chart-color1 {
+ fill: #FF0000;
+}
+.chart-color2 {
+ fill: #FF4D00;
+}
+.chart-color3 {
+ fill: #FF8200;
+}
+.chart-color4 {
+ fill: #FFA600;
+}
+.chart-color5 {
+ fill: #FFDC00;
+}
+.chart-color6 {
+ fill: #FFE600;
+}
+.chart-color7 {
+ fill: #FFF800;
+}
+.chart-color8 {
+ fill: #D5FF00;
+}
+.chart-color9 {
+ fill: #72F600;
+}
+.chart-color10 {
+ fill: #07FB00;
+}
+.needle,
+.needle-center {
+ fill: #464A4F;
+}
diff --git a/non-puppet/qtmetrics2/templates/about.html b/non-puppet/qtmetrics2/templates/about.html
index 715df9b..aa54a3e 100644
--- a/non-puppet/qtmetrics2/templates/about.html
+++ b/non-puppet/qtmetrics2/templates/about.html
@@ -34,7 +34,7 @@
/**
* About window content
- * @since 24-09-2015
+ * @since 28-09-2015
* @author Juha Sippola
*/
@@ -52,4 +52,4 @@ and the global Qt developer community are the target audience. For detailed desc
<p>See the <strong><a href="https://wiki.qt.io/Qt_Metrics_2_Backlog" target="_blank">backlog</a></strong>
for development items currently identified or in progress.</p>
-<p><small>Version 0.35 (24-Sep-2015)</small></p>
+<p><small>Version 0.36 (28-Sep-2015)</small></p>
diff --git a/non-puppet/qtmetrics2/templates/dashboard.html b/non-puppet/qtmetrics2/templates/dashboard.html
new file mode 100644
index 0000000..692c52c
--- /dev/null
+++ b/non-puppet/qtmetrics2/templates/dashboard.html
@@ -0,0 +1,219 @@
+{#
+#############################################################################
+##
+## 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$
+##
+#############################################################################
+
+/**
+ * Overview page
+ * @since 28-09-2015
+ * @author Juha Sippola
+ */
+
+#}
+
+{% include "header.html" %}
+
+{# Failed/passed bar area size in px #}
+{% set BAR_AREA = 60 %}
+
+<ol class="breadcrumb">
+{% for link in breadcrumb %}
+<li><a href="{{ link.link }}">{{ link.name }}</a></li>
+{% endfor %}
+<li class="active">dashboard</li>
+</ol>
+
+<div class="container-fluid">
+
+<div class="row">
+<div class="col-sm-12 col-md-12 main">
+
+{##### Title #####}
+
+<h1 class="page-header">
+Dashboard
+<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">
+<span class="glyphicon glyphicon-info-sign"></span> <strong>Dashboard</strong><br>
+<ul>
+<li><strong>Latest {{ masterProject }} {{ masterState }} Build Status</strong> shows the status
+based on the configuration build results (% of {{ constant('confRun::RESULT_SUCCESS') }} from
+total) in the latest <strong>{{ masterProject }} {{ masterState }}</strong> builds by branch.</li>
+<li><strong>Latest {{ masterProject }} {{ masterState }} Testing Status</strong> shows the status
+based on the testset results (% of {{ constant('testsetRun::RESULT_SUCCESS') }} from total) in the
+latest <strong>{{ masterProject }} {{ masterState }}</strong> builds by branch (in any configuration).</li>
+<li>Details on the result % are available as tooltip</li>
+</ul>
+</div>
+</div>
+
+{##### Latest Build Status #####}
+
+<div class="panel panel-primary">
+<div class="panel-heading">
+<h4 class="panel-title bold">Latest {{ masterProject }} {{ masterState }} Build Status
+<a class="btn btn-info btn-xs spaceHorizontal" href="{{ buildProjectRoute }}" role="button"><span class="spaceHorizontal glyphicon glyphicon-share-alt"></span></a>
+</h4>
+</div>
+<div class="panel-body">
+<div class="row">
+
+{# Get branches #}
+{% set branches = [] %}
+{% for run in latestConfRuns %}
+{% if run.branch not in branches %}
+{% set branches = branches|merge([run.branch]) %}
+{% endif %}
+{% endfor %}
+
+{# Result (by branch) #}
+{% for branch in branches %}
+{% set branchTag = branch %}
+{% set branchTag = branchTag|replace({'.': '--'}) %} {# '.' reserved in jQuery #}
+{% set branchTag = branchTag|replace({':': '---'}) %} {# ':' reserved in jQuery #}
+{% set branchTag = branchTag|replace({',': '----'}) %} {# '.' reserved in jQuery #}
+{% set branchTag = branchTag|replace({'[': '-----'}) %} {# '.' reserved in jQuery #}
+{% set branchTag = branchTag|replace({']': '------'}) %} {# '.' reserved in jQuery #}
+{% set branchTag = branchTag|replace({'_': '-------'}) %} {# '_' used as separator for modal confirmations #}
+{% for run in latestConfRuns if branch == run.branch %}
+{% set passed = run.passed %}
+{% set failed = run.failed %}
+{% set aborted = run.aborted %}
+{% set undef = run.undef %}
+{% set total = passed + failed + aborted + undef %}
+{% if total > 0 %}
+{% set percent = (100 * passed / total)|round(1) %}
+{% else %}
+{% set percent = 0 %}
+{% endif %}
+<div class="col-md-3">
+<div class="chartSpeedo">
+<h3>{{ branch }}</h3>
+<div id="speedo{{ branchTag }}Build" class="chartArea"></div>
+<h4><span class="label label-primary clickOnTouch" data-toggle="tooltip" data-placement="top" data-html="true"
+title="<table>
+<tr><th>{{ branch }}</th><td>{{ run.timestamp}}</td></tr>
+<tr><td>{{ constant('confRun::RESULT_SUCCESS') }}: </td><td>{{ passed }}</td></tr>
+<tr><td>{{ constant('confRun::RESULT_FAILURE') }}: </td><td>{{ failed }}</td></tr>
+<tr><td>{{ constant('confRun::RESULT_ABORTED') }}: </td><td>{{ aborted }}</td></tr>
+<tr><td>{{ constant('confRun::RESULT_UNDEF') }}: </td><td>{{ undef }}</td></tr>
+<tr><td>Total: </td><td>{{ total }}</td></tr></table>">
+<span id="speedo{{ branchTag }}BuildValue" class="clickOnTouch">{{ percent }}</span> %
+</span></h4>
+</div>
+</div>
+{% endfor %}{# run #}
+{% endfor %}{# branch #}
+
+</div> {# .row #}
+</div> {# .panel-body #}
+</div> {# .panel #}
+
+{##### Latest Testing Status #####}
+
+<div class="panel panel-primary">
+<div class="panel-heading">
+<h4 class="panel-title bold">Latest {{ masterProject }} {{ masterState }} Testing Status
+<a class="btn btn-info btn-xs spaceHorizontal" href="{{ overviewRoute }}" role="button"><span class="spaceHorizontal glyphicon glyphicon-share-alt"></span></a>
+</h4>
+</div>
+<div class="panel-body">
+<div class="row">
+
+{# Get branches #}
+{% set branches = [] %}
+{% for run in latestTestsetRuns %}
+{% if run.branch not in branches %}
+{% set branches = branches|merge([run.branch]) %}
+{% endif %}
+{% endfor %}
+
+{# Result (by branch) #}
+{% for branch in branches %}
+{% set branchTag = branch %}
+{% set branchTag = branchTag|replace({'.': '--'}) %} {# '.' reserved in jQuery #}
+{% set branchTag = branchTag|replace({':': '---'}) %} {# ':' reserved in jQuery #}
+{% set branchTag = branchTag|replace({',': '----'}) %} {# '.' reserved in jQuery #}
+{% set branchTag = branchTag|replace({'[': '-----'}) %} {# '.' reserved in jQuery #}
+{% set branchTag = branchTag|replace({']': '------'}) %} {# '.' reserved in jQuery #}
+{% set branchTag = branchTag|replace({'_': '-------'}) %} {# '_' used as separator for modal confirmations #}
+{% for run in latestTestsetRuns if branch == run.branch %}
+{% set passed = run.passed %}
+{% set failed = run.failed %}
+{% set total = passed + failed %}
+{% if total > 0 %}
+{% set percent = (100 * passed / total)|round(1) %}
+{% else %}
+{% set percent = 0 %}
+{% endif %}
+<div class="col-md-3">
+<div class="chartSpeedo">
+<h3>{{ branch }}</h3>
+<div id="speedo{{ branchTag }}Testset" class="chartArea"></div>
+<h4><span class="label label-primary clickOnTouch" data-toggle="tooltip" data-placement="top" data-html="true"
+title="<table>
+<tr><th>{{ branch }}</th><td>{{ run.timestamp}}</td></tr>
+<tr><td>{{ constant('testsetRun::RESULT_SUCCESS') }}: </td><td>{{ passed }}</td></tr>
+<tr><td>{{ constant('testsetRun::RESULT_FAILURE') }}: </td><td>{{ failed }}</td></tr>
+<tr><td>Total: </td><td>{{ total }}</td></tr></table>">
+<span id="speedo{{ branchTag }}TestsetValue" class="clickOnTouch">{{ percent }}</span> %
+</span></h4>
+</div>
+</div>
+{% endfor %}{# run #}
+{% endfor %}{# branch #}
+
+</div> {# .row #}
+</div> {# .panel-body #}
+</div> {# .panel #}
+
+</div> {# .col... #}
+</div> {# .row #}
+
+</div> {# .container-fluid #}
+
+{% include "footer.html" %}
+
+{# Local scripts for this page #}
+<script src="lib/D3/d3.min.js"></script>
+<script src="scripts/speedo.js"></script>
+<script src="scripts/tooltip.js"></script>
+
+{% include "close.html" %}
diff --git a/non-puppet/qtmetrics2/templates/header.html b/non-puppet/qtmetrics2/templates/header.html
index 23492bf..79e6611 100644
--- a/non-puppet/qtmetrics2/templates/header.html
+++ b/non-puppet/qtmetrics2/templates/header.html
@@ -34,7 +34,7 @@
/**
* Header section of html page including the meta data and style sheets
- * @since 15-09-2015
+ * @since 27-09-2015
* @author Juha Sippola
*/
@@ -67,6 +67,7 @@
{# Own styles #}
<link rel="stylesheet" href="styles/qtmetrics.css">
+<link rel="stylesheet" href="styles/qtmetrics_svg.css">
{# HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries #}
{#[if lt IE 9]>
diff --git a/non-puppet/qtmetrics2/templates/home.html b/non-puppet/qtmetrics2/templates/home.html
index da90858..946b341 100644
--- a/non-puppet/qtmetrics2/templates/home.html
+++ b/non-puppet/qtmetrics2/templates/home.html
@@ -34,7 +34,7 @@
/**
* Home page
- * @since 24-09-2015
+ * @since 27-09-2015
* @author Juha Sippola
*/
@@ -64,9 +64,10 @@
<div class="col-md-4">
<hr>
<h2>Overview</h2>
-<p>See the latest build status across the branches:</p>
+<p>See the latest <strong>{{ masterProject }} {{ masterState }}</strong> status:</p>
<div>
-<a class="btn btn-primary btn-xs" href="{{ overviewRoute }}" role="button">{{ masterProject }} {{ masterState }}</a>
+<a class="btn btn-primary btn-xs" href="{{ dashboardRoute }}" role="button">dashboard</a>
+<a class="btn btn-primary btn-xs" href="{{ overviewRoute }}" role="button">overview</a>
</div>
</div>