Project homepage Mailing List  Warmcat.com  API Docs  Github Mirror 
    npro  
 Modern all-safe Rust Network Protocol library supporting h1, h2, h3, ws, wt sans-IO and with socket IO + tls
git clone https://npro.rs/repo/npro
Author[]Andy Green <andy@warmcat.com> 2026-09-12 10:21 UTC
Committer[]Andy Green <andy@warmcat.com> 2026-09-12 10:21 UTC
Treef1e7e857c8d78a609d77edbca8335ee33b4d42e4   Raw Patch
 
assets: task table: keep header above platform icons, duration is seconds
assets: task table: keep header above platform icons, duration is seconds

The first platform icon (img.zup) is positioned at z-index 11 so it can
overlap its siblings, which put it above the table's sticky header
(z-index 1) while scrolling.  Lift the header to 20.

The server stores a task's duration in seconds (sais_process_rej():
lws_now_secs() - first_log_timestamp), not microseconds, so dividing by
1e6 showed 0s for every finished task in the table and "Dur: 0.0s" in
the taskinfo header.  Treat it as seconds in both places.  While a task
is still building, always show now - started, since the server also
refreshes duration at each step boundary and that would otherwise stick.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
diff --git a/assets/sai.css b/assets/sai.css index 321814e..f54c72c 100644 --- a/assets/sai.css +++ b/assets/sai.css @@ -2467,7 +2467,8 @@ table.tt { table.tt th.tt-th { position: sticky; top: 0; - z-index: 1; + /* above the platform icons: img.zup is positioned at z-index 11 */ + z-index: 20; background: #f1f5f9; color: #1e293b; text-align: left; diff --git a/assets/sai.js b/assets/sai.js index ed246e1..27f63b0 100644 --- a/assets/sai.js +++ b/assets/sai.js @@ -1160,9 +1160,8 @@ function sai_taskinfo_render(t, now_ut) /* started is a unix time, in seconds */ s += "<span class=\"ti5\"> " + agify(now_ut, t.t.started) + " ago, Dur: " + - (t.t.duration ? t.t.duration / 1000000 : - now_ut - t.t.started).toFixed(1) + - "s</span><div id=\"sai_arts\"></div><div id=\"metrics-summary-" + san(t.t.uuid) + "\"></div>"; + sai_tt_fmt_dur(sai_tt_dur_secs(t.t, now_ut)) + + "</span><div id=\"sai_arts\"></div><div id=\"metrics-summary-" + san(t.t.uuid) + "\"></div>"; sai_arts = ""; } @@ -2019,13 +2018,21 @@ function sai_tt_is_ongoing(state) return state === 1 || state === 2 || state === 6 || state === 10; } -/* wallclock seconds the task took / has taken so far, or -1 if never started */ +/* + * Wallclock seconds the task has been building, or -1 if it never started. + * + * While it's still going, that's now minus the time the first step was + * accepted (t.started, unix secs). Once it reached a disposition, the + * server stored the elapsed seconds at that moment in t.duration (see + * sais_process_rej()); it also refreshes t.duration at each step boundary, + * so it must not be preferred over the live clock for an ongoing task. + */ function sai_tt_dur_secs(t, now_ut) { - if (t.duration) - return t.duration / 1000000; if (t.started && sai_tt_is_ongoing(t.state)) return Math.max(0, now_ut - t.started); + if (t.duration) + return t.duration; return -1; } @@ -2185,10 +2192,10 @@ function sai_tt_row_key(tr, key, now_ut) case "started": return parseInt(d.started) > 0 ? parseInt(d.started) : null; case "duration": - if (parseInt(d.dur) > 0) - return parseInt(d.dur) / 1000000; if (parseInt(d.started) > 0 && sai_tt_is_ongoing(state)) return now_ut - parseInt(d.started); + if (parseInt(d.dur) > 0) + return parseInt(d.dur); return null; case "step": return sai_tt_state_rank(state) * 10000 + (parseInt(d.step) + 1); @@ -2300,7 +2307,7 @@ function sai_tt_tick() rows.forEach(function(tr) { var d = tr.dataset; - if (parseInt(d.dur) > 0 || !(parseInt(d.started) > 0) || + if (!(parseInt(d.started) > 0) || !sai_tt_is_ongoing(parseInt(d.state))) return;
Page fetched 0s ago, creation time: 16ms (vhost etag hits: 0%, cache hits: 0%)