dashboard frontend: consume rfc3339 timestamps from the api

This commit is contained in:
damocles 2026-07-02 21:35:03 +02:00 committed by mara
commit cafef519a9
5 changed files with 46 additions and 33 deletions

View file

@ -13,7 +13,7 @@
import { $, el, appendLinkified } from './common.js';
import { themedConfirm, themedToast } from './modal.js';
import { paintAtomic, fmtAgo, fmtDuration } from './util.js';
import { paintAtomic, epochSec, fmtAgo, fmtDuration } from './util.js';
import { containersState } from './state.js';
export async function refreshReminders() {
@ -47,7 +47,7 @@ function renderReminders(rows) {
for (const r of rows) {
const failed = (r.attempt_count || 0) > 0;
const li = el('li', { class: 'reminder-row' + (failed ? ' reminder-failed' : '') });
const dueIn = r.due_at - Math.floor(Date.now() / 1000);
const dueIn = epochSec(r.due_at) - Math.floor(Date.now() / 1000);
const dueLabel = dueIn <= 0
? `overdue ${fmtAgo(r.due_at)}`
: `in ${fmtDuration(dueIn)}`;
@ -55,8 +55,8 @@ function renderReminders(rows) {
el('span', { class: 'agent' }, r.agent), ' ',
el('span', {
class: 'meta reminder-due',
title: new Date(r.due_at * 1000).toISOString(),
'data-due-at': String(r.due_at),
title: new Date(r.due_at).toISOString(),
'data-due-at': String(epochSec(r.due_at)),
}, dueLabel),
' ',
el('span', { class: 'meta' }, `· id ${r.id}`),
@ -394,7 +394,7 @@ function renderSchedulesList() {
const aOrd = a.cancelled_at_unix ? 2 : a.paused_at_unix ? 1 : 0;
const bOrd = b.cancelled_at_unix ? 2 : b.paused_at_unix ? 1 : 0;
if (aOrd !== bOrd) return aOrd - bOrd;
return a.next_fire_at_unix - b.next_fire_at_unix;
return epochSec(a.next_fire_at_unix) - epochSec(b.next_fire_at_unix);
});
for (const s of sorted) {
tbody.append(renderScheduleRow(s, agents));
@ -657,24 +657,24 @@ function renderScheduleRow(s, agents) {
// absolute ISO in the title.
const nextCell = el('td', { class: 'meta schedules-table-next-col' });
if (cancelled) {
nextCell.title = 'cancelled ' + new Date(s.cancelled_at_unix * 1000).toISOString();
nextCell.title = 'cancelled ' + new Date(s.cancelled_at_unix).toISOString();
nextCell.textContent = 'cancelled';
} else if (paused) {
nextCell.title = 'paused since '
+ new Date(s.paused_at_unix * 1000).toISOString()
+ new Date(s.paused_at_unix).toISOString()
+ '\nwould fire at '
+ new Date(s.next_fire_at_unix * 1000).toISOString();
+ new Date(s.next_fire_at_unix).toISOString();
nextCell.append(
el('span', { class: 'sched-paused-label' }, '⏸ paused'),
);
} else {
const dueIn = s.next_fire_at_unix - Math.floor(Date.now() / 1000);
nextCell.title = new Date(s.next_fire_at_unix * 1000).toISOString();
const dueIn = epochSec(s.next_fire_at_unix) - Math.floor(Date.now() / 1000);
nextCell.title = new Date(s.next_fire_at_unix).toISOString();
nextCell.textContent = dueIn <= 0
? 'overdue ' + fmtAgo(s.next_fire_at_unix)
: fmtDuration(dueIn);
nextCell.classList.add('sched-due');
nextCell.dataset.dueAt = String(s.next_fire_at_unix);
nextCell.dataset.dueAt = String(epochSec(s.next_fire_at_unix));
}
tr.append(nextCell);
@ -841,7 +841,7 @@ function renderScheduleEditForm(s) {
});
firstFireInput.value = carry.next_fire !== undefined
? carry.next_fire
: isoForDatetimeLocal(new Date(s.next_fire_at_unix * 1000));
: isoForDatetimeLocal(new Date(s.next_fire_at_unix));
form_.append(scheduleField('next fire', firstFireInput));
const intervalCx = buildIntervalComposer({
@ -968,7 +968,7 @@ async function submitEditSchedule(originalSchedule, form_) {
if (newDescription !== (s.description || '')) {
patch.description = newDescription || null;
}
if (newNextFireUnix !== s.next_fire_at_unix) {
if (newNextFireUnix !== epochSec(s.next_fire_at_unix)) {
patch.next_fire_at_unix = newNextFireUnix;
}
if (newIntervalSeconds !== (s.interval_seconds || null)) {