+
+
+
+
{{vm.vulnerabilities}}
+ Vulnerabilities
+
+
+
+
-
{{vm.coverage||"unknown"}}
- Code Coverage
+ {{vm.coverage||"/"}}
+ Code Coverage
-
+
-
{{vm.blocker||"unknown"}}
- Blocker Issues
+ {{vm.blocker||"/"}}
+ Blocker Issues
-
+
+
+
{{vm.technicalDept+" days" ||"/"}}
+ Technical Dept
+
+
about metrics
diff --git a/src/service.js b/src/service.js
index 9d6cff8..6d50e89 100644
--- a/src/service.js
+++ b/src/service.js
@@ -1,10 +1,37 @@
'use strict';
-sonarADFWidget.
-factory('sonarApi', sonarApi);
+sonarADFWidget.factory('sonarApi', sonarApi);
//function factory sonar
-function sonarApi($http, $q) {
+function sonarApi($http, $q, sonarEndpoint) {
+
+
+ function checkVersionCompatibilityLowerThan(requiredAPIVersion, serverVersion) {
+ if (requiredAPIVersion && serverVersion) {
+ var ver1 = requiredAPIVersion.split('.');
+ var ver2 = serverVersion.split('.');
+ if (ver1[0] > ver2[0]) {
+ return true;
+ } else if (ver1[0] === ver2[0] && ver1[1] >= ver2[1]) {
+ return true;
+ }
+ return false;
+ }
+
+ }
+
+ function getServerVersion(sonarUrl) {
+ var serverVersionReqUrl = sonarUrl + "/api/server/version";
+ return $http({
+ method: 'GET',
+ url: serverVersionReqUrl,
+ headers: {
+ 'Accept': 'application/json'
+ }
+ }).then(function (response) {
+ return response.data;
+ });
+ }
function createApiUrlProjects(sonarUrl) {
return sonarUrl + '/api/projects/index?format=json';
@@ -23,7 +50,7 @@ function sonarApi($http, $q) {
}
function createApiUrlQuality(sonarUrl, projectname) {
- return sonarUrl + '/api/resources?resource=' + projectname + '&metrics=coverage,blocker_violations,quality_gate_details';
+ return sonarUrl + '/api/measures/component?componentKey=' + projectname + '&metricKeys=coverage,blocker_violations,alert_status,sqale_index,vulnerabilities';
}
function getProjectTime(projectBeginn, projectEnd) {
@@ -44,7 +71,7 @@ function sonarApi($http, $q) {
function workingDaysBetweenDates(startDate, endDate) {
// Validate input
- if (endDate < startDate){
+ if (endDate < startDate) {
return 0;
}
@@ -64,19 +91,17 @@ function sonarApi($http, $q) {
var endDay = endDate.getDay();
// Remove weekend not previously removed.
- if (startDay - endDay > 1)
- {
+ if (startDay - endDay > 1) {
days = days - 2;
}
// Remove start day if span starts on Sunday but ends before Saturday
- if (startDay === 0 && endDay != 6){
+ if (startDay === 0 && endDay != 6) {
days = days - 1;
}
// Remove end day if span ends on Saturday but starts after Sunday
- if (endDay === 6 && startDay != 0)
- {
+ if (endDay === 6 && startDay != 0) {
days = days - 1;
}
@@ -112,30 +137,28 @@ function sonarApi($http, $q) {
var apiUrlProject2 = createApiUrlMetrics(sonarUrl, projectname2);
var api1 = $http.get(apiUrlProject1);
var api2 = $http.get(apiUrlProject2);
- var responsesArray = $q.all([api1, api2])
- .then(function(response) {
+ return $q.all([api1, api2])
+ .then(function (response) {
var projectLeft = response[0];
var projectRight = response[1];
var projectMetrics = {
'projectLeft': projectLeft,
'projectRight': projectRight
};
- return projectMetrics;
+ return {resp: projectMetrics, projectLeft: projectname1, projectRight: projectname2};
});
-
- return responsesArray;
}
function getChartData(sonarUrl, projectname, metrics, timespan) {
-
var apiUrl;
var fromDateTime;
var toDateTime;
+ var metricsArray = [];
var metricsString = createMetricsString(metrics);
if (timespan.type === 'dynamic') {
var today = new Date();
- switch(timespan.dynamic) {
+ switch (timespan.dynamic) {
case 'week':
fromDateTime = new Date(today.getTime() - 7 * 24 * 60 * 60 * 1000);
break;
@@ -151,39 +174,94 @@ function sonarApi($http, $q) {
fromDateTime = timespan.fromDateTime;
toDateTime = timespan.toDateTime;
}
- if ((fromDateTime && toDateTime)) {
- apiUrl = sonarUrl + '/api/timemachine?resource=' + projectname + '&metrics=' + metricsString + '&fromDateTime=' + fromDateTime + '&toDateTime=' + toDateTime;
- } else {
- apiUrl = sonarUrl + '/api/timemachine?resource=' + projectname + '&metrics=' + metricsString;
- }
- return $http({
- method: 'GET',
- url: apiUrl,
- headers: {
- 'Accept': 'application/json'
- }
- }).then(function(response) {
- var metricsArray = [];
- var responseData = response.data[0];
- var cols = responseData.cols;
- var cells = responseData.cells;
- for (var x = 0; x < cols.length; x++) {
- var values = [];
- var dates = [];
- for (var y = 0; y < cells.length; y++) {
- dates[y] = cells[y].d.split("T")[0];
- values[y] = cells[y].v[x];
- }
- var metricsObj = {
- 'metric': cols[x].metric,
- 'values': values,
- 'dates': dates
- };
- metricsArray.push(metricsObj);
- }
- return metricsArray;
- });
+ var requiredAPIVersion = '6.2';
+ return new Promise(
+ function (resolve) {
+
+ var serverVersion = getServerVersion(sonarUrl).then(function (response) {
+ return response;
+ });
+
+ var isAPISupported = serverVersion.then(function (serverVersion) {
+ return checkVersionCompatibilityLowerThan(requiredAPIVersion, serverVersion)
+ });
+
+ var responseData = isAPISupported.then(function (isAPISupported) {
+ // implementation for api version 6.2 or lower
+ if (isAPISupported) {
+ if ((fromDateTime && toDateTime)) {
+ apiUrl = sonarUrl + '/api/timemachine?resource=' + projectname + '&metrics=' + metricsString + '&fromDateTime=' + fromDateTime + '&toDateTime=' + toDateTime;
+ } else {
+ apiUrl = sonarUrl + '/api/timemachine?resource=' + projectname + '&metrics=' + metricsString;
+ }
+ return $http({
+ method: 'GET',
+ url: apiUrl,
+ headers: {
+ 'Accept': 'application/json'
+ }
+ }).then(function (response) {
+ var responseData = response.data[0];
+ var cols = responseData.cols;
+ var cells = responseData.cells;
+ for (var x = 0; x < cols.length; x++) {
+ var values = [];
+ var dates = [];
+ for (var y = 0; y < cells.length; y++) {
+ dates[y] = cells[y].d.split("T")[0];
+ values[y] = cells[y].v[x];
+ }
+ var metricsObj = {
+ 'metric': cols[x].metric,
+ 'values': values,
+ 'dates': dates
+ };
+ metricsArray.push(metricsObj);
+ }
+ return metricsArray;
+ });
+ // implementation vor api version 6.3 or higher
+ } else {
+
+ if ((fromDateTime && toDateTime)) {
+ //convert for api request YEAR-MONTH-DAY
+ fromDateTime = fromDateTime.toISOString().replace(/T.*/, '').split('-').join('-');
+ toDateTime = toDateTime.toISOString().replace(/T.*/, '').split('-').join('-');
+
+ apiUrl = sonarUrl + '/api/measures/search_history?component=' + projectname + '&metrics=' + metricsString + '&from=' + fromDateTime + '&to=' + toDateTime;
+ } else {
+ apiUrl = sonarUrl + '/api/measures/search_history?component=' + projectname + '&metrics=' + metricsString;
+ }
+ return $http({
+ method: 'GET',
+ url: apiUrl,
+ headers: {
+ 'Accept': 'application/json'
+ }
+ }).then(function (response) {
+ response.data.measures.forEach(function (element) {
+ var dates = [];
+ var values = [];
+ element.history.forEach(function (data) {
+ dates.push(data.date.split("T")[0]);
+ values.push(data.value);
+ });
+ var metricsObj = {
+ 'metric': element.metric,
+ 'values': values,
+ 'dates': dates
+ };
+ metricsArray.push(metricsObj);
+ });
+ return metricsArray
+ });
+ }
+ });
+ setTimeout(function () {
+ resolve(responseData)
+ });
+ });
}
@@ -191,13 +269,15 @@ function sonarApi($http, $q) {
var linesOfCodeSum = 0;
var avarageCoverage = 0;
for (var i = 0; i < projects.length; i++) {
- if (projects[i].msr[0]) {
- var linesOfCode = projects[i].msr[0].val;
- linesOfCodeSum += linesOfCode;
- }
- if (projects[i].msr[1]) {
- var coverage = projects[i].msr[1].val;
- avarageCoverage += coverage;
+ if (projects[i].msr) {
+ if (projects[i].msr[0]) {
+ var linesOfCode = projects[i].msr[0].val;
+ linesOfCodeSum += linesOfCode;
+ }
+ if (projects[i].msr[1]) {
+ var coverage = projects[i].msr[1].val;
+ avarageCoverage += coverage;
+ }
}
}
avarageCoverage = avarageCoverage / projects.length;
@@ -216,27 +296,54 @@ function sonarApi($http, $q) {
headers: {
'Accept': 'application/json'
}
- }).then(function(response) {
+ }).then(function (response) {
return response.data;
});
}
- function getAllProjectsStatistics(sonarUrl){
- var apiUrl = createApiUrlAllProjectsStatistics(sonarUrl);
- return $http({
- method: 'GET',
- url: apiUrl,
- headers: {
- 'Accept': 'application/json'
- }
- }).then(function(response) {
- var projects = response.data;
- return generateArray(projects);
- });
+ function getAllProjectsStatistics(sonarUrl) {
+ var requiredAPIVersion = '6.2';
+ return new Promise(
+ function (resolve) {
+
+ var serverVersion = getServerVersion(sonarUrl).then(function (data) {
+ return data;
+ });
+
+ var isAPISupported = serverVersion.then(function (serverVersion) {
+ return checkVersionCompatibilityLowerThan(requiredAPIVersion, serverVersion)
+ });
+
+ var responseData = isAPISupported.then(function (isAPISupported) {
+ if (isAPISupported) {
+ var apiUrl = createApiUrlAllProjectsStatistics(sonarUrl);
+ return $http({
+ method: 'GET',
+ url: apiUrl,
+ headers: {
+ 'Accept': 'application/json'
+ }
+ }).then(function (response) {
+ var projects = response.data;
+ return generateArray(projects);
+ });
+ } else {
+ return {
+ support: true,
+ message: "This widget is only compatible with sonar v" + requiredAPIVersion + " or lower."
+ }
+ }
+ });
+ setTimeout(function () {
+ resolve(responseData)
+ });
+ });
+
+
}
- function getAllMyIssues(sonarUrl){
+ function getAllMyIssues(sonarUrl) {
var apiUrl = createApiUrlAllMyIssues(sonarUrl);
return $http({
@@ -245,22 +352,21 @@ function sonarApi($http, $q) {
headers: {
'Accept': 'application/json'
}
- }).then(function(response) {
+ }).then(function (response) {
return response.data.issues;
});
}
- function getProjectquality(sonarUrl, project){
+ function getProjectquality(sonarUrl, project) {
var apiUrl = createApiUrlQuality(sonarUrl, project);
-
return $http({
method: 'GET',
url: apiUrl,
headers: {
'Accept': 'application/json'
}
- }).then(function(response) {
- return response.data[0];
+ }).then(function (response) {
+ return {"project": project, "quality_index": response.data.component.measures, "url": sonarEndpoint.url};
});
}
@@ -271,7 +377,8 @@ function sonarApi($http, $q) {
getMetrics: getMetrics,
getProjectTime: getProjectTime,
getAllMyIssues: getAllMyIssues,
- getProjectquality: getProjectquality
+ getProjectquality: getProjectquality,
+ getServerVersion: getServerVersion
};
}
diff --git a/src/sonar.js b/src/sonar.js
index b83015e..f9b2b80 100644
--- a/src/sonar.js
+++ b/src/sonar.js
@@ -1,27 +1,35 @@
'use strict';
//app initialisation with dependencies
-var sonarADFWidget = angular.module('adf.widget.sonar', ['adf.provider', 'chart.js', 'ui.bootstrap', 'ui.bootstrap.datepicker','angular-svg-round-progressbar'])
-.constant("sonarEndpoint", {
- "url": "https://sonarcloud.io"
-}).constant("METRIC_NAMES", {"open_issues":"Open Issues","ncloc":"Lines of Code",
-"public_documented_api_density": "Public documented API density","duplicated_lines_density": "Duplicated Lines (%)",
-"sqale_index":"SQALE index", "coverage": "Coverage (%)", "tests": "Tests" })
- .config(function(dashboardProvider) {
+var sonarADFWidget = angular.module('adf.widget.sonar', ['adf.provider', 'chart.js', 'ui.bootstrap', 'ui.bootstrap.datepicker', 'angular-svg-round-progressbar'])
+ .constant("sonarEndpoint", {
+ "url": "https://builds.apache.org/analysis"
+ })
+ .constant("METRIC_NAMES", {
+ "open_issues": "Open Issues",
+ "ncloc": "Lines of Code",
+ "public_documented_api_density": "Public documented API density",
+ "duplicated_lines_density": "Duplicated Lines (%)",
+ "sqale_index": "SQALE index",
+ "coverage": "Coverage (%)",
+ "tests": "Tests"
+ })
+ .config(function (dashboardProvider) {
dashboardProvider
.widget('sonar-all-projects-statistics', {
title: 'Sonar Statistics of all Projects ',
description: 'Displays all SonarQube statistics',
templateUrl: '{widgetsPath}/sonar/src/allProjects/view.html',
- resolve: {
- data: function(sonarApi, config, sonarEndpoint) {
- if (config.apiUrl) {
- return sonarApi.getAllProjectsStatistics(config.apiUrl);
- }
- else if (sonarEndpoint.url){
- return sonarApi.getAllProjectsStatistics(sonarEndpoint.url);
+ reload: true,
+ resolve: {
+ data: function(sonarApi, config, sonarEndpoint) {
+ if (config.apiUrl) {
+ return sonarApi.getAllProjectsStatistics(config.apiUrl);
+ }
+ else if (sonarEndpoint.url){
+ return sonarApi.getAllProjectsStatistics(sonarEndpoint.url);
+ }
+ return 'Please Setup the Widget';
}
- return 'Please Setup the Widget';
- }
},
category: 'SonarQube',
controller: 'sonarStatsCtrl',
@@ -35,16 +43,16 @@ var sonarADFWidget = angular.module('adf.widget.sonar', ['adf.provider', 'chart.
description: 'Displays a linechart with different metrics',
templateUrl: '{widgetsPath}/sonar/src/chart/view.html',
resolve: {
- data: function(sonarApi, config, sonarEndpoint) {
+ data: function (sonarApi, config, sonarEndpoint) {
var apiUrl;
if (config.apiUrl) {
apiUrl = config.apiUrl;
} else {
apiUrl = sonarEndpoint.url;
}
- if (apiUrl && config.project && config.metrics){
+ if (apiUrl && config.project && config.metrics) {
return sonarApi.getChartData(apiUrl, config.project, config.metrics, config.timespan);
- } else{
+ } else {
return 'Please Setup the Widget';
}
}
@@ -61,13 +69,12 @@ var sonarADFWidget = angular.module('adf.widget.sonar', ['adf.provider', 'chart.
description: 'Displays a table to compare two projects',
templateUrl: '{widgetsPath}/sonar/src/compare/view.html',
resolve: {
- data: function(sonarApi, config, sonarEndpoint) {
+ data: function (sonarApi, config, sonarEndpoint) {
- if (config.apiUrl){
+ if (config.apiUrl) {
return sonarApi.getMetrics(config.apiUrl, config.projectname1, config.projectname2);
- }
- else if (sonarEndpoint.url && config.projectname1 && config.projectname2){
- return sonarApi.getMetrics(sonarEndpoint.url, config.projectname1,config.projectname2);
+ } else if (sonarEndpoint.url && config.projectname1 && config.projectname2) {
+ return sonarApi.getMetrics(sonarEndpoint.url, config.projectname1, config.projectname2);
}
return 'Please Setup the Widget';
}
@@ -84,8 +91,8 @@ var sonarADFWidget = angular.module('adf.widget.sonar', ['adf.provider', 'chart.
description: 'Visualizes the progress of a project',
templateUrl: '{widgetsPath}/sonar/src/project-progress/view.html',
resolve: {
- data: function(sonarApi, config) {
- if (config.projectBeginn){
+ data: function (sonarApi, config) {
+ if (config.projectBeginn) {
return sonarApi.getProjectTime(config.projectBeginn, config.projectEnd);
}
return 'Please Setup the Widget';
@@ -97,16 +104,28 @@ var sonarADFWidget = angular.module('adf.widget.sonar', ['adf.provider', 'chart.
templateUrl: '{widgetsPath}/sonar/src/project-progress/edit.html'
}
})
+ .widget('version', {
+ title: 'Sonar Server Version',
+ description: 'Displays the current sonar server version',
+ templateUrl: '{widgetsPath}/sonar/src/version/view.html',
+ resolve: {
+ data: function (sonarApi, sonarEndpoint) {
+ return sonarApi.getServerVersion(sonarEndpoint.url);
+ }
+ },
+ category: 'SonarQube',
+ controller: 'version',
+ controllerAs: 'vm'
+ })
.widget('sonar-my-issues', {
title: 'Sonar My Issues',
description: 'Displays all issues of yourself',
templateUrl: '{widgetsPath}/sonar/src/issues/view.html',
resolve: {
- data: function(sonarApi, config, sonarEndpoint) {
+ data: function (sonarApi, config, sonarEndpoint) {
if (config.apiUrl) {
return sonarApi.getAllMyIssues(config.apiUrl);
- }
- else if (sonarEndpoint.url){
+ } else if (sonarEndpoint.url) {
return sonarApi.getAllMyIssues(sonarEndpoint.url);
}
return 'Please Setup the Widget';
@@ -116,19 +135,18 @@ var sonarADFWidget = angular.module('adf.widget.sonar', ['adf.provider', 'chart.
controller: 'sonarIssueCtrl',
controllerAs: 'vm',
edit: {
- templateUrl: '{widgetsPath}/sonar/src/issues/edit.html'
+ templateUrl: '{widgetsPath}/sonar/src/issues/edit.html'
}
})
.widget('sonar-projectquality', {
- title: 'Sonar Projectquality of a Project',
- description: 'Displays Status of the Quality Gate, Code Coverage and Blocker Issues',
+ title: 'Sonar Project Quality',
+ description: 'Displays metrics of a specific project',
templateUrl: '{widgetsPath}/sonar/src/projectquality/view.html',
resolve: {
- data: function(sonarApi, config, sonarEndpoint) {
+ data: function (sonarApi, config, sonarEndpoint) {
if (config.apiUrl && config.project) {
return sonarApi.getProjectquality(config.apiUrl, config.project);
- }
- else if (sonarEndpoint.url && config.project){
+ } else if (sonarEndpoint.url && config.project) {
return sonarApi.getProjectquality(sonarEndpoint.url, config.project);
}
return 'Please Setup the Widget';
@@ -138,7 +156,7 @@ var sonarADFWidget = angular.module('adf.widget.sonar', ['adf.provider', 'chart.
controller: 'qualityCtrl',
controllerAs: 'vm',
edit: {
- templateUrl: '{widgetsPath}/sonar/src/projectquality/edit.html'
+ templateUrl: '{widgetsPath}/sonar/src/projectquality/edit.html'
}
});
diff --git a/src/version/version.controller.js b/src/version/version.controller.js
new file mode 100644
index 0000000..6da8bf1
--- /dev/null
+++ b/src/version/version.controller.js
@@ -0,0 +1,8 @@
+'use strict';
+
+sonarADFWidget.controller('version', version);
+
+function version(data) {
+ var vm = this;
+ vm.version = data;
+}
diff --git a/src/version/view.html b/src/version/view.html
new file mode 100644
index 0000000..8e7936a
--- /dev/null
+++ b/src/version/view.html
@@ -0,0 +1,4 @@
+
+
+
{{vm.version}}
+