fix: offline operators removed from live_status + award-column visibility

Live status: when an operator goes offline (no QSO in the window) OpsLog now
DELETEs its live_status row instead of just flipping online=0, so a status page
that lists present/recent rows shows them as gone without having to read the
online column — the whole point of the feature. The row reappears on the next
QSO.

Recent QSOs columns: toggling an award column (e.g. DDFM) rebuilt columnDefs and
made AG Grid re-apply every colDef hide default, so hidden non-award columns
(QTH/Grid) came back and restoringRef stayed stuck true (saving off). The
restore-saved-state effect now also runs on awardShown changes, so the other
columns keep the user's visibility.
This commit is contained in:
2026-07-20 09:55:14 +02:00
parent 5f044b959e
commit 9e4f43f648
2 changed files with 25 additions and 19 deletions
+17 -13
View File
@@ -202,33 +202,37 @@ func (a *App) publishLiveStatus() {
}
a.liveActMu.Unlock()
lastQSO := a.liveLastQSOTime() // authoritative (in-memory OR shared DB)
// Online = a new contact was logged within the window. An operator who leaves
// the log open but stops working shows offline after `liveOnlineWindow`; the
// next QSO flips them back on. never-logged (zero time) → offline.
online := 0
var lastQSOArg any
if !lastQSO.IsZero() {
lastQSOArg = lastQSO.UTC()
if time.Since(lastQSO) < liveOnlineWindow {
online = 1
}
}
// On air = a new contact was logged within the window. An operator who leaves
// the log open but stops working goes offline after `liveOnlineWindow`; the next
// QSO puts them back on. never-logged (zero time) → offline.
online := !lastQSO.IsZero() && time.Since(lastQSO) < liveOnlineWindow
if err := a.ensureLiveStatusTable(); err != nil {
applog.Printf("livestatus: CREATE TABLE failed: %v", err)
return
}
// Offline → REMOVE the row entirely, not just flip a flag: a status page that
// lists the present rows (the common case, keyed on updated_at) then shows the
// operator as gone without having to read the online column. The row reappears
// on the next QSO. This is the whole point — no one shows on air when they're not.
if !online {
if _, err := a.logDb.ExecContext(a.ctx, "DELETE FROM live_status WHERE operator=?", op); err != nil {
applog.Printf("livestatus: offline DELETE failed: %v", err)
}
return
}
lastQSOArg := lastQSO.UTC()
_, err := a.logDb.ExecContext(a.ctx,
"INSERT INTO live_status (operator, station, freq_hz, band, mode, online, version, last_qso_at, updated_at) "+
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, UTC_TIMESTAMP()) "+
"ON DUPLICATE KEY UPDATE station=VALUES(station), freq_hz=VALUES(freq_hz), "+
"band=VALUES(band), mode=VALUES(mode), online=VALUES(online), version=VALUES(version), "+
"last_qso_at=VALUES(last_qso_at), updated_at=UTC_TIMESTAMP()",
op, station, freqHz, band, mode, online, appVersion, lastQSOArg)
op, station, freqHz, band, mode, 1, appVersion, lastQSOArg)
if err != nil {
applog.Printf("livestatus: INSERT failed: %v", err)
return
}
applog.Printf("livestatus: published op=%s station=%s %dHz %s %s online=%d", op, station, freqHz, band, mode, online)
applog.Printf("livestatus: published op=%s station=%s %dHz %s %s ON AIR", op, station, freqHz, band, mode)
}
// LiveStation is one operator's live status for the multi-op "who's on air" widget.