88 lines
3.6 KiB
JavaScript
88 lines
3.6 KiB
JavaScript
import { $, safe } from './helpers.js';
|
|
import { api } from './api.js';
|
|
import { refs, setHealth, renderClusterCards, renderUnits, renderReplicationTable, renderHAResources, renderNonHA, renderNodesTable } from './tables.js';
|
|
import { renderVMAdmin } from './admin.js';
|
|
|
|
// ------ actions ------
|
|
async function callAction(act) {
|
|
const node = refs.nodeInput.value || '';
|
|
const d = await api.action(act, node);
|
|
alert(d.ok ? 'OK' : ('ERROR: ' + (d.error || 'unknown')));
|
|
}
|
|
$('#btnEnable').onclick = () => callAction('enable');
|
|
$('#btnDisable').onclick = () => callAction('disable');
|
|
$('#btnToggleAll').onclick = () => {
|
|
document.querySelectorAll('.accordion-collapse').forEach(el => {
|
|
const bs = bootstrap.Collapse.getOrCreateInstance(el, { toggle: false });
|
|
el.classList.contains('show') ? bs.hide() : bs.show();
|
|
});
|
|
};
|
|
|
|
// ------ refresh control ------
|
|
let REF_TIMER = null;
|
|
let ac = null; // AbortController dla równoległych fetchy
|
|
|
|
async function doRefresh() {
|
|
try {
|
|
if (ac) ac.abort();
|
|
ac = new AbortController();
|
|
const node = refs.nodeInput.value || '';
|
|
// Minimalny szybki zestaw danych — równolegle:
|
|
const [cluster, nodes, units, repl] = await Promise.allSettled([
|
|
api.clusterBrief(), api.nodesSummary(), api.units(node), api.replicationAll()
|
|
]);
|
|
|
|
// render
|
|
const vq = (cluster.value && cluster.value.votequorum) || {};
|
|
const unitsMap = (units.value && units.value.units) || {};
|
|
const allUnits = Object.values(unitsMap).every(v => v === 'active');
|
|
setHealth((vq.quorate === 'yes') && allUnits, vq, allUnits);
|
|
|
|
const gl = document.getElementById('global-loading'); if (gl) gl.remove();
|
|
|
|
refs.qSummary.textContent = `Quorate: ${safe(vq.quorate)} | members: ${safe(vq.members)} | expected: ${safe(vq.expected)} | total: ${safe(vq.total)} | quorum: ${safe(vq.quorum)}`;
|
|
renderClusterCards((cluster.value && cluster.value.cluster_status) || []);
|
|
renderUnits(unitsMap);
|
|
renderReplicationTable((repl.value || {jobs:[]}));
|
|
|
|
renderHAResources((cluster.value && cluster.value.ha_resources) || []);
|
|
renderNodesTable((nodes.value && nodes.value.nodes) || []);
|
|
|
|
refs.pvecmPre.textContent = safe(cluster.value && cluster.value.pvecm);
|
|
refs.cfgtoolPre.textContent = safe(cluster.value && cluster.value.cfgtool);
|
|
refs.footer.textContent = `node_arg=${safe(node)} | host=${safe(cluster.value && cluster.value.hostname)} | ts=${new Date(((cluster.value && cluster.value.ts) || 0) * 1000).toLocaleString()}`;
|
|
|
|
// pierwszy raz: dociągnij Non-HA + VM Admin w idle
|
|
if (!doRefresh.didNonHA) { requestIdleCallback(() => renderNonHA().catch(console.error)); doRefresh.didNonHA = true; }
|
|
if (!doRefresh.didAdmin) { requestIdleCallback(() => renderVMAdmin().catch(console.error)); doRefresh.didAdmin = true; }
|
|
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
$('#btnRefresh').onclick = doRefresh;
|
|
|
|
$('#btnAuto').onclick = () => {
|
|
if (REF_TIMER) {
|
|
clearInterval(REF_TIMER); REF_TIMER = null;
|
|
$('#btnAuto').textContent = 'OFF';
|
|
$('#btnAuto').classList.remove('btn-success'); $('#btnAuto').classList.add('btn-outline-success');
|
|
$('#selInterval').disabled = true;
|
|
} else {
|
|
const iv = parseInt($('#selInterval').value || '30000', 10);
|
|
REF_TIMER = setInterval(doRefresh, iv);
|
|
$('#btnAuto').textContent = 'ON';
|
|
$('#btnAuto').classList.remove('btn-outline-success'); $('#btnAuto').classList.add('btn-success');
|
|
$('#selInterval').disabled = false;
|
|
}
|
|
};
|
|
$('#selInterval').onchange = () => {
|
|
if (REF_TIMER) {
|
|
clearInterval(REF_TIMER);
|
|
REF_TIMER = setInterval(doRefresh, parseInt($('#selInterval').value || '30000', 10));
|
|
}
|
|
};
|
|
|
|
// initial one-shot load
|
|
doRefresh().catch(console.error);
|