From 4b51fa5e5b0264d9d15b382a24c479d6b19d284c Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Thu, 2 Mar 2017 16:21:52 -0500 Subject: [PATCH] Update security scan col in repo view to use donut chart and better language --- .../directives/repo-view/repo-panel-tags.css | 13 ++++ static/css/directives/ui/donut-chart.css | 5 ++ static/css/directives/ui/image-link.css | 1 + static/directives/donut-chart.html | 1 + static/directives/image-link.html | 2 +- .../directives/repo-view/repo-panel-tags.html | 34 +++++---- .../directives/repo-view/repo-panel-tags.js | 4 +- static/js/directives/ui/donut-chart.js | 71 +++++++++++++++++++ static/js/services/vulnerability-service.js | 2 + 9 files changed, 113 insertions(+), 20 deletions(-) create mode 100644 static/css/directives/ui/donut-chart.css create mode 100644 static/directives/donut-chart.html create mode 100644 static/js/directives/ui/donut-chart.js diff --git a/static/css/directives/repo-view/repo-panel-tags.css b/static/css/directives/repo-view/repo-panel-tags.css index 0208ca3c3..446c35d85 100644 --- a/static/css/directives/repo-view/repo-panel-tags.css +++ b/static/css/directives/repo-view/repo-panel-tags.css @@ -110,6 +110,19 @@ .repo-panel-tags-element .security-scan-col .has-vulns.Defcon1 .highest-vuln { } + +.repo-panel-tags-element .security-scan-col .has-vulns { + font-size: 13px; +} + +.repo-panel-tags-element .security-scan-col .has-vulns .donut-chart { + margin-right: 4px; +} + +.repo-panel-tags-element .security-scan-col .has-vulns a { + color: ablack; +} + .repo-panel-tags-element .other-vulns { color: black; } diff --git a/static/css/directives/ui/donut-chart.css b/static/css/directives/ui/donut-chart.css new file mode 100644 index 000000000..8fde416ab --- /dev/null +++ b/static/css/directives/ui/donut-chart.css @@ -0,0 +1,5 @@ +.donut-chart-element svg { + display: inline-block; + width: auto; + vertical-align: middle; +} \ No newline at end of file diff --git a/static/css/directives/ui/image-link.css b/static/css/directives/ui/image-link.css index f7dc88382..3b08a1a86 100644 --- a/static/css/directives/ui/image-link.css +++ b/static/css/directives/ui/image-link.css @@ -21,6 +21,7 @@ width: 40px; text-align: center; color: black !important; + display: inline-block; } .image-link .id-label.cas { diff --git a/static/directives/donut-chart.html b/static/directives/donut-chart.html new file mode 100644 index 000000000..9ad7c78ed --- /dev/null +++ b/static/directives/donut-chart.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/directives/image-link.html b/static/directives/image-link.html index af4e173c1..71af47bca 100644 --- a/static/directives/image-link.html +++ b/static/directives/image-link.html @@ -7,7 +7,7 @@ bs-tooltip>V1ID SHA256 diff --git a/static/directives/repo-view/repo-panel-tags.html b/static/directives/repo-view/repo-panel-tags.html index 5907a0b6d..84f40e68b 100644 --- a/static/directives/repo-view/repo-panel-tags.html +++ b/static/directives/repo-view/repo-panel-tags.html @@ -90,7 +90,7 @@ Security Scan @@ -141,7 +141,7 @@ data-title="The image for this tag is queued to be scanned for vulnerabilities" bs-tooltip> - Queued for scan + Queued @@ -149,7 +149,7 @@ data-title="The image for this tag could not be scanned for vulnerabilities" bs-tooltip> - Unable to scan image + Unable to scan @@ -178,22 +178,20 @@ - - - - {{ getTagVulnerabilities(tag).highestVulnerability.Count }} - - - - + {{ getTagVulnerabilities(tag).vulnerabilities.length - getTagVulnerabilities(tag).highestVulnerability.Count }} others - - - - More Info + + + + + + + {{ getTagVulnerabilities(tag).featuresInfo.brokenFeaturesCount }} vulnerable packages + + + {{ getTagVulnerabilities(tag).featuresInfo.fixableFeatureCount }} fixable packages + diff --git a/static/js/directives/repo-view/repo-panel-tags.js b/static/js/directives/repo-view/repo-panel-tags.js index 71568b11c..f89c3b5a4 100644 --- a/static/js/directives/repo-view/repo-panel-tags.js +++ b/static/js/directives/repo-view/repo-panel-tags.js @@ -213,7 +213,8 @@ angular.module('quay').directive('repoPanelTags', function () { highest = { 'Priority': vuln.Severity, 'Count': 1, - 'index': VulnerabilityService.LEVELS[vuln.Severity].index + 'index': VulnerabilityService.LEVELS[vuln.Severity].index, + 'Color': VulnerabilityService.LEVELS[vuln.Severity].color } } else if (VulnerabilityService.LEVELS[vuln.Severity].index == highest.index) { highest['Count']++; @@ -226,6 +227,7 @@ angular.module('quay').directive('repoPanelTags', function () { imageData.hasVulnerabilities = !!vulnerabilities.length; imageData.vulnerabilities = vulnerabilities; imageData.highestVulnerability = highest; + imageData.featuresInfo = VulnerabilityService.buildFeaturesInfo(null, resp); } }, function() { imageData.loading = false; diff --git a/static/js/directives/ui/donut-chart.js b/static/js/directives/ui/donut-chart.js new file mode 100644 index 000000000..9e6ae2542 --- /dev/null +++ b/static/js/directives/ui/donut-chart.js @@ -0,0 +1,71 @@ +/** + * An element which displays a donut chart of data. + */ +angular.module('quay').directive('donutChart', function () { + var directiveDefinitionObject = { + priority: 0, + templateUrl: '/static/directives/donut-chart.html', + replace: false, + transclude: false, + restrict: 'C', + scope: { + 'width': '@width', + 'data': '=data', + }, + controller: function($scope, $element) { + $scope.created = false; + + // Based on: http://bl.ocks.org/erichoco/6694616 + var chart = d3.select($element.find('.donut-chart-element')[0]); + + var renderChart = function() { + if (!$scope.data || !$scope.data.length) { + return; + } + + var $chart = $element.find('.donut-chart-element'); + $chart.empty(); + + var width = $scope.width * 1; + var chart_m = width / 2 * 0.14; + var chart_r = width / 2 * 0.85; + + var topG = chart.append('svg:svg') + .attr('width', (chart_r + chart_m) * 2) + .attr('height', (chart_r + chart_m) * 2) + .append('svg:g') + .attr('class', 'donut') + .attr('transform', 'translate(' + (chart_r + chart_m) + ',' + + (chart_r + chart_m) + ')'); + + + var arc = d3.svg.arc() + .innerRadius(chart_r * 0.6) + .outerRadius(function(d, i) { + return i == $scope.data.length - 1 ? chart_r * 1.2 : chart_r * 1; + }); + + var pie = d3.layout.pie() + .sort(null) + .value(function(d) { + return d.value; + }); + + var reversed = $scope.data.slice(0).reverse(); + var g = topG.selectAll(".arc") + .data(pie(reversed)) + .enter().append("g") + .attr("class", "arc"); + + g.append("path") + .attr("d", arc) + .style('stroke', '#fff') + .style("fill", function(d) { return d.data.color; }); + + }; + + $scope.$watch('data', renderChart); + } + }; + return directiveDefinitionObject; +}); \ No newline at end of file diff --git a/static/js/services/vulnerability-service.js b/static/js/services/vulnerability-service.js index 6408345af..dda617ce0 100644 --- a/static/js/services/vulnerability-service.js +++ b/static/js/services/vulnerability-service.js @@ -279,6 +279,8 @@ angular.module('quay').factory('VulnerabilityService', ['Config', 'ApiService', return { 'features': features, + 'brokenFeaturesCount': features.length - totalCount, + 'fixableFeatureCount': features.filter(function(f) { return f.fixableScore > 0 }).length, 'severityBreakdown': severityBreakdown, 'highestFixableScore': highestFixableScore }