diff --git a/Plugin/unraid/pages/rsync.php b/Plugin/unraid/pages/rsync.php
index 9280d97..3fb8348 100644
--- a/Plugin/unraid/pages/rsync.php
+++ b/Plugin/unraid/pages/rsync.php
@@ -571,14 +571,24 @@ function _lastSyncCard(data) {
}
// ── Window cards row ──────────────────────────────────────────────────────────
+const WIN_TOGGLE_KEYS = {
+ critical: 'CRITICAL_RSYNC_ENABLED',
+ intermediate: 'INTERMEDIATE_RSYNC_ENABLED',
+ daily: 'DAILY_RSYNC_ENABLED',
+ weekly: 'WEEKLY_RSYNC_ENABLED',
+ fallback: 'FALLBACK_RSYNC_ENABLED',
+};
+
function _windowsRow(data) {
const windows = data.windows || {};
const lastSync = data.last_sync || {};
const cards = Object.entries(WIN_META).map(([key, meta]) => {
- const enabled = windows[key] !== false;
- const ls = lastSync[key];
- const cls = enabled ? 'enabled' : 'disabled';
+ const enabled = windows[key] !== false;
+ const ls = lastSync[key];
+ const cls = enabled ? 'enabled' : 'disabled';
+ const toggleKey = WIN_TOGGLE_KEYS[key] || '';
+ const trackId = 'vv-ry-tog-win-' + key;
let statusHtml = '
No run history
';
if (ls && ls.ts) {
@@ -587,11 +597,26 @@ function _windowsRow(data) {
${_rel(ls.ts)}${ls.duration ? ' · ' + _dur(ls.duration) : ''}
`;
}
- return `
-
${meta.cadence}
-
${meta.label}
-
${enabled ? 'enabled' : 'disabled'}
- ${statusHtml}
+ const panelHtml = toggleKey ? `
+
` : '';
+
+ return `
+
+
+
${meta.cadence}
+
${meta.label}
+
${enabled ? 'enabled' : 'disabled'}
+ ${statusHtml}
+
+
▸
+
+ ${panelHtml}
`;
});
@@ -741,6 +766,9 @@ function _settingsSection(data) {
`;
}
+// Track which window panels are open so they survive poll re-renders
+const _vvRyWinOpen = new Set();
+
// ── Main render ───────────────────────────────────────────────────────────────
function _render(data) {
let html = '';
@@ -751,6 +779,16 @@ function _render(data) {
html += _settingsSection(data);
document.getElementById('vv-ry-grid').innerHTML = html;
+ // Restore any window panels that were open before the re-render
+ _vvRyWinOpen.forEach(key => {
+ const card = document.querySelector(`.vv-ry-win[data-win-key="${key}"]`);
+ if (!card) return;
+ const panel = card.querySelector('.vv-ry-win-panel');
+ const chev = card.querySelector('.vv-ry-win-chev');
+ if (panel) panel.style.display = '';
+ if (chev) chev.textContent = '▾';
+ });
+
const ts = data.ts
? new Date(data.ts * 1000).toLocaleString([], {
month:'numeric', day:'numeric', year:'numeric',
@@ -771,6 +809,18 @@ setInterval(vvRyLoad, 30000);
})();
+// ── Window card expand/collapse ───────────────────────────────────────────────
+function vvRyWinExpand(card) {
+ const key = card.dataset.winKey;
+ const panel = card.querySelector('.vv-ry-win-panel');
+ const chev = card.querySelector('.vv-ry-win-chev');
+ if (!panel) return;
+ const open = panel.style.display !== 'none';
+ panel.style.display = open ? 'none' : '';
+ if (chev) chev.textContent = open ? '▸' : '▾';
+ if (key) open ? _vvRyWinOpen.delete(key) : _vvRyWinOpen.add(key);
+}
+
// ── Toggle a boolean flag — called by inline onclick ──────────────────────────
function vvRyToggle(trackEl, name) {
const on = !trackEl.classList.contains('on');