Skip to content

Commit 72d7e9a

Browse files
committed
Added PoC implementation for Common components: Score badge, Severity bar chart panel
1 parent c9363e1 commit 72d7e9a

File tree

6 files changed

+323
-39
lines changed

6 files changed

+323
-39
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<template>
2+
<div class="badge" :class="severity">
3+
<div v-if="score && scoreType" class="text">{{ score }} ({{ scoreType }})</div>
4+
<div v-else class="text na">n/a</div>
5+
</div>
6+
</template>
7+
8+
<script>
9+
export default {
10+
name: 'ScoreBadge',
11+
props: {
12+
score: Number,
13+
scoreType: String
14+
},
15+
computed: {
16+
severity() {
17+
if (!this.score) {
18+
return 'na';
19+
} else if (this.score >= 9.5) {
20+
return 'critical';
21+
} else if (this.score >= 8.0) {
22+
return 'high';
23+
} else if (this.score >= 6.0) {
24+
return 'medium';
25+
} else {
26+
return 'low';
27+
}
28+
}
29+
}
30+
}
31+
</script>
32+
33+
<style lang="scss" scoped>
34+
.badge {
35+
/* layout */
36+
display: flex;
37+
justify-content: center;
38+
align-items: center;
39+
flex: 1 0 0;
40+
align-self: stretch;
41+
/* style */
42+
border-radius: 4px;
43+
44+
&.critical {
45+
background: #850917;
46+
}
47+
48+
&.high {
49+
background: #DE2136;
50+
}
51+
52+
&.medium {
53+
background: #FF8533;
54+
}
55+
56+
&.low {
57+
background: #EEC707;
58+
}
59+
60+
&.na{
61+
background: #DCDEE7;
62+
}
63+
64+
.text {
65+
color: rgba(255, 255, 255, 0.90);
66+
font-family: Lato;
67+
font-size: 13px;
68+
font-style: normal;
69+
font-weight: 500;
70+
line-height: 20px; /* 153.846% */
71+
&.na {
72+
color: #717179;
73+
}
74+
}
75+
}
76+
</style>
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<template>
2+
<div class="severity-bar-chart">
3+
<div class="severity-heading">
4+
<span class="vul-total">{{ total }}</span>
5+
<span class="vul-desc">vulnerabilities in total</span>
6+
</div>
7+
<div class="severity-chart">
8+
<div v-for="(value, key) in severityData" :key="key" class="severity-item">
9+
<div class="severity-item-name">{{ key }}</div>
10+
<PercentageBar :modelValue="percentage(value)" style="width: 314px" />
11+
<div class="severity-item-value"> {{ value }}</div>
12+
</div>
13+
</div>
14+
</div>
15+
</template>
16+
17+
<script>
18+
import PercentageBar from '@shell/components/PercentageBar.vue';
19+
20+
export default {
21+
name: 'SeverityBarChart',
22+
components: {
23+
PercentageBar,
24+
},
25+
props: {
26+
severityData: {
27+
type: Object,
28+
required: true
29+
}
30+
},
31+
methods: {
32+
percentage(value) {
33+
return (value / this.total) * 100;
34+
}
35+
},
36+
computed: {
37+
total() {
38+
return Object.values(this.severityData).reduce((sum, value) => sum + value, 0);
39+
},
40+
}
41+
}
42+
</script>
43+
44+
<style lang="scss" scoped>
45+
.severity-bar-chart {
46+
display: flex;
47+
padding: 8px 0px;
48+
align-items: flex-start;
49+
gap: 24px;
50+
align-self: stretch;
51+
52+
.severity-heading {
53+
display: flex;
54+
width: 160px;
55+
flex-direction: column;
56+
justify-content: center;
57+
align-items: center;
58+
gap: 4px;
59+
align-self: stretch;
60+
61+
.vul-total {
62+
color: #141419;
63+
font-family: Lato;
64+
font-size: 24px;
65+
font-style: normal;
66+
font-weight: 800;
67+
line-height: normal;
68+
}
69+
70+
.vul-desc {
71+
color: #6C6C76;
72+
font-family: Lato;
73+
font-size: 14px;
74+
font-style: normal;
75+
font-weight: 400;
76+
line-height: normal;
77+
}
78+
}
79+
80+
.severity-chart {
81+
display: flex;
82+
flex-direction: column;
83+
align-items: flex-start;
84+
gap: 4px;
85+
flex: 1 0 0;
86+
87+
.severity-item {
88+
display: flex;
89+
justify-content: flex-end;
90+
align-items: center;
91+
gap: 12px;
92+
align-self: stretch;
93+
94+
.severity-item-name {
95+
display: flex;
96+
width: 80px;
97+
align-items: center;
98+
gap: 12px;
99+
align-self: stretch;
100+
}
101+
102+
.severity-item-value {
103+
display: flex;
104+
width: 45px;
105+
justify-content: flex-end;
106+
align-items: center;
107+
gap: 12px;
108+
align-self: stretch;
109+
}
110+
}
111+
}
112+
}
113+
</style>
Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,44 @@
1-
import { IPlugin } from '@shell/core/types';
2-
import { PRODUCT_NAME, PAGE } from '@sbombastic-image-vulnerability-scanner/types';
1+
import { IPlugin } from "@shell/core/types";
2+
import {
3+
PRODUCT_NAME,
4+
PAGE,
5+
} from "@sbombastic-image-vulnerability-scanner/types";
36

47
export function init($plugin: IPlugin, store: any) {
8+
const { product, virtualType, basicType } = $plugin.DSL(store, PRODUCT_NAME);
59

6-
const {
7-
product,
8-
virtualType,
9-
basicType
10-
} = $plugin.DSL(store, PRODUCT_NAME);
10+
// registering a cluster-level product
11+
product({
12+
icon: "pod_security",
13+
inStore: "cluster",
14+
});
1115

12-
// registering a cluster-level product
13-
product({
14-
icon: 'pod_security',
15-
inStore: 'cluster',
16-
});
16+
// => => => creating a custom page
17+
virtualType({
18+
label: store.getters["i18n/t"]("image_scanner.registries.title"),
19+
name: PAGE.REGISTRIES,
20+
namespaced: false,
21+
route: {
22+
name: `c-cluster-${PRODUCT_NAME}-${PAGE.REGISTRIES}`,
23+
params: {
24+
product: PRODUCT_NAME,
25+
},
26+
meta: { pkg: PRODUCT_NAME, product: PRODUCT_NAME },
27+
},
28+
});
1729

18-
// => => => creating a custom page
19-
virtualType({
20-
label: store.getters['i18n/t']('image_scanner.registries.title'),
21-
name: PAGE.REGISTRIES,
22-
namespaced: false,
23-
route: {
24-
name: `c-cluster-${PRODUCT_NAME}-${PAGE.REGISTRIES}`,
25-
params: {
26-
product: PRODUCT_NAME
27-
},
28-
meta: { pkg: PRODUCT_NAME, product: PRODUCT_NAME }
29-
}
30-
});
30+
virtualType({
31+
label: store.getters["i18n/t"]("image_scanner.vulnerabilities.title"),
32+
name: PAGE.VULNERABILITY_OVERVIEW,
33+
namespaced: false,
34+
route: {
35+
name: `c-cluster-${PRODUCT_NAME}-${PAGE.VULNERABILITY_OVERVIEW}`,
36+
params: {
37+
product: PRODUCT_NAME,
38+
},
39+
meta: { pkg: PRODUCT_NAME, product: PRODUCT_NAME },
40+
},
41+
});
3142

32-
basicType([
33-
PAGE.REGISTRIES
34-
]);
35-
}
43+
basicType([PAGE.REGISTRIES, PAGE.VULNERABILITY_OVERVIEW]);
44+
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
image_scanner:
22
registries:
3-
title: Registries
3+
title: Registries
4+
vulnerabilities:
5+
title: Vulnerabilities
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<template>
2+
<div class="page">
3+
<div class="header">
4+
<h1>Vulnerabilities</h1>
5+
</div>
6+
<div class="charts">
7+
<SeverityBarChart :severityData="severityData" />
8+
</div>
9+
<div class="table">
10+
<ScoreBadge :score="7.8" :scoreType="'v2'" style="width: 123px; height: 24px;"/>
11+
</div>
12+
</div>
13+
</template>
14+
15+
<script>
16+
import ScoreBadge from '../../../../components/common/ScoreBadge.vue';
17+
import SeverityBarChart from '../../../../components/common/SeverityBarChart.vue';
18+
19+
export default {
20+
name: 'vulnerabilities',
21+
components: {
22+
ScoreBadge,
23+
SeverityBarChart
24+
},
25+
data() {
26+
return {
27+
severityData: {
28+
Critical: 1627,
29+
High: 353,
30+
Medium: 246,
31+
Low: 65,
32+
None: 293,
33+
}
34+
};
35+
}
36+
}
37+
</script>
38+
39+
<style lang="scss" scoped>
40+
.page {
41+
display: flex;
42+
padding: 24px;
43+
flex-direction: column;
44+
align-items: flex-start;
45+
gap: 24px;
46+
flex: 1 0 0;
47+
align-self: stretch;
48+
}
49+
50+
.header {
51+
display: flex;
52+
align-items: flex-start;
53+
gap: 24px;
54+
align-self: stretch;
55+
}
56+
57+
.charts {
58+
/* layout */
59+
display: flex;
60+
align-items: flex-start;
61+
align-self: stretch;
62+
/* style */
63+
border-radius: 6px;
64+
border: 1px solid #DCDEE7;
65+
background: #FFF;
66+
}
67+
68+
.table {
69+
display: flex;
70+
flex-direction: column;
71+
align-items: flex-start;
72+
gap: 24px;
73+
align-self: stretch;
74+
}
75+
</style>
Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
1-
import Registries from '@sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/registries.vue'
2-
import { PRODUCT_NAME, PAGE } from '@sbombastic-image-vulnerability-scanner/types';
1+
import Registries from "@sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/registries.vue";
2+
import Vulnerabilities from "@sbombastic-image-vulnerability-scanner/pages/c/_cluster/sbombastic-image-vulnerability-scanner/vulnerabilities.vue";
3+
import {
4+
PRODUCT_NAME,
5+
PAGE,
6+
} from "@sbombastic-image-vulnerability-scanner/types";
37

48
const routes = [
5-
{
6-
name: `c-cluster-${ PRODUCT_NAME }-${PAGE.REGISTRIES}`,
7-
path: `/c/:cluster/${ PRODUCT_NAME }/${PAGE.REGISTRIES}`,
8-
component: Registries
9-
}
10-
]
9+
{
10+
name: `c-cluster-${PRODUCT_NAME}-${PAGE.REGISTRIES}`,
11+
path: `/c/:cluster/${PRODUCT_NAME}/${PAGE.REGISTRIES}`,
12+
component: Registries,
13+
},
14+
{
15+
name: `c-cluster-${PRODUCT_NAME}-${PAGE.VULNERABILITY_OVERVIEW}`,
16+
path: `/c/:cluster/${PRODUCT_NAME}/${PAGE.VULNERABILITY_OVERVIEW}`,
17+
component: Vulnerabilities,
18+
},
19+
];
1120

12-
export default routes;
21+
export default routes;

0 commit comments

Comments
 (0)