Skip to content

Commit dbe326f

Browse files
Rewote percentageBar and Bar, Implemented severity beased color on the bar
1 parent 1a35143 commit dbe326f

File tree

7 files changed

+267
-33
lines changed

7 files changed

+267
-33
lines changed

pkg/sbombastic-image-vulnerability-scanner/components/ImageRiskAssessment.vue

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<template>
22
<div class="chart-area">
33
<div class="title">
4-
Most affected images at risk
4+
{{ t('imageScanner.images.imageBySeverityChart.title') }}
55
</div>
66
<div class="severity-bar-chart">
7-
<SeverityBarChart :severityData="severityData" />
7+
<SeverityBarChart :severityData="severityData" :description="t('imageScanner.images.imageBySeverityChart.subTitle')" />
88
</div>
99
</div>
1010
</template>
@@ -23,17 +23,7 @@
2323
required: true
2424
}
2525
},
26-
data() {
27-
return {
28-
severityData: {
29-
Critical: 1627,
30-
High: 353,
31-
Medium: 246,
32-
Low: 65,
33-
None: 293,
34-
}
35-
};
36-
}
26+
data() {}
3727
}
3828
</script>
3929

pkg/sbombastic-image-vulnerability-scanner/components/common/SeverityBarChart.vue

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22
<div class="severity-bar-chart">
33
<div class="severity-heading">
44
<span class="vul-total">{{ total }}</span>
5-
<span class="vul-desc">vulnerabilities in total</span>
5+
<span class="vul-desc">{{ description }}</span>
66
</div>
77
<div class="severity-chart">
88
<div v-for="(value, key) in severityData" :key="key" class="severity-item">
9-
<div class="severity-item-name">{{ key }}</div>
10-
<PercentageBar class="severity-item-bar" :modelValue="percentage(value)" />
9+
<div class="severity-item-name">{{ t(`imageScanner.enum.severity.${ key }`) }}</div>
10+
<PercentageBar class="severity-item-bar" :colorStops="{0: `--cve-${ key }`}" :value="percentage(value)" :height="7"/>
1111
<div class="severity-item-value"> {{ value }}</div>
1212
</div>
1313
</div>
1414
</div>
1515
</template>
1616

1717
<script>
18-
import PercentageBar from '@shell/components/PercentageBar.vue';
18+
import PercentageBar from '@sbombastic-image-vulnerability-scanner/components/rancher-rewritten/shell/components/PercentageBar';
1919
2020
export default {
2121
name: 'SeverityBarChart',
@@ -26,7 +26,11 @@ export default {
2626
severityData: {
2727
type: Object,
2828
required: true
29-
}
29+
},
30+
description: {
31+
type: String,
32+
required: true
33+
},
3034
},
3135
methods: {
3236
percentage(value) {
@@ -84,10 +88,10 @@ export default {
8488
flex-direction: column;
8589
gap: 4px;
8690
flex: 3;
87-
8891
.severity-item {
8992
display: flex;
9093
align-items: center;
94+
margin: 2px 0;
9195
gap: 12px;
9296
9397
.severity-item-name {
@@ -100,15 +104,22 @@ export default {
100104
flex: 1;
101105
overflow: hidden;
102106
}
107+
103108
.severity-item-value {
104-
width: 30px;
109+
width: 50px;
105110
text-align: right;
106111
align-items: left;
107112
gap: 12px;
108113
}
109-
110-
111114
}
112115
}
116+
117+
118+
--cve-critical: #880E1E;
119+
--cve-high: #DE2136;
120+
--cve-medium: #FF8533;
121+
--cve-low: #EEC707;
122+
--cve-none: #DCDEE7;
123+
--border: #F4F5FA;
113124
}
114125
</style>
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<script>
2+
import Bar from '@sbombastic-image-vulnerability-scanner/components/rancher-rewritten/shell/components/graph/Bar';
3+
import { formatPercent } from '@shell/utils/string';
4+
5+
export const PreferredDirection = {
6+
LESS: 'LESS',
7+
MORE: 'MORE'
8+
};
9+
10+
/**
11+
* A percentage bar which can be used to display how much a resource is being consumed.
12+
*/
13+
export default {
14+
components: { Bar },
15+
props: {
16+
/**
17+
* A value representing the percentage to be displayed. *Must be a value between 0 and 100*.
18+
*/
19+
value: {
20+
type: Number,
21+
required: true,
22+
validator(value) {
23+
return value >= 0;
24+
}
25+
},
26+
27+
/**
28+
* A value which indicates which direction is better so we can change the color appropriately (Valid values: 'LESS' or 'MORE')
29+
*/
30+
preferredDirection: {
31+
type: String,
32+
default: PreferredDirection.LESS
33+
},
34+
35+
/**
36+
* Determines whether we display the numerical percentage value to the right of the bar.
37+
*/
38+
showPercentage: {
39+
type: Boolean,
40+
default: false
41+
},
42+
43+
/**
44+
* Optional map of percentage:color class stops to apply to bar
45+
*/
46+
47+
colorStops: {
48+
type: Object,
49+
default: null
50+
},
51+
52+
/**
53+
* Show vertical lines to denote where multiple sources that are contributing to this percentage end
54+
*/
55+
slices: {
56+
type: Array,
57+
default: () => []
58+
},
59+
60+
/**
61+
* Define the height of the percentage bar
62+
*/
63+
height: {
64+
type: Number,
65+
default: 15
66+
}
67+
},
68+
69+
computed: {
70+
primaryColor() {
71+
const isLess = this.preferredDirection === PreferredDirection.LESS;
72+
73+
if (this.colorStops) {
74+
const thresholds = Object.keys(this.colorStops).sort();
75+
76+
if (isLess) {
77+
let i = thresholds.length - 1;
78+
79+
while (this.value < thresholds[i]) {
80+
i--;
81+
}
82+
83+
return this.colorStops[thresholds[i]];
84+
} else {
85+
let i = 0;
86+
87+
while (this.value > thresholds[i]) {
88+
i++;
89+
}
90+
91+
return this.colorStops[thresholds[i]];
92+
}
93+
}
94+
const threshold = isLess ? 80 : 20;
95+
96+
const left = isLess ? this.value : threshold;
97+
const right = isLess ? threshold : this.value;
98+
99+
if (left <= right) {
100+
return '--primary';
101+
}
102+
103+
return '--error';
104+
},
105+
formattedPercentage() {
106+
return formatPercent(this.value);
107+
}
108+
},
109+
};
110+
</script>
111+
112+
<template>
113+
<span class="percentage-bar">
114+
<Bar
115+
:percentage="value"
116+
:primary-color="primaryColor"
117+
:slices="slices"
118+
:height="height"
119+
/>
120+
<span
121+
v-if="showPercentage"
122+
class="ml-5 percentage-value"
123+
>{{ formattedPercentage }}</span>
124+
</span>
125+
</template>
126+
127+
<style lang="scss" scoped>
128+
.percentage-bar {
129+
display: flex;
130+
flex-direction: row;
131+
132+
.percentage-value {
133+
word-break: keep-all;
134+
}
135+
}
136+
</style>
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<script>
2+
export default {
3+
props: {
4+
percentage: {
5+
type: Number,
6+
required: true
7+
},
8+
primaryColor: {
9+
type: String,
10+
default: '--primary'
11+
},
12+
secondaryColor: {
13+
type: String,
14+
default: '--border'
15+
},
16+
slices: {
17+
type: Array,
18+
default: () => []
19+
},
20+
height: {
21+
type: Number,
22+
default: 15
23+
}
24+
},
25+
computed: {
26+
indicatorStyle() {
27+
return {
28+
width: `${ this.percentage }%`,
29+
height: `${ this.height }px`,
30+
backgroundColor: `var(${ this.primaryColor })`
31+
};
32+
},
33+
barStyle() {
34+
return {
35+
backgroundColor: `var(${ this.secondaryColor })`,
36+
height: `${ this.height }px`,
37+
borderRadius: `${ this.height / 2 }px`,
38+
};
39+
},
40+
sliceStyles() {
41+
return this.slices.map((slice) => ({
42+
left: `${ slice }%`,
43+
visibility: slice < this.percentage ? 'visible' : 'hidden'
44+
}));
45+
}
46+
}
47+
};
48+
</script>
49+
50+
<template>
51+
<div
52+
class="bar"
53+
:style="barStyle"
54+
>
55+
<div
56+
class="indicator"
57+
:style="indicatorStyle"
58+
/>
59+
<div
60+
v-for="(sliceStyle, i) in sliceStyles"
61+
:key="i"
62+
class="slice"
63+
:style="sliceStyle"
64+
/>
65+
</div>
66+
</template>
67+
68+
<style lang="scss" scoped>
69+
.bar {
70+
width: 100%;
71+
overflow: hidden;
72+
position: relative;
73+
74+
.indicator {
75+
height: 100%;
76+
}
77+
78+
.slice {
79+
position: absolute;
80+
top: 0;
81+
bottom: 0;
82+
width: 1px;
83+
background-color: var(--body-bg);
84+
}
85+
}
86+
</style>

pkg/sbombastic-image-vulnerability-scanner/l10n/en-us.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ imageScanner:
44
images:
55
title: Images
66
downloadReport: Download full report
7+
imageBySeverityChart:
8+
title: Most affected images at risk
9+
subTitle: images in total
710
filters:
811
image:
912
allImages: All images
@@ -19,4 +22,12 @@ imageScanner:
1922
registry: Registry
2023
vulnerabilities:
2124
title: Vulnerabilities
25+
enum:
26+
severity:
27+
critical: Critical
28+
high: High
29+
medium: Medium
30+
low: Low
31+
none: None
32+
2233

pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/ImageOverview.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,11 +165,11 @@
165165
},
166166
],
167167
severityData: {
168-
Critical: 1627,
169-
High: 353,
170-
Medium: 246,
171-
Low: 65,
172-
None: 293,
168+
critical: 1627,
169+
high: 353,
170+
medium: 246,
171+
low: 1265,
172+
none: 293,
173173
},
174174
filterCveOptions,
175175
filterImageOptions,

pkg/sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/vulnerabilities.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<h1>Vulnerabilities</h1>
55
</div>
66
<div class="charts">
7-
<SeverityBarChart :severityData="severityData" />
7+
<SeverityBarChart :severityData="severityData" description="vulnerabilities in total"/>
88
</div>
99
<div class="table">
1010
<ScoreBadge :score="7.8" :scoreType="'v2'" style="width: 123px; height: 24px;"/>
@@ -25,11 +25,11 @@
2525
data() {
2626
return {
2727
severityData: {
28-
Critical: 1627,
29-
High: 353,
30-
Medium: 246,
31-
Low: 65,
32-
None: 293,
28+
critical: 1627,
29+
high: 353,
30+
medium: 246,
31+
low: 1265,
32+
none: 293,
3333
}
3434
};
3535
}

0 commit comments

Comments
 (0)