SysOps: deploy-all — 2026-06-09 11:27 UTC
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
{% block extra_head %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
|
||||
<link rel="stylesheet" href="/static/css/hermes.css" />
|
||||
<link rel="stylesheet" href="/static/css/herman-dashboard.css?v=14" />
|
||||
<link rel="stylesheet" href="/static/css/herman-dashboard.css?v=15" />
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="herman-shell hm-neo">
|
||||
@@ -24,11 +24,6 @@
|
||||
</div>
|
||||
|
||||
<section class="panel herman-briefing" x-data="dashboardBriefing()" x-init="init()">
|
||||
<div class="briefing-loading-overlay" x-show="loading" x-cloak>
|
||||
<div class="loading-dots"><span></span><span></span><span></span></div>
|
||||
<p x-text="loadingMsg"></p>
|
||||
</div>
|
||||
|
||||
<header class="herman-briefing-header">
|
||||
<div>
|
||||
<h2>Dagelijkse briefing</h2>
|
||||
@@ -44,6 +39,24 @@
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div id="hm-live-bar" class="hm-live-bar" x-show="loading || liveLog.length" x-cloak :class="loading ? 'hm-live-bar-active' : 'hm-live-bar-done'">
|
||||
<div class="hm-live-bar-head">
|
||||
<span class="hm-live-dot"></span>
|
||||
<strong class="hm-live-title" x-text="loading ? loadingMsg : 'Dagrapport voltooid'"></strong>
|
||||
<span class="hm-live-progress" x-show="loading" x-text="liveProgress"></span>
|
||||
<button type="button" class="btn btn-sm hm-live-close" x-show="!loading && liveLog.length" @click="liveLog = []">✕</button>
|
||||
</div>
|
||||
<ol id="hm-live-log" class="hm-live-log">
|
||||
<template x-for="(entry, idx) in liveLog" :key="idx">
|
||||
<li :class="'hm-live-entry hm-live-' + (entry.status || 'ok') + (entry.type === 'agent_msg' ? ' hm-live-agent' : '')">
|
||||
<span class="hm-live-src" x-text="entry.source || entry.agent"></span>
|
||||
<span class="hm-live-msg" x-text="entry.message"></span>
|
||||
<small class="hm-live-detail" x-show="entry.detail" x-text="entry.detail"></small>
|
||||
</li>
|
||||
</template>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div id="viz-toolbar" class="viz-toolbar"></div>
|
||||
<div id="dashboard-customize" class="hm-customize-wrap" x-show="editLayout" x-cloak></div>
|
||||
|
||||
@@ -190,7 +203,8 @@
|
||||
const INITIAL_BRIEFING = {{ briefing_payload | tojson }};
|
||||
function dashboardBriefing() {
|
||||
return {
|
||||
loading: false, loadingMsg: 'Herman werkt…', editLayout: false,
|
||||
loading: false, loadingMsg: 'Herman werkt…', liveLog: [], liveProgress: '',
|
||||
editLayout: false,
|
||||
content: INITIAL_BRIEFING.content || '', createdAt: INITIAL_BRIEFING.created_at || '',
|
||||
_pollStop: null, _wsStop: null, _vizMode: 'neo-bars', _stats: null,
|
||||
_prefs: null, _setDragMode: null, _saveTimer: null,
|
||||
@@ -359,20 +373,70 @@ function dashboardBriefing() {
|
||||
if (toast !== false) Cockpit.toast('Live data bijgewerkt', 'success');
|
||||
} catch (e) { if (toast !== false) Cockpit.toast(e.message, 'error'); }
|
||||
},
|
||||
pushLiveEntry(entry) {
|
||||
this.liveLog.push(entry);
|
||||
this.loadingMsg = entry.message || this.loadingMsg;
|
||||
if (entry.type === 'step') {
|
||||
const done = this.liveLog.filter(e => e.type === 'step' && e.status === 'ok').length;
|
||||
this.liveProgress = done + ' bronnen geladen';
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
const log = document.getElementById('hm-live-log');
|
||||
if (log) log.scrollTop = log.scrollHeight;
|
||||
const bar = document.getElementById('hm-live-bar');
|
||||
if (bar && this.loading) bar.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
});
|
||||
},
|
||||
async generate() {
|
||||
this.loading = true;
|
||||
this.loadingMsg = 'Live data laden…';
|
||||
await this.refreshLive(false);
|
||||
this.loadingMsg = 'Herman schrijft dagrapport…';
|
||||
this.liveLog = [];
|
||||
this.liveProgress = '';
|
||||
this.loadingMsg = 'Herman start dagrapport…';
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
const bar = document.getElementById('hm-live-bar');
|
||||
if (bar) bar.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
try {
|
||||
const r = await Cockpit.api('/api/herman/briefing', { method: 'POST' });
|
||||
this.content = r.content || '';
|
||||
this.createdAt = r.generated_at || new Date().toISOString();
|
||||
BriefingCharts.render(document.getElementById('briefing-dashboard'), r.stats, r.content, this.createdAt, this._vizMode);
|
||||
this.renderClientsMini(r.stats || {});
|
||||
const resp = await fetch('/api/herman/briefing/stream', { method: 'POST' });
|
||||
if (!resp.ok) throw new Error('Stream mislukt (' + resp.status + ')');
|
||||
const reader = resp.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
let buf = '';
|
||||
let result = null;
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
buf += decoder.decode(value, { stream: true });
|
||||
const parts = buf.split('\n\n');
|
||||
buf = parts.pop() || '';
|
||||
for (const chunk of parts) {
|
||||
const line = chunk.trim();
|
||||
if (!line.startsWith('data:')) continue;
|
||||
const evt = JSON.parse(line.replace(/^data:\s*/, ''));
|
||||
if (evt.type === 'step' || evt.type === 'agent_msg') {
|
||||
this.pushLiveEntry(evt);
|
||||
} else if (evt.type === 'done') {
|
||||
result = evt;
|
||||
this.pushLiveEntry({ type: 'step', status: 'ok', source: 'Herman', message: '✓ Dagrapport klaar!' });
|
||||
} else if (evt.type === 'error') {
|
||||
throw new Error(evt.message || 'Onbekende fout');
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!result) throw new Error('Geen resultaat van Herman');
|
||||
this.content = result.content || '';
|
||||
this.createdAt = result.generated_at || new Date().toISOString();
|
||||
this._stats = result.stats;
|
||||
BriefingCharts.render(document.getElementById('briefing-dashboard'), result.stats, result.content, this.createdAt, this._vizMode);
|
||||
this.renderClientsMini(result.stats || {});
|
||||
this.renderActivityLog((result.stats || {}).activity_log || []);
|
||||
document.getElementById('briefing-meta').textContent = 'Rapport: ' + this.createdAt.substring(0, 19).replace('T', ' ') + ' UTC';
|
||||
Cockpit.toast('Dagrapport klaar!', 'success');
|
||||
} catch (e) { Cockpit.toast(e.message, 'error'); }
|
||||
} catch (e) {
|
||||
this.pushLiveEntry({ type: 'step', status: 'warn', source: 'Fout', message: e.message || String(e) });
|
||||
Cockpit.toast(e.message || 'Fout bij genereren', 'error');
|
||||
}
|
||||
this.loading = false;
|
||||
this.loadingMsg = 'Klaar';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user