Partnership page: one settings card instead of three, and a Data Transferred card
Windows with runs but no bytes say 'no data moved' rather than 0.00 GB, and rows before the byte-parser fix are excluded rather than summed into a false total.
This commit is contained in:
@@ -105,16 +105,6 @@ textarea.vv-pt-set-input { resize:vertical; white-space:pre; }
|
||||
<div id="vv-pt-config-body" style="color:#444;font-size:12px;">Loading…</div>
|
||||
</div>
|
||||
|
||||
<!-- Host Settings -->
|
||||
<div class="vv-card" id="vv-pt-hosts-card" style="margin-bottom:12px;display:none;">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;">
|
||||
<h3 style="margin:0;">Host Settings</h3>
|
||||
<button id="vv-pt-hosts-save" class="vv-pt-action-btn run"
|
||||
onclick="vvPtSaveHosts(this)" style="display:none;">Save</button>
|
||||
</div>
|
||||
<div id="vv-pt-hosts-body"></div>
|
||||
</div>
|
||||
|
||||
<!-- Offline countdown warning (shown only when partner has been unreachable) -->
|
||||
<div id="vv-pt-offline-warn" style="display:none;margin-bottom:12px;"></div>
|
||||
|
||||
@@ -123,8 +113,11 @@ textarea.vv-pt-set-input { resize:vertical; white-space:pre; }
|
||||
<div style="color:#444;font-size:12px;padding:16px 0;text-align:center;">Loading…</div>
|
||||
</div>
|
||||
|
||||
<!-- Array settings (above sync/actions row) -->
|
||||
<div id="vv-pt-arrays-wrap" style="margin-bottom:12px;display:none;"></div>
|
||||
<!-- Data moved between the servers -->
|
||||
<div class="vv-card" id="vv-pt-xfer-card" style="margin-bottom:12px;">
|
||||
<h3>Data Transferred</h3>
|
||||
<div id="vv-pt-xfer-body" style="color:#444;font-size:12px;">Loading…</div>
|
||||
</div>
|
||||
|
||||
<!-- Mirror sync + Actions side by side -->
|
||||
<div style="display:flex;gap:12px;margin-bottom:12px;align-items:stretch;flex-wrap:wrap;">
|
||||
@@ -153,9 +146,28 @@ textarea.vv-pt-set-input { resize:vertical; white-space:pre; }
|
||||
</div>
|
||||
</div>
|
||||
<div id="vv-pt-settings-hint" style="font-size:10px;color:#444;margin-top:4px;">
|
||||
Partnership configuration for this server.
|
||||
Partnership, host and array configuration for this server.
|
||||
</div>
|
||||
|
||||
<!-- One card, three sections. These were three separate top-level cards — "Host Settings",
|
||||
"Array Settings" and "Settings" — stacked down the page between the things people
|
||||
actually come here to look at. They are all the same kind of thing: conf this host owns.
|
||||
Collapsed together they cost one line until opened. -->
|
||||
<div id="vv-pt-settings-body" style="display:none;margin-top:10px;">
|
||||
|
||||
<div id="vv-pt-hosts-section" style="display:none;margin-bottom:16px;">
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">
|
||||
<div class="vv-cl-title" style="margin:0;">Host settings</div>
|
||||
<button id="vv-pt-hosts-save" class="vv-pt-action-btn run"
|
||||
onclick="vvPtSaveHosts(this)" style="display:none;">Save</button>
|
||||
</div>
|
||||
<div id="vv-pt-hosts-body"></div>
|
||||
</div>
|
||||
|
||||
<div id="vv-pt-arrays-wrap" style="display:none;margin-bottom:16px;"></div>
|
||||
|
||||
<div id="vv-pt-settings-conf"></div>
|
||||
</div>
|
||||
<div id="vv-pt-settings-body" style="display:none;margin-top:10px;"></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -504,9 +516,9 @@ function _vvRenderArrayCards() {
|
||||
if (!hasArrays) { wrap.style.display = 'none'; return; }
|
||||
|
||||
wrap.style.display = '';
|
||||
wrap.innerHTML = `<div class="vv-card">
|
||||
wrap.innerHTML = `<div>
|
||||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">
|
||||
<h3 style="margin:0;">Array Settings</h3>
|
||||
<div class="vv-cl-title" style="margin:0;">Array settings</div>
|
||||
<button id="vv-pt-arrays-save" class="vv-pt-action-btn run"
|
||||
onclick="vvPtSaveArrays(this)" style="display:none;">Save Changes</button>
|
||||
</div>
|
||||
@@ -570,7 +582,9 @@ function vvPtToggleSettings() {
|
||||
}
|
||||
|
||||
function vvPtLoadSettings() {
|
||||
const body = document.getElementById('vv-pt-settings-body');
|
||||
// The conf rows render into their own sub-node, not the whole collapsible body — the body now
|
||||
// also holds the host and array sections, and writing over it would delete them.
|
||||
const body = document.getElementById('vv-pt-settings-conf');
|
||||
body.innerHTML = '<div style="color:#555;font-size:12px;padding:8px 0;">Loading…</div>';
|
||||
fetch('/plugins/varaverk/api/partnership_settings.php?_=' + Date.now())
|
||||
.then(r => r.json())
|
||||
@@ -627,12 +641,12 @@ function vvPtSetChanged(el) {
|
||||
const changed = el.value !== el.dataset.orig;
|
||||
el.classList.toggle('changed', changed);
|
||||
// Show Save button if any field is changed
|
||||
const any = document.querySelector('#vv-pt-settings-body .vv-pt-set-input.changed');
|
||||
const any = document.querySelector('#vv-pt-settings-conf .vv-pt-set-input.changed');
|
||||
document.getElementById('vv-pt-settings-save').style.display = any ? '' : 'none';
|
||||
}
|
||||
|
||||
async function vvPtSaveSettings(btn) {
|
||||
const changedEls = document.querySelectorAll('#vv-pt-settings-body .vv-pt-set-input.changed');
|
||||
const changedEls = document.querySelectorAll('#vv-pt-settings-conf .vv-pt-set-input.changed');
|
||||
if (!changedEls.length) return;
|
||||
const changes = [];
|
||||
changedEls.forEach(el => changes.push({
|
||||
@@ -723,6 +737,64 @@ function _syncToggle(gate, dimmed) {
|
||||
title="${gate.var} — click to ${on ? 'disable' : 'enable'}">${on ? 'ON' : 'OFF'}</span>`;
|
||||
}
|
||||
|
||||
// ── Data transferred ──────────────────────────────────────────────────────────
|
||||
//
|
||||
// A window with runs but no bytes says "no data moved", not "0.00 GB". They are different
|
||||
// claims: rsync completing with nothing to send is the normal state for a mirror that is
|
||||
// already in step, and printing a zero total invites the reading that the sync is broken.
|
||||
// A window with no runs at all says so separately again.
|
||||
function _renderXfer(x) {
|
||||
const el = document.getElementById('vv-pt-xfer-body');
|
||||
if (!el) return;
|
||||
x = x || {};
|
||||
const w = x.windows || {};
|
||||
|
||||
const fmt = (b) => {
|
||||
if (b === null || b === undefined) return null;
|
||||
const u = ['B','KB','MB','GB','TB'];
|
||||
let i = 0, v = b;
|
||||
while (v >= 1024 && i < u.length - 1) { v /= 1024; i++; }
|
||||
return (i >= 3 ? v.toFixed(2) : Math.round(v)) + ' ' + u[i];
|
||||
};
|
||||
|
||||
const row = (label, key) => {
|
||||
const d = w[key] || {};
|
||||
const bytes = fmt(d.bytes);
|
||||
let val, col;
|
||||
if (!d.runs) { val = 'no syncs ran'; col = '#333'; }
|
||||
else if (bytes) { val = bytes; col = '#4caf50'; }
|
||||
else { val = 'no data moved'; col = '#555'; }
|
||||
const extra = d.runs
|
||||
? `<span style="color:#333;font-size:9px;">${d.runs} run${d.runs===1?'':'s'}${d.failed?` · ${d.failed} failed`:''}</span>`
|
||||
: '';
|
||||
return `<div style="display:flex;justify-content:space-between;align-items:baseline;gap:10px;
|
||||
padding:5px 0;border-bottom:1px solid #171717;">
|
||||
<span style="color:#666;font-size:11px;">${label}</span>
|
||||
<span style="display:flex;align-items:baseline;gap:8px;">
|
||||
${extra}<span style="color:${col};font-size:12px;font-family:monospace;">${val}</span>
|
||||
</span></div>`;
|
||||
};
|
||||
|
||||
const live = x.live;
|
||||
const liveHtml = live
|
||||
? `<div style="display:flex;justify-content:space-between;align-items:baseline;gap:10px;
|
||||
padding:5px 0;border-bottom:1px solid #171717;">
|
||||
<span style="color:#666;font-size:11px;">Live</span>
|
||||
<span style="color:#ff9800;font-size:12px;font-family:monospace;">⟳ ${live.running} transfer${live.running===1?'':'s'}${live.share?` · ${vvEscHtml(live.share)}`:''}</span>
|
||||
</div>`
|
||||
: `<div style="display:flex;justify-content:space-between;align-items:baseline;gap:10px;
|
||||
padding:5px 0;border-bottom:1px solid #171717;">
|
||||
<span style="color:#666;font-size:11px;">Live</span>
|
||||
<span style="color:#333;font-size:12px;font-family:monospace;">idle</span>
|
||||
</div>`;
|
||||
|
||||
el.innerHTML = liveHtml + row('Last 24 hours','24h') + row('Last 7 days','7d') + row('Last 30 days','30d')
|
||||
+ `<div style="margin-top:7px;font-size:9px;color:#2e2e2e;line-height:1.5;">
|
||||
Counted from ${vvEscHtml(x.epoch || '')} — before that rsync logged every transfer as
|
||||
0 bytes, so those rows are excluded rather than summed into a false total.
|
||||
</div>`;
|
||||
}
|
||||
|
||||
function _renderSync(sync) {
|
||||
const jobs = sync.jobs || {};
|
||||
const gates = sync.gates || {};
|
||||
@@ -1332,7 +1404,7 @@ function _render(data) {
|
||||
document.getElementById('vv-pt-config-body').innerHTML = _renderConfig(cfg);
|
||||
|
||||
// Host settings — always shown upfront
|
||||
const hostsCard = document.getElementById('vv-pt-hosts-card');
|
||||
const hostsCard = document.getElementById("vv-pt-hosts-section");
|
||||
hostsCard.style.display = nodes.length ? '' : 'none';
|
||||
document.getElementById('vv-pt-hosts-body').innerHTML = _renderHostSettings(nodes, isOwner);
|
||||
document.getElementById('vv-pt-hosts-save').style.display = 'none';
|
||||
@@ -1341,6 +1413,7 @@ function _render(data) {
|
||||
_renderOfflineWarn(cfg);
|
||||
|
||||
// Mirror sync health
|
||||
_renderXfer(data.xfer || {});
|
||||
document.getElementById('vv-pt-sync-body').innerHTML = _renderSync(data.sync || {});
|
||||
|
||||
// Node grid — columns based on count
|
||||
|
||||
Reference in New Issue
Block a user