dashboard frontend: consume rfc3339 timestamps from the api
This commit is contained in:
parent
bac2c0a65e
commit
cafef519a9
5 changed files with 46 additions and 33 deletions
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import { $, el, form, Panel, appendLinkified } from './common.js';
|
||||
import { themedToast } from './modal.js';
|
||||
import { fmtAgo, fmtDuration } from './util.js';
|
||||
import { epochSec, fmtAgo, fmtDuration } from './util.js';
|
||||
import { questionsState, QUESTION_HISTORY_LIMIT } from './state.js';
|
||||
|
||||
// Registered by the dashboard entry at boot; defaults to a no-op so the
|
||||
|
|
@ -70,7 +70,7 @@ function renderOperatorInbox() {
|
|||
`✓ mark all read (${operatorInbox.length})`);
|
||||
mark.addEventListener('click', markOperatorInboxRead);
|
||||
root.append(el('div', { class: 'inbox-toolbar' }, mark));
|
||||
const fmt = (n) => new Date(n * 1000).toISOString().replace('T', ' ').slice(0, 19);
|
||||
const fmt = (ts) => new Date(ts).toISOString().replace('T', ' ').slice(0, 19);
|
||||
const ul = el('ul', { class: 'inbox' });
|
||||
for (const m of operatorInbox) {
|
||||
const body = el('span', { class: 'msg-body' });
|
||||
|
|
@ -333,11 +333,12 @@ export function renderApprovals() {
|
|||
// Goes amber once it's been pending an hour so a stale request is
|
||||
// obvious at a glance (see docs/web-ui.md::Approval card).
|
||||
if (a.requested_at != null) {
|
||||
const ageSec = Math.max(0, Math.floor(Date.now() / 1000 - a.requested_at));
|
||||
const requestedSec = epochSec(a.requested_at);
|
||||
const ageSec = Math.max(0, Math.floor(Date.now() / 1000 - requestedSec));
|
||||
head.append(el('span', {
|
||||
class: 'approval-ts' + (ageSec >= 3600 ? ' stale' : ''),
|
||||
title: 'requested ' + new Date(a.requested_at * 1000).toLocaleString(),
|
||||
'data-requested-at': String(a.requested_at),
|
||||
title: 'requested ' + new Date(a.requested_at).toLocaleString(),
|
||||
'data-requested-at': String(requestedSec),
|
||||
}, 'requested ' + fmtAgo(a.requested_at)));
|
||||
}
|
||||
li.append(head);
|
||||
|
|
@ -556,7 +557,7 @@ function questionRowFingerprint(q) {
|
|||
// Event listeners attached here (keydown on textarea, submit on form) are
|
||||
// preserved in the reused node — no re-attachment needed.
|
||||
function buildQuestionLi(q) {
|
||||
const fmt = (n) => new Date(n * 1000).toISOString().replace('T', ' ').slice(0, 19);
|
||||
const fmt = (ts) => new Date(ts).toISOString().replace('T', ' ').slice(0, 19);
|
||||
const targetLabel = q.target || 'operator';
|
||||
const li = el('li', { class: 'question' + (q.target ? ' question-peer' : '') });
|
||||
const head = el('div', { class: 'q-head' },
|
||||
|
|
@ -570,10 +571,10 @@ function buildQuestionLi(q) {
|
|||
// Tag the chip with its deadline so the global 1s ticker
|
||||
// can refresh the text without re-rendering the questions section.
|
||||
const ttlEl = el('span', {
|
||||
class: 'q-ttl', 'data-deadline': String(q.deadline_at),
|
||||
class: 'q-ttl', 'data-deadline': String(epochSec(q.deadline_at)),
|
||||
});
|
||||
ttlEl.textContent = formatTtl(
|
||||
q.deadline_at - Math.floor(Date.now() / 1000),
|
||||
epochSec(q.deadline_at) - Math.floor(Date.now() / 1000),
|
||||
);
|
||||
head.append(' ', ttlEl);
|
||||
}
|
||||
|
|
@ -694,7 +695,7 @@ export function renderQuestions() {
|
|||
// <li> nodes (preserving textarea/checkbox state) and only rebuilds
|
||||
// cache-miss rows, so we no longer wipe the DOM at the start.
|
||||
const openDetails = snapshotOpenDetails(root);
|
||||
const fmt = (n) => new Date(n * 1000).toISOString().replace('T', ' ').slice(0, 19);
|
||||
const fmt = (ts) => new Date(ts).toISOString().replace('T', ' ').slice(0, 19);
|
||||
const allPending = questionsState.pending;
|
||||
|
||||
// Filter chips. Always include `all` / `operator` / `peer`; add
|
||||
|
|
|
|||
Loading…
Reference in a new issue