From 471e875896baf12f5fb4de43195b84936dc10e93 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Fri, 23 Aug 2024 10:29:18 -0700 Subject: [PATCH] ui: contest: support multi-column sort and add markers Make the sorting more generic (as in make it work on all columns). When more than one column is selected we sort in the reverse order of selection, JavaScript sort is stable. Highlight the sorting column and add a direction marker. Signed-off-by: Jakub Kicinski --- ui/contest.html | 2 +- ui/contest.js | 51 +++++++++++++++++++++++++++++++++++++------------ ui/nipa.css | 7 +++++++ ui/nipa.js | 29 +++++++++++++++++++++++----- 4 files changed, 71 insertions(+), 18 deletions(-) diff --git a/ui/contest.html b/ui/contest.html index f5827b7..184d9af 100644 --- a/ui/contest.html +++ b/ui/contest.html @@ -114,7 +114,7 @@ Test Result Retry - Time + Time Links diff --git a/ui/contest.js b/ui/contest.js index e06a692..d957230 100644 --- a/ui/contest.js +++ b/ui/contest.js @@ -10,6 +10,33 @@ function colorify_str(value) return ret + value + ''; } +function sort_results(rows) +{ + for (const sort_key of nipa_sort_keys) { + let sort_ord = nipa_sort_get(sort_key); + + if (sort_key === "date") { + rows.sort(function(a, b) { + return sort_ord * (b.v.end - a.v.end); + }); + } else if (sort_key === "time") { + rows.sort(function(a, b) { + if (a.r[sort_key] === undefined && b.r[sort_key] === undefined) + return 0; + if (a.r[sort_key] === undefined) + return 1; + if (b.r[sort_key] === undefined) + return -1; + return sort_ord * (b.r[sort_key] - a.r[sort_key]); + }); + } else { + rows.sort(function(a, b) { + return sort_ord * (b.r[sort_key] < a.r[sort_key] ? 1 : -1); + }); + } + } +} + function load_result_table(data_raw) { var table = document.getElementById("results"); @@ -69,17 +96,13 @@ function load_result_table(data_raw) }); }); - let sort_time = nipa_sort_get('time'); - if (sort_time) - rows.sort(function(a, b) { - if (a.r.time === undefined && b.r.time === undefined) - return 0; - if (a.r.time === undefined) - return 1; - if (b.r.time === undefined) - return -1; - return sort_time * (b.r.time - a.r.time); - }); + // Trim the time, so that sort behavior matches what user sees + for (const result of rows) { + if (result.r.time) + result.r.time = Math.round(result.r.time); + } + + sort_results(rows); for (const result of rows) { const r = result.r; @@ -110,7 +133,7 @@ function load_result_table(data_raw) if ("retry" in r) retry.innerHTML = colorify_str(r.retry); if ("time" in r) - time.innerHTML = nipa_msec_to_str(Math.round(r.time) * 1000); + time.innerHTML = nipa_msec_to_str(r.time * 1000); res.innerHTML = colorify_str(r.result); outputs.innerHTML = "outputs"; hist.innerHTML = "history"; @@ -172,6 +195,10 @@ function loaded_one() if (--xfr_todo) return; + let headers = document.getElementsByTagName("th"); + for (const th of headers) { + th.addEventListener("click", nipa_sort_key_set); + } reload_select_filters(true); nipa_filters_enable(reload_data, "ld-pw"); nipa_filters_enable(results_update, "fl-pw"); diff --git a/ui/nipa.css b/ui/nipa.css index 81eea5e..5033da3 100644 --- a/ui/nipa.css +++ b/ui/nipa.css @@ -27,6 +27,10 @@ tr:nth-child(even) { font-style: italic; } +.column-sorted { + background-color: #d0d0d0; +} + .box-pass { background-color: green; } .box-skip { background-color: royalblue; } .box-flake { background-color: red; } @@ -92,4 +96,7 @@ tr:nth-child(even) { .end-row td { border-color: #202020; } + .column-sorted { + background-color: #484848; + } } diff --git a/ui/nipa.js b/ui/nipa.js index 9a89b53..6ec15e4 100644 --- a/ui/nipa.js +++ b/ui/nipa.js @@ -171,27 +171,46 @@ var nipa_sort_cb = null; let nipa_sort_keys = []; let nipa_sort_polarity = []; -function nipa_sort_key_set(what) +function nipa_sort_key_set(event) { + let elem = event.target; + let what = elem.innerText.toLowerCase().replace(/[^a-z0-9]/g, ''); const index = nipa_sort_keys.indexOf(what); let polarity = 1; if (index != -1) { - polarity = -1 * nipa_sort_polarity[index]; + polarity = nipa_sort_polarity[index]; + + // if it's the main sort key invert direction, otherwise we're changing + // order of keys but not their direction + let main_key = index == nipa_sort_keys.length - 1; + if (main_key) + polarity *= -1; + // delete it nipa_sort_keys.splice(index, 1); nipa_sort_polarity.splice(index, 1); + elem.innerText = elem.innerText.slice(0, -2); // We flipped back to normal polarity, that's a reset - if (polarity == 1) { + if (main_key && polarity == 1) { + elem.classList.remove('column-sorted'); nipa_sort_cb(); return; } + } else { + elem.classList.add('column-sorted'); + } + + if (polarity == 1) { + elem.innerHTML = elem.innerText + " ⯆"; + } else { + elem.innerHTML = elem.innerText + " ⯅"; } // add it - nipa_sort_keys.unshift(what); - nipa_sort_polarity.unshift(polarity); + nipa_sort_keys.push(what); + nipa_sort_polarity.push(polarity); nipa_sort_cb(); }