support/scripts/pkg-stats: make cells with many CVEs collapsible

Sometimes a package can have a lot of CVEs.
Rather than have the CVE cell make a really tall row
(that means you have to scroll a bunch) this collapses the CVE
cell to a fixed size scrollable element with a
sticky button that lets you expand and collapse it.

If Javascript is enabled:

A stylesheet is generated and appended before content rendering,
amending the cells style to have a fixed height and overflow.

Also, the expand/contract button is unhidden.

This means the CVE cells are rendered in a collapsed state
instead of being rendered in an expanded state and then
slamming shut.

This avoids a "flash" and *helps* (vertically at least) manage CLS
(cumulative layout shift).

see: https://web.dev/cls/

If Javascript is disabled:

The cells stay fully open and the expand/contract button stays hidden.

Signed-off-by: Sen Hastings <sen@phobosdpl.com>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
This commit is contained in:
Sen Hastings 2022-07-28 18:23:55 -05:00 committed by Thomas Petazzoni
parent 2a592f0b2a
commit d45b5377c1

View File

@ -747,6 +747,14 @@ html_header = """
const triangleUp = String.fromCodePoint(32, 9652);
const triangleDown = String.fromCodePoint(32, 9662);
var lastColumnName = false;
const styleElement = document.createElement('style');
document.head.insertAdjacentElement("afterend", styleElement);
const styleSheet = styleElement.sheet;
const collapseRule = ".collapse{ height: 200px; overflow: hidden scroll;}"
const buttonRule = ".see-more{ display: block;}"
styleSheet.insertRule(collapseRule);
styleSheet.insertRule(buttonRule);
function sortGrid(sortLabel){
let i = 0;
@ -759,7 +767,6 @@ function sortGrid(sortLabel){
lastStyle.disable = true;
lastStyle.remove();
};
const styleElement = document.createElement('style');
styleElement.id = "sort-css";
document.head.appendChild(styleElement);
const styleSheet = styleElement.sheet;
@ -809,16 +816,37 @@ function sortGrid(sortLabel){
let rule = "." + listing[0] + " { grid-row: " + i + "; }";
styleSheet.insertRule(rule);
});
styleSheet.insertRule(collapseRule);
styleSheet.insertRule(buttonRule);
};
function expandField(fieldId){
const field = document.getElementById(fieldId);
const fieldText = field.firstElementChild.innerText;
const fieldTotal = fieldText.split(' ')[2];
if (fieldText == "see all " + fieldTotal + triangleDown){
field.firstElementChild.innerText = "see less " + fieldTotal + triangleUp;
field.style.height = "auto";
} else {
field.firstElementChild.innerText = "see all " + fieldTotal + triangleDown;
field.style.height = "200px";
}
};
</script>
<style>
.label {
.see-more{
display: none;
}
.label, .see-more {
position: sticky;
top: 1px;
}
.label{
z-index: 1;
background: white;
padding: 10px 2px 10px 2px;
}
@ -1029,6 +1057,8 @@ def dump_html_pkg(f, pkg):
data_field_id = f'cves__{pkg_css_class}'
div_class = ["centered cves data"]
div_class.append(f'_{pkg_css_class}')
if len(pkg.cves) > 10:
div_class.append("collapse")
if pkg.is_status_ok("cve"):
div_class.append("cve-ok")
elif pkg.is_status_error("cve"):
@ -1038,6 +1068,10 @@ def dump_html_pkg(f, pkg):
else:
div_class.append("cve-unknown")
f.write(f' <div id=\"{data_field_id}\" class=\"{" ".join(div_class)}\">\n')
if len(pkg.cves) > 10:
cve_total = len(pkg.cves) + 1
f.write(f' <div onclick=\"expandField(\'{data_field_id}\')\" \
class=\"see-more centered cve_ignored\">see all ({cve_total}) &#9662;</div>\n')
if pkg.is_status_error("cve"):
for cve in pkg.cves:
f.write(" <a href=\"https://security-tracker.debian.org/tracker/%s\">%s</a><br/>\n" % (cve, cve))