diff --git a/dist/urbm-2026.06.15.r020-x86_64-1.txz.sha256 b/dist/urbm-2026.06.15.r020-x86_64-1.txz.sha256 deleted file mode 100644 index 8554c6e..0000000 --- a/dist/urbm-2026.06.15.r020-x86_64-1.txz.sha256 +++ /dev/null @@ -1 +0,0 @@ -a9b5d02c0b92ea7f0a72d0d30a62870a88165065aaf97637c57aec2e7df37139 urbm-2026.06.15.r020-x86_64-1.txz diff --git a/dist/urbm-2026.06.15.r020-x86_64-1.txz b/dist/urbm-2026.06.15.r021-x86_64-1.txz similarity index 56% rename from dist/urbm-2026.06.15.r020-x86_64-1.txz rename to dist/urbm-2026.06.15.r021-x86_64-1.txz index df95c44..45f84e6 100644 Binary files a/dist/urbm-2026.06.15.r020-x86_64-1.txz and b/dist/urbm-2026.06.15.r021-x86_64-1.txz differ diff --git a/dist/urbm-2026.06.15.r021-x86_64-1.txz.sha256 b/dist/urbm-2026.06.15.r021-x86_64-1.txz.sha256 new file mode 100644 index 0000000..01f21d7 --- /dev/null +++ b/dist/urbm-2026.06.15.r021-x86_64-1.txz.sha256 @@ -0,0 +1 @@ +7cb21e5fd01532e461c7cddf2af78ee6e1f5b26b24988d42c128b64dfe0e6331 urbm-2026.06.15.r021-x86_64-1.txz diff --git a/dist/urbm.plg b/dist/urbm.plg index 64ec485..fdcf812 100644 --- a/dist/urbm.plg +++ b/dist/urbm.plg @@ -2,13 +2,18 @@ - + - + ]> +### 2026.06.15.r021 +- Show an orange mixed checkbox on parent folders when only some descendant folders are selected. +- Keep partial-selection indicators visible while navigating between folder levels for Restic and Rsync source selection. +- Add a clear "Partially selected" label and tooltip to distinguish descendant selections from full-folder selections. + ### 2026.06.15.r020 - Add a guided Restic repository password change that creates and verifies a new key before removing the old key. - Update the encrypted URBM secret only after Restic accepts the new password, with automatic repository rollback on secret-storage failure. diff --git a/plugin/urbm.plg b/plugin/urbm.plg index b0de9a2..668f372 100644 --- a/plugin/urbm.plg +++ b/plugin/urbm.plg @@ -2,13 +2,18 @@ - + ]> +### 2026.06.15.r021 +- Show an orange mixed checkbox on parent folders when only some descendant folders are selected. +- Keep partial-selection indicators visible while navigating between folder levels for Restic and Rsync source selection. +- Add a clear "Partially selected" label and tooltip to distinguish descendant selections from full-folder selections. + ### 2026.06.15.r020 - Add a guided Restic repository password change that creates and verifies a new key before removing the old key. - Update the encrypted URBM secret only after Restic accepts the new password, with automatic repository rollback on secret-storage failure. diff --git a/webgui/URBM.page b/webgui/URBM.page index 3a07f45..0cefa3a 100644 --- a/webgui/URBM.page +++ b/webgui/URBM.page @@ -9,12 +9,12 @@ Tag="URBM Unraid Restic Backup Manager backup snapshots restore" - +
- -

URBM 2026.06.15.r020

Restic Backup Manager für Unraid

+ +

URBM 2026.06.15.r021

Restic Backup Manager für Unraid

Verbindung wird hergestellt...
@@ -32,4 +32,4 @@ $pluginRoot = '/plugins/urbm';
- + diff --git a/webgui/assets/urbm.css b/webgui/assets/urbm.css index 3291fdf..f95225e 100644 --- a/webgui/assets/urbm.css +++ b/webgui/assets/urbm.css @@ -80,6 +80,9 @@ .bu-selection-list { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0; } .bu-selection { background: var(--bu-panel-alt); border: 1px solid var(--bu-border); border-radius: 999px; color: var(--bu-text); font-size: 12px; padding: 4px 8px; } .bu-browser-card input[type="checkbox"], .bu-table input[type="checkbox"] { accent-color: var(--bu-accent); height: 20px; width: 20px; } +.bu-source-partial { background: rgba(255, 140, 47, .09); background: color-mix(in srgb, var(--bu-accent) 9%, transparent); } +.bu-source-partial .bu-source-select { accent-color: var(--bu-accent); } +.bu-partial-label { border: 1px solid var(--bu-accent); border-radius: 999px; color: var(--bu-text); display: inline-block; font-size: 11px; font-weight: 700; margin-left: 8px; padding: 2px 7px; vertical-align: middle; } .bu-count { align-items: center; border: 1px solid var(--bu-border); border-radius: 999px; display: inline-flex; font-size: 13px; font-weight: 700; padding: 7px 11px; } .bu-inline-error { background: rgba(180,35,47,.08); border: 1px solid var(--bu-bad); border-radius: 5px; color: var(--bu-bad); font-weight: 600; margin: 10px 0; padding: 10px 12px; } .bu-inline-info { background: rgba(19,138,98,.08); border: 1px solid var(--bu-good); border-radius: 5px; color: var(--bu-text); font-weight: 600; margin: 10px 0; padding: 10px 12px; } diff --git a/webgui/assets/urbm.js b/webgui/assets/urbm.js index 347ecac..744a052 100644 --- a/webgui/assets/urbm.js +++ b/webgui/assets/urbm.js @@ -448,10 +448,17 @@ const host = document.getElementById('bu-source-browser'); if (!host) return; const selected = new Set(state.backupSelections); - const rows = state.sourceDirectories.map(item => `Ordner${esc(item.name)}${esc(item.path)}${button('Öffnen',`open-source-dir:${encodeURIComponent(item.path)}`)}`).join(''); + const rows = state.sourceDirectories.map(item => { + const exact=selected.has(item.path); + const prefix=item.path.replace(/\/$/,'')+'/'; + const partial=!exact&&state.backupSelections.some(path=>path.startsWith(prefix)); + const hint=partial?'Ein oder mehrere Unterordner sind ausgewählt. Klicken, um den gesamten Ordner auszuwählen.':'Diesen Ordner als vollständige Backup-Quelle auswählen.'; + return `Ordner${esc(item.name)}${partial?'Teilweise ausgewählt':''}${esc(item.path)}${button('Öffnen',`open-source-dir:${encodeURIComponent(item.path)}`)}`; + }).join(''); const chosen = state.backupSelections.length ? state.backupSelections.map(path=>`${esc(path)}`).join('') : 'Keine Ordner ausgewählt.'; const error = state.sourceBrowserError ? `
${esc(state.sourceBrowserError)}
` : ''; host.innerHTML = `

Backup-Quellen auswählen

${esc(state.sourceBrowserPath)}
${state.sourceBrowserPath!=='/'?button('Aktuellen Ordner auswählen','select-current-source'):''}${state.sourceBrowserPath!=='/'?button('Nach oben','source-up'):''}Ausgewählt: ${state.backupSelections.length}
${error}
${chosen}
${rows||''}
AuswahlTypNamePfad
Keine Unterordner gefunden.
`; + host.querySelectorAll('.bu-source-select[data-partial="true"]').forEach(box=>{ box.indeterminate=true; box.setAttribute('aria-checked','mixed'); }); enhanceTooltips(host); }