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 26 additions and 22 deletions
Showing only changes of commit cdfb6d4ecd - Show all commits

No files matched your search

+1 -1
View File
@@ -1,7 +1,7 @@
<?php
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).
// Off by default; enable via env for local troubleshooting only.
@@ -54,11 +54,12 @@ function isOpen() {
function show() {
if (!overlay) return;
overlay.classList.add('open');
if (!state.namespaces.length) bootstrap();
else {
refresh();
startLive();
}
// Always kick off polling — refresh() self-heals: it loads namespaces
// 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();
startLive();
}
function hide() {
if (!overlay) return;
@@ -70,21 +71,6 @@ function 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() {
const host = $('oumta-ns-tabs');
if (!host) return;
@@ -125,10 +111,27 @@ function switchView(view) {
}
// ── 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() {
if (!state.activeNamespace) return;
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([
api('/api/cluster/overview'),
api('/api/workloads'),
@@ -138,6 +141,7 @@ async function refresh() {
state.data.workloads = wl.items || [];
state.data.timeline = tl.items || [];
renderAll();
setLive('polling');
} catch (e) {
setLive('error', e.message);
}