feat: dossiers-ngi sticky bar vs-main +green/−red diffstat

This commit is contained in:
Hernâni Marques 2026-09-30 16:07:28 +02:00
parent a4ec0305bc
commit 31af42538a
No known key found for this signature in database
6 changed files with 134 additions and 32 deletions

View file

@ -76,3 +76,12 @@ a.cascade-tree-row.is-active:hover {
font-size: 10px;
}
}
.cascade-bar .diff-plus {
color: #3fb950;
font-weight: 600;
}
.cascade-bar .diff-minus {
color: #f85149;
font-weight: 600;
}

View file

@ -37,23 +37,49 @@
return Math.round(n) + "s";
}
function metaBits(row) {
function metaHtml(row) {
var tip = row.tip || "";
var tipTime = row.tip_time || "";
var builtAt = row.built_at || "";
var buildSec = row.build_seconds;
var bits = [];
if (tip) bits.push("@" + tip);
if (tipTime) bits.push("tip " + shortTime(tipTime));
var parts = [];
if (tip) parts.push(esc("@" + tip));
if (tipTime) parts.push(esc("tip " + shortTime(tipTime)));
if (buildSec != null && buildSec !== "")
bits.push("build " + fmtBuildSec(buildSec));
if (builtAt) bits.push("at " + shortTime(builtAt));
return bits;
parts.push(esc("build " + fmtBuildSec(buildSec)));
if (builtAt) parts.push(esc("at " + shortTime(builtAt)));
// vs main: +grün / −rot (omit on main / when both zero absent)
var plus = row.vs_main_plus;
var minus = row.vs_main_minus;
if (plus != null || minus != null) {
var p = plus == null ? 0 : Number(plus);
var m = minus == null ? 0 : Number(minus);
if (isFinite(p) && isFinite(m) && (p > 0 || m > 0 || row.branch !== "main")) {
parts.push(
'<span class="diff-plus">+' +
esc(String(p)) +
'</span> <span class="diff-minus">−' +
esc(String(m)) +
"</span>"
);
}
}
return parts.join(" · ");
}
function rowTitle(row, buildSec) {
var tip = row.tip || "";
var tipTime = row.tip_time || "";
var plus = row.vs_main_plus;
var minus = row.vs_main_minus;
var vs = "";
if (plus != null || minus != null) {
vs =
" vs main +" +
String(plus == null ? 0 : plus) +
"/−" +
String(minus == null ? 0 : minus);
}
return (
"Switch build to " +
(row.branch || "") +
@ -61,7 +87,8 @@
(tipTime ? " tip=" + tipTime : "") +
(buildSec != null && buildSec !== ""
? " build=" + fmtBuildSec(buildSec)
: "")
: "") +
vs
);
}
@ -125,15 +152,15 @@
var a = rows[i];
if (a.getAttribute("data-edition") !== (row.edition || "")) return false;
if (a.getAttribute("data-branch") !== (row.branch || "")) return false;
var bits = metaBits(row);
var tipHtml = metaHtml(row);
var tipEl = a.querySelector(".tip");
var wantTip = bits.length ? " " + bits.join(" · ") : "";
var wantTip = tipHtml ? " " + tipHtml : "";
if (tipEl) {
if (tipEl.textContent !== wantTip) tipEl.textContent = wantTip;
if (tipEl.innerHTML !== wantTip) tipEl.innerHTML = wantTip;
} else if (wantTip) {
tipEl = document.createElement("span");
tipEl.className = "tip";
tipEl.textContent = wantTip;
tipEl.innerHTML = wantTip;
a.appendChild(tipEl);
}
var defEl = a.querySelector(".cascade-default");
@ -189,15 +216,13 @@
var tipTime = row.tip_time || "";
var buildSec = row.build_seconds;
var isDefault = branch === defaultBranch;
var bits = metaBits(row);
var tipHtml = metaHtml(row);
var label =
esc(prefix) +
"<code>" +
esc(branch) +
"</code>" +
(bits.length
? '<span class="tip"> ' + esc(bits.join(" · ")) + "</span>"
: "") +
(tipHtml ? '<span class="tip"> ' + tipHtml + "</span>" : "") +
(isDefault ? '<span class="cascade-default"> · default</span>' : "");
html.push(
'<a class="cascade-tree-row" role="treeitem" href="/_cascade/use/' +