mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-14 06:16:20 -06:00
The patch4 server derives 3-state liveness (healthy / degraded-reconnecting / offline) and emits it as data.liveness on dashboard:device-status, but the frontend only consumed binary online/offline — the signal was thrown away. Add a shared livenessBadge() helper (utils.js) consumed by both the dashboard device list and the device-detail view (initial render + live statusHandler). Degrades to the binary status when liveness is absent (old payload / plain reconnect+disconnect emits / DB device object) so nothing renders blank; unknown/no-data -> offline default. CSS: healthy=green, degraded=amber+pulse (reads as reconnecting), offline=red — reusing the existing --success/--warning/--danger tokens. Labels in en.js (all locales fall back to en). Frontend-only; server derivation unchanged. 13/13 unit tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
42 lines
2.1 KiB
JavaScript
42 lines
2.1 KiB
JavaScript
import { t } from './i18n.js';
|
|
|
|
// HTML escape helper — prevents XSS when inserting user data into innerHTML
|
|
export function esc(str) {
|
|
if (str == null) return '';
|
|
return String(str).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"').replace(/'/g,''');
|
|
}
|
|
|
|
// v4 liveness badge. The patch4 server derives a 3-state liveness — 'healthy' / 'degraded'
|
|
// (temporarily reconnecting) / 'offline' — and emits it as `data.liveness` on dashboard:device-status.
|
|
// It is present on SOME emits only (the plain reconnect + disconnect emits, and any device object read
|
|
// from the DB, carry just the binary `status`), so we DEGRADE to the binary status when liveness is
|
|
// absent — nothing ever renders blank. 'provisioning' is a lifecycle state (never-paired), kept
|
|
// distinct from liveness. livenessState() is pure (unit-testable); livenessBadge() adds the i18n label.
|
|
const LIVENESS_LABEL_KEY = {
|
|
healthy: 'device.liveness.healthy',
|
|
degraded: 'device.liveness.degraded',
|
|
offline: 'device.liveness.offline',
|
|
provisioning: 'dashboard.awaiting_pairing',
|
|
};
|
|
export function livenessState(data) {
|
|
const lv = data && data.liveness;
|
|
if (lv === 'healthy' || lv === 'degraded' || lv === 'offline') return lv; // 3-state signal present
|
|
const st = data && data.status; // backward-compat: derive from binary status
|
|
if (st === 'provisioning') return 'provisioning';
|
|
if (st === 'online') return 'healthy';
|
|
if (st === 'offline') return 'offline';
|
|
return 'offline'; // unknown / no data yet -> safe default, never blank
|
|
}
|
|
export function livenessBadge(data) {
|
|
const state = livenessState(data);
|
|
return { state, label: t(LIVENESS_LABEL_KEY[state]) };
|
|
}
|
|
|
|
// Phase 2.1: the Phase 1 schema migration renamed the legacy 'superadmin'
|
|
// role to 'platform_admin'. Existing frontend checks still match the old
|
|
// string; this helper accepts both so we don't have to splatter the array
|
|
// at every call site. Use everywhere the UI gates on platform-level access.
|
|
export function isPlatformAdmin(user) {
|
|
return !!(user && (user.role === 'superadmin' || user.role === 'platform_admin'));
|
|
}
|