Skip to content

Commit 48b4c51

Browse files
committed
Improve UI for Importer Panel Charts
Signed-off-by: Sampurna Pyne <sampurnapyne1710@gmail.com>
1 parent 8a5ac28 commit 48b4c51

3 files changed

Lines changed: 73 additions & 40 deletions

File tree

insights/charts/importer_panel.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,13 @@ def build_importer_package_columns(importers) -> Dict[str, Any]:
160160
"x_categories": importer_names,
161161
"columns": [
162162
["total_advisories"] + total_advisories,
163-
["advisories_without_packages"] + advisories_without_packages,
164163
["advisories_with_packages"] + advisories_with_packages,
164+
["advisories_without_packages"] + advisories_without_packages,
165165
["advisories_without_ghost_packages"] + advisories_without_ghost_packages,
166166
["advisories_with_ghost_packages"] + advisories_with_ghost_packages,
167167
],
168168
"groups": [
169-
["advisories_without_packages", "advisories_with_packages"],
169+
["advisories_with_packages", "advisories_without_packages"],
170170
["advisories_without_ghost_packages", "advisories_with_ghost_packages"],
171171
],
172172
}
@@ -176,10 +176,11 @@ def build_importer_exploit_columns(importers) -> Dict[str, Any]:
176176
"""Helper to build mappings for Exploit Coverage chart as expected by Billboard.JS"""
177177
importer_names = []
178178
total_advisories = []
179+
advisories_with_exploits = []
180+
advisories_without_exploits = []
179181
advisories_with_kev = []
180182
advisories_with_metasploit = []
181183
advisories_with_exploitdb = []
182-
advisories_without_exploits = []
183184

184185
for importer_insight in importers:
185186
importer_names.append(format_importer_name(importer_insight.importer))
@@ -193,18 +194,21 @@ def build_importer_exploit_columns(importers) -> Dict[str, Any]:
193194
+ importer_insight.advisories_with_metasploit
194195
+ importer_insight.advisories_with_exploitdb
195196
)
197+
advisories_with_exploits.append(total_with_exploits)
196198
advisories_without_exploits.append(importer_insight.total_advisories - total_with_exploits)
197199

198200
return {
199201
"x_categories": importer_names,
200202
"columns": [
201203
["total_advisories"] + total_advisories,
204+
["advisories_with_exploits"] + advisories_with_exploits,
202205
["advisories_without_exploits"] + advisories_without_exploits,
203206
["advisories_with_exploitdb"] + advisories_with_exploitdb,
204207
["advisories_with_metasploit"] + advisories_with_metasploit,
205208
["advisories_with_kev"] + advisories_with_kev,
206209
],
207210
"groups": [
208-
["advisories_with_exploitdb", "advisories_with_metasploit", "advisories_with_kev"]
211+
["advisories_with_exploits", "advisories_without_exploits"],
212+
["advisories_with_exploitdb", "advisories_with_metasploit", "advisories_with_kev"],
209213
],
210214
}

insights/static/insights/js/importer_panel.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,68 @@
88
//
99

1010
import { initDropdownChart } from './core.js';
11+
import { formatWholeNumbersOnly, getCssVar, renderers } from './renderers.js';
12+
13+
const names = {
14+
total_advisories: "Total Advisories",
15+
advisories_without_packages: "Advisories without a Package",
16+
advisories_with_packages: "Advisories with a Package",
17+
advisories_without_ghost_packages: "Advisories without a Ghost Package",
18+
advisories_with_ghost_packages: "Advisories with a Ghost Package",
19+
advisories_without_exploits: "Advisories without an Exploit",
20+
advisories_with_exploitdb: "Advisories with Exploit-DB",
21+
advisories_with_metasploit: "Advisories with Metasploit",
22+
advisories_with_kev: "Advisories with KEV",
23+
advisories_with_exploits: "Advisories with an Exploit",
24+
};
25+
26+
function renderImporterBar(id, config) {
27+
// Get the total count of the importer from config.columns
28+
const totals = config.columns.find((c) => c[0] === "total_advisories");
29+
30+
bb.generate({
31+
bindto: `#chart-${id}`,
32+
data: {
33+
x: "x",
34+
columns: [["x", ...config.x_categories], ...config.columns],
35+
type: "bar",
36+
order: null,
37+
hide: ["total_advisories"],
38+
colors: {
39+
advisories_with_packages: getCssVar("--bulma-primary"),
40+
advisories_without_packages: getCssVar("--bulma-danger"),
41+
advisories_with_exploits: getCssVar("--bulma-primary"),
42+
advisories_without_exploits: getCssVar("--bulma-danger"),
43+
advisories_with_kev: getCssVar("--bulma-warning"),
44+
advisories_with_metasploit: getCssVar("--bulma-purple"),
45+
advisories_with_exploitdb: getCssVar("--bulma-link"),
46+
advisories_with_ghost_packages: getCssVar("--bulma-orange"),
47+
advisories_without_ghost_packages: getCssVar("--bulma-primary-dark"),
48+
},
49+
names,
50+
groups: config.groups,
51+
},
52+
axis: {
53+
rotated: true,
54+
x: { type: "category" },
55+
y: { tick: { format: formatWholeNumbersOnly } },
56+
},
57+
bar: { width: { ratio: 0.8 } },
58+
tooltip: {
59+
grouped: true,
60+
format: {
61+
title: (x) => `${config.x_categories[x]} (Total: ${totals?.[x + 1]?.toLocaleString()})`,
62+
value: (val) => val.toLocaleString(),
63+
},
64+
},
65+
legend: {
66+
show: true,
67+
hide: ["total_advisories"],
68+
},
69+
});
70+
}
71+
72+
renderers.importer_bar = renderImporterBar;
1173

1274
document.addEventListener('insightsDataLoaded', (e) => {
1375
if (e.detail.panelId !== "importer_panel") return;

insights/static/insights/js/renderers.js

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// See https://aboutcode.org for more information about nexB OSS projects.
88
//
99

10-
const getCssVar = (name) => getComputedStyle(document.documentElement).getPropertyValue(name).trim();
10+
export const getCssVar = (name) => getComputedStyle(document.documentElement).getPropertyValue(name).trim();
1111

1212
const paletteVars = [
1313
"--bulma-primary",
@@ -31,7 +31,7 @@ const getBucketColors = () => [
3131
getCssVar("--bulma-danger"), getCssVar("--bulma-danger") // 8-9: Danger
3232
];
3333

34-
const formatWholeNumbersOnly = x => Number.isInteger(x) ? x : "";
34+
export const formatWholeNumbersOnly = (x) => (Number.isInteger(x) ? x : "");
3535

3636
export const renderers = {
3737
donut(id, config) {
@@ -75,39 +75,6 @@ export const renderers = {
7575
});
7676
},
7777

78-
importer_bar(id, config) {
79-
bb.generate({
80-
bindto: `#chart-${id}`,
81-
data: {
82-
x: "x",
83-
columns: [["x", ...config.x_categories], ...config.columns],
84-
type: "bar",
85-
colors: {
86-
total_advisories: getCssVar("--bulma-link"),
87-
advisories_with_packages: getCssVar("--bulma-primary"),
88-
advisories_without_packages: getCssVar("--bulma-danger"),
89-
advisories_with_exploits: getCssVar("--bulma-success"),
90-
advisories_without_exploits: getCssVar("--bulma-danger"),
91-
advisories_with_kev: getCssVar("--bulma-warning"),
92-
advisories_with_metasploit: getCssVar("--bulma-purple"),
93-
advisories_with_exploitdb: getCssVar("--bulma-success"),
94-
advisories_with_ghost_packages: getCssVar("--bulma-orange"),
95-
advisories_without_ghost_packages: getCssVar("--bulma-primary-dark"),
96-
},
97-
names: {
98-
total_advisories: "All Advisories", advisories_with_packages: "Advisories with a Package",
99-
advisories_without_packages: "Advisories without a Package", advisories_with_exploits: "Advisories with an Exploit",
100-
advisories_without_exploits: "Advisories without an Exploit", advisories_with_kev: "Advisories with KEV",
101-
advisories_with_metasploit: "Advisories with Metasploit", advisories_with_exploitdb: "Advisories with Exploit-DB",
102-
advisories_with_ghost_packages: "Advisories with a Ghost Package", advisories_without_ghost_packages: "Advisories without a Ghost Package"
103-
},
104-
groups: config.groups
105-
},
106-
axis: { rotated: true, x: { type: "category" }, y: { tick: { format: formatWholeNumbersOnly } } },
107-
bar: { width: { ratio: 0.8 } }, tooltip: { grouped: true }, legend: { show: true }
108-
});
109-
},
110-
11178
scatter(id, config) {
11279
const [, ...buckets] = config.columns[0];
11380
const [, ...counts] = config.columns[1];
@@ -158,7 +125,7 @@ export const renderers = {
158125
color: (defaultColor, dataPoint) => dataPoint.x !== undefined ? getBucketColors()[dataPoint.x] || defaultColor : defaultColor,
159126
labels: false
160127
},
161-
bubble: { maxR: 55 },
128+
bubble: { maxR: 45 },
162129
axis: {
163130
x: {
164131
type: "category",

0 commit comments

Comments
 (0)