Improve Cluster Dashboard Timeline #1

Merged
tu merged 6 commits from feature/check-whether-works-as-pwa into master 2026-04-19 13:08:57 +00:00
2 changed files with 24 additions and 20 deletions
Showing only changes of commit cdfb6d4ecd - Show all commits

No files matched your search

+1 -1
View File
@@ -1,7 +1,7 @@
<?php <?php
define('APP_NAME', 'hyprcrd'); define('APP_NAME', 'hyprcrd');
define('APP_VERSION', '2.0.13'); define('APP_VERSION', '2.0.14');
// APP_DEBUG: gates verbose error responses (curl traces, upstream bodies). // APP_DEBUG: gates verbose error responses (curl traces, upstream bodies).
// Off by default; enable via env for local troubleshooting only. // Off by default; enable via env for local troubleshooting only.
@@ -54,11 +54,12 @@ function isOpen() {
function show() { function show() {
if (!overlay) return; if (!overlay) return;
overlay.classList.add('open'); overlay.classList.add('open');
if (!state.namespaces.length) bootstrap(); // Always kick off polling — refresh() self-heals: it loads namespaces
else { // if they aren't there yet, and the interval keeps retrying even if
// the initial poll fails. Previously an initial bootstrap failure
// stopped the loop entirely and required a page reload to recover.
refresh(); refresh();
startLive(); startLive();
}
} }
function hide() { function hide() {
if (!overlay) return; if (!overlay) return;
@@ -70,21 +71,6 @@ function toggle() {
} }
window._oumtaToggle = toggle; window._oumtaToggle = toggle;
// ── Bootstrap: load namespaces, then first refresh ─────────────
async function bootstrap() {
try {
const res = await api('/api/namespaces');
state.namespaces = res.items || [];
state.activeNamespace = state.namespaces[0] || null;
renderNamespaceTabs();
await refresh();
startLive();
} catch (e) {
setLive('error', e.message);
}
}
function renderNamespaceTabs() { function renderNamespaceTabs() {
const host = $('oumta-ns-tabs'); const host = $('oumta-ns-tabs');
if (!host) return; if (!host) return;
@@ -125,10 +111,27 @@ function switchView(view) {
} }
// ── Refresh all data for the active namespace ────────────────── // ── Refresh all data for the active namespace ──────────────────
//
// Self-healing: if namespaces aren't loaded yet (e.g. initial poll
// failed), fetch them first; if upstream is down, leave state as
// 'error' and let the next interval tick try again. On any successful
// poll we flip back to 'polling' so the indicator recovers without a
// page reload.
async function refresh() { async function refresh() {
if (!state.activeNamespace) return;
try { try {
if (!state.activeNamespace) {
const res = await api('/api/namespaces');
state.namespaces = res.items || [];
state.activeNamespace = state.namespaces[0] || null;
renderNamespaceTabs();
}
if (!state.activeNamespace) {
// Namespaces endpoint returned empty — nothing to poll yet.
// Stay in 'polling' so we keep retrying on the interval.
setLive('polling');
return;
}
const [ov, wl, tl] = await Promise.all([ const [ov, wl, tl] = await Promise.all([
api('/api/cluster/overview'), api('/api/cluster/overview'),
api('/api/workloads'), api('/api/workloads'),
@@ -138,6 +141,7 @@ async function refresh() {
state.data.workloads = wl.items || []; state.data.workloads = wl.items || [];
state.data.timeline = tl.items || []; state.data.timeline = tl.items || [];
renderAll(); renderAll();
setLive('polling');
} catch (e) { } catch (e) {
setLive('error', e.message); setLive('error', e.message);
} }