Skip to content

Commit f82275e

Browse files
xingzhang-suserushk014
authored andcommitted
#200: Bug: Row selection cannot be deselected in layer by grouped and repository view in Image overview and detail pages
1 parent c7bac13 commit f82275e

File tree

4 files changed

+83
-84
lines changed

4 files changed

+83
-84
lines changed

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

Lines changed: 79 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@
266266
<SortableTable
267267
v-if="safeTableData && safeTableData.length > 0"
268268
:key="`table-${isGrouped ? 'grouped' : 'ungrouped'}`"
269-
:rows="safeTableData"
269+
:rows="isGrouped ? layerData : safeTableData"
270270
:headers="isGrouped ? LAYER_BASED_TABLE : VULNERABILITY_DETAILS_TABLE"
271271
:has-advanced-filtering="false"
272272
:namespaced="false"
@@ -365,6 +365,7 @@ export default {
365365
loadedSbom: null,
366366
// Cache filtered results to prevent selection issues
367367
cachedFilteredVulnerabilities: [],
368+
layerData: [],
368369
// Download dropdown state
369370
showDownloadDropdown: false,
370371
filters: {
@@ -433,8 +434,7 @@ export default {
433434
const metadata = this.currentImage.imageMetadata;
434435
435436
if (metadata?.registryURI && metadata?.repository && metadata?.tag) {
436-
// return `${metadata.registryURI}/${metadata.repository}:${metadata.tag}`;
437-
return `${ metadata.repository.split('/')[0] }:${ metadata.tag }`;
437+
return `${ metadata.registryURI }/${ metadata.repository }:${ metadata.tag }`;
438438
}
439439
440440
// Fallback to the hash ID if metadata is not available
@@ -669,7 +669,8 @@ export default {
669669
// Safe data for SortableTable
670670
safeTableData() {
671671
if (this.isGrouped) {
672-
const layerData = this.vulnerabilitiesByLayer || [];
672+
this.layerData = this.vulnerabilitiesByLayer(this.cachedFilteredVulnerabilities) || [];
673+
const layerData = this.vulnerabilitiesByLayer(this.cachedFilteredVulnerabilities) || [];
673674
674675
return layerData.filter((item) => item && typeof item === 'object' && item.id);
675676
} else {
@@ -684,82 +685,6 @@ export default {
684685
return this.selectedVulnerabilities ? this.selectedVulnerabilities.length : 0;
685686
},
686687
687-
// Group vulnerabilities by layer (diffID) - following ImageOverview pattern
688-
vulnerabilitiesByLayer() {
689-
if (!this.vulnerabilityDetails || !Array.isArray(this.vulnerabilityDetails) || this.vulnerabilityDetails.length === 0) {
690-
return [];
691-
}
692-
693-
try {
694-
// Group vulnerabilities by diffID (layer identifier)
695-
const layerMap = new Map();
696-
697-
this.vulnerabilityDetails.forEach((vuln) => {
698-
if (!vuln || typeof vuln !== 'object') {
699-
return; // Skip invalid vulnerabilities
700-
}
701-
702-
const layerId = vuln.diffID || vuln.packagePath || this.t('imageScanner.general.unknown');
703-
const mapKey = layerId;
704-
705-
if (layerMap.has(mapKey)) {
706-
const layer = layerMap.get(mapKey);
707-
708-
if (layer && layer.vulnerabilities && Array.isArray(layer.vulnerabilities)) {
709-
layer.vulnerabilities.push(vuln);
710-
// Count severity
711-
const severity = vuln.severity?.toLowerCase() || 'none';
712-
713-
if (layer.severityCounts && layer.severityCounts[severity] !== undefined) {
714-
layer.severityCounts[severity]++;
715-
}
716-
}
717-
} else {
718-
const severityCounts = {
719-
critical: 0, high: 0, medium: 0, low: 0, none: 0
720-
};
721-
const severity = vuln.severity?.toLowerCase() || 'none';
722-
723-
if (severityCounts[severity] !== undefined) {
724-
severityCounts[severity]++;
725-
}
726-
727-
layerMap.set(mapKey, {
728-
id: mapKey,
729-
layerId: this.decodeLayerId(layerId), // Decode layer ID to show meaningful information
730-
vulnerabilities: this.formatVulnerabilityCounts(severityCounts),
731-
updated: this.getLayerUpdatedTime(layerId),
732-
size: this.getLayerSize(layerId),
733-
severityCounts,
734-
vulnerabilityList: [vuln]
735-
});
736-
}
737-
});
738-
739-
// Create severity breakdown and sort
740-
const result = Array.from(layerMap.values()).map((layer) => {
741-
if (!layer || !layer.severityCounts || !layer.vulnerabilityList || !Array.isArray(layer.vulnerabilityList)) {
742-
return null;
743-
}
744-
745-
const counts = layer.severityCounts;
746-
747-
layer.vulnerabilities = this.formatVulnerabilityCounts(counts);
748-
layer.updated = this.getLayerUpdatedTime(layer.id);
749-
layer.size = this.getLayerSize(layer.id);
750-
751-
return layer;
752-
}).filter((layer) => layer !== null && layer !== undefined).sort((a, b) => {
753-
if (!a || !b) return 0;
754-
755-
return (b.vulnerabilityList?.length || 0) - (a.vulnerabilityList?.length || 0);
756-
});
757-
758-
return result;
759-
} catch (error) {
760-
return [];
761-
}
762-
},
763688
},
764689
765690
watch: {
@@ -1381,7 +1306,80 @@ export default {
13811306
link.click();
13821307
document.body.removeChild(link);
13831308
}
1384-
}
1309+
},
1310+
1311+
// Group vulnerabilities by layer (diffID) - following ImageOverview pattern
1312+
vulnerabilitiesByLayer(vulnerabilityReport) {
1313+
try {
1314+
// Group vulnerabilities by diffID (layer identifier)
1315+
const layerMap = new Map();
1316+
1317+
vulnerabilityReport.forEach((vuln) => {
1318+
if (!vuln || typeof vuln !== 'object') {
1319+
return; // Skip invalid vulnerabilities
1320+
}
1321+
1322+
const layerId = vuln.diffID || vuln.packagePath || this.t('imageScanner.general.unknown');
1323+
const mapKey = layerId;
1324+
1325+
if (layerMap.has(mapKey)) {
1326+
const layer = layerMap.get(mapKey);
1327+
1328+
if (layer && layer.vulnerabilities && Array.isArray(layer.vulnerabilities)) {
1329+
layer.vulnerabilities.push(vuln);
1330+
// Count severity
1331+
const severity = vuln.severity?.toLowerCase() || 'none';
1332+
1333+
if (layer.severityCounts && layer.severityCounts[severity] !== undefined) {
1334+
layer.severityCounts[severity]++;
1335+
}
1336+
}
1337+
} else {
1338+
const severityCounts = {
1339+
critical: 0, high: 0, medium: 0, low: 0, none: 0
1340+
};
1341+
const severity = vuln.severity?.toLowerCase() || 'none';
1342+
1343+
if (severityCounts[severity] !== undefined) {
1344+
severityCounts[severity]++;
1345+
}
1346+
1347+
layerMap.set(mapKey, {
1348+
id: mapKey,
1349+
layerId: this.decodeLayerId(layerId), // Decode layer ID to show meaningful information
1350+
vulnerabilities: this.formatVulnerabilityCounts(severityCounts),
1351+
updated: this.getLayerUpdatedTime(layerId),
1352+
size: this.getLayerSize(layerId),
1353+
severityCounts,
1354+
vulnerabilityList: [vuln]
1355+
});
1356+
}
1357+
});
1358+
1359+
// Create severity breakdown and sort
1360+
const result = Array.from(layerMap.values()).map((layer) => {
1361+
if (!layer || !layer.severityCounts || !layer.vulnerabilityList || !Array.isArray(layer.vulnerabilityList)) {
1362+
return null;
1363+
}
1364+
1365+
const counts = layer.severityCounts;
1366+
1367+
layer.vulnerabilities = this.formatVulnerabilityCounts(counts);
1368+
layer.updated = this.getLayerUpdatedTime(layer.id);
1369+
layer.size = this.getLayerSize(layer.id);
1370+
1371+
return layer;
1372+
}).filter((layer) => layer !== null && layer !== undefined).sort((a, b) => {
1373+
if (!a || !b) return 0;
1374+
1375+
return (b.vulnerabilityList?.length || 0) - (a.vulnerabilityList?.length || 0);
1376+
});
1377+
1378+
return result;
1379+
} catch (error) {
1380+
return [];
1381+
}
1382+
},
13851383
},
13861384
};
13871385
</script>

pkg/sbombastic-image-vulnerability-scanner/edit/sbombastic.rancher.io.registry.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export default {
4242
};
4343
}
4444
45-
if ( this.value.spec.scanInterval == null) {
45+
if ( this.value.spec.scanInterval === null) {
4646
this.value.spec.scanInterval = SCAN_INTERVALS.MANUAL;
4747
}
4848

pkg/sbombastic-image-vulnerability-scanner/models/sbombastic.rancher.io.registry.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import SteveModel from '@shell/plugins/steve/steve-class';
22
import { PRODUCT_NAME, PAGE, RESOURCE } from '@pkg/types';
3-
import _ from 'lodash';
43
export default class Registry extends SteveModel {
54
get _availableActions() {
65
// Remove the default actions we don't want

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,9 +304,11 @@ export default {
304304
return imageMatch && severityMatch && repositoryMatch && registryMatch && platformMatch;
305305
});
306306
307+
this.rowsByRepo = this.preprocessData(filteredRows);
308+
307309
return {
308310
rows: filteredRows,
309-
rowsByRepo: this.preprocessData(filteredRows)
311+
rowsByRepo: this.rowsByRepo,
310312
};
311313
},
312314
customActions() {

0 commit comments

Comments
 (0)