Keep activity messages within table bounds

This commit is contained in:
Mikei386
2026-06-15 00:31:16 +02:00
parent e23563afb1
commit b93b06ec20
8 changed files with 31 additions and 12 deletions
-1
View File
@@ -1 +0,0 @@
6dad60f99de38355bfe32185dc0437f208ac69c6f09f02c2965390a873347d82 urbm-2026.06.15.r002-x86_64-1.txz
+1
View File
@@ -0,0 +1 @@
87517e9e5e8d7b255576173f55c9092551c161e84ea2a95c0301ca06c5c5b519 urbm-2026.06.15.r003-x86_64-1.txz
+6 -2
View File
@@ -2,13 +2,17 @@
<!DOCTYPE PLUGIN [ <!DOCTYPE PLUGIN [
<!ENTITY name "urbm"> <!ENTITY name "urbm">
<!ENTITY author "Michael Roll"> <!ENTITY author "Michael Roll">
<!ENTITY version "2026.06.15.r002"> <!ENTITY version "2026.06.15.r003">
<!ENTITY pluginURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm.plg"> <!ENTITY pluginURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm.plg">
<!ENTITY packageURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm-&version;-x86_64-1.txz"> <!ENTITY packageURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm-&version;-x86_64-1.txz">
<!ENTITY packageSHA256 "6dad60f99de38355bfe32185dc0437f208ac69c6f09f02c2965390a873347d82"> <!ENTITY packageSHA256 "87517e9e5e8d7b255576173f55c9092551c161e84ea2a95c0301ca06c5c5b519">
]> ]>
<PLUGIN name="&name;" author="&author;" version="&version;" pluginURL="&pluginURL;" min="7.0.0" support="https://git.casaderoll.de/michael/URBM/issues" icon="urbm.png"> <PLUGIN name="&name;" author="&author;" version="&version;" pluginURL="&pluginURL;" min="7.0.0" support="https://git.casaderoll.de/michael/URBM/issues" icon="urbm.png">
<CHANGES> <CHANGES>
### 2026.06.15.r003
- Keep activity tables inside their cards by wrapping long messages, paths, and job IDs and removing oversized empty action columns.
- Add controlled horizontal scrolling for activity tables on narrow displays.
### 2026.06.15.r002 ### 2026.06.15.r002
- Add a confirmed repository unlock action that invokes Restic's safe stale-lock cleanup without `--remove-all`. - Add a confirmed repository unlock action that invokes Restic's safe stale-lock cleanup without `--remove-all`.
+5 -1
View File
@@ -2,13 +2,17 @@
<!DOCTYPE PLUGIN [ <!DOCTYPE PLUGIN [
<!ENTITY name "urbm"> <!ENTITY name "urbm">
<!ENTITY author "Michael Roll"> <!ENTITY author "Michael Roll">
<!ENTITY version "2026.06.15.r002"> <!ENTITY version "2026.06.15.r003">
<!ENTITY pluginURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm.plg"> <!ENTITY pluginURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm.plg">
<!ENTITY packageURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm-&version;-x86_64-1.txz"> <!ENTITY packageURL "https://git.casaderoll.de/michael/URBM/raw/branch/main/dist/urbm-&version;-x86_64-1.txz">
<!ENTITY packageSHA256 "REPLACE_DURING_RELEASE"> <!ENTITY packageSHA256 "REPLACE_DURING_RELEASE">
]> ]>
<PLUGIN name="&name;" author="&author;" version="&version;" pluginURL="&pluginURL;" min="7.0.0" support="https://git.casaderoll.de/michael/URBM/issues" icon="urbm.png"> <PLUGIN name="&name;" author="&author;" version="&version;" pluginURL="&pluginURL;" min="7.0.0" support="https://git.casaderoll.de/michael/URBM/issues" icon="urbm.png">
<CHANGES> <CHANGES>
### 2026.06.15.r003
- Keep activity tables inside their cards by wrapping long messages, paths, and job IDs and removing oversized empty action columns.
- Add controlled horizontal scrolling for activity tables on narrow displays.
### 2026.06.15.r002 ### 2026.06.15.r002
- Add a confirmed repository unlock action that invokes Restic's safe stale-lock cleanup without `--remove-all`. - Add a confirmed repository unlock action that invokes Restic's safe stale-lock cleanup without `--remove-all`.
+4 -4
View File
@@ -9,12 +9,12 @@ Tag="URBM Unraid Restic Backup Manager backup snapshots restore"
<?php <?php
$pluginRoot = '/plugins/urbm'; $pluginRoot = '/plugins/urbm';
?> ?>
<link rel="stylesheet" href="<?= $pluginRoot ?>/assets/urbm.css?v=20260615r002"> <link rel="stylesheet" href="<?= $pluginRoot ?>/assets/urbm.css?v=20260615r003">
<div id="urbm-app" data-api="<?= $pluginRoot ?>/api.php"> <div id="urbm-app" data-api="<?= $pluginRoot ?>/api.php">
<header class="bu-header"> <header class="bu-header">
<div class="bu-brand"> <div class="bu-brand">
<img class="bu-logo" src="<?= $pluginRoot ?>/images/urbm.png?v=20260615r002" alt="URBM-Logo"> <img class="bu-logo" src="<?= $pluginRoot ?>/images/urbm.png?v=20260615r003" alt="URBM-Logo">
<div><h1>URBM <span class="bu-version">2026.06.15.r002</span></h1><p>Restic Backup Manager für Unraid</p></div> <div><h1>URBM <span class="bu-version">2026.06.15.r003</span></h1><p>Restic Backup Manager für Unraid</p></div>
</div> </div>
<div id="bu-health" class="bu-health" tabindex="0" data-tooltip="Zeigt, ob die URBM-Hintergrundkomponente erreichbar ist. Beispiel: 'Daemon online' bedeutet, dass Jobs gestartet werden können.">Verbindung wird hergestellt...</div> <div id="bu-health" class="bu-health" tabindex="0" data-tooltip="Zeigt, ob die URBM-Hintergrundkomponente erreichbar ist. Beispiel: 'Daemon online' bedeutet, dass Jobs gestartet werden können.">Verbindung wird hergestellt...</div>
</header> </header>
@@ -32,4 +32,4 @@ $pluginRoot = '/plugins/urbm';
<div id="bu-tooltip" role="tooltip" aria-hidden="true"></div> <div id="bu-tooltip" role="tooltip" aria-hidden="true"></div>
</div> </div>
<script>window.URBM_CSRF = <?= json_encode($var['csrf_token'] ?? '') ?>;</script> <script>window.URBM_CSRF = <?= json_encode($var['csrf_token'] ?? '') ?>;</script>
<script src="<?= $pluginRoot ?>/assets/urbm-2026.06.15.r002.js"></script> <script src="<?= $pluginRoot ?>/assets/urbm-2026.06.15.r003.js"></script>
+14 -3
View File
@@ -97,13 +97,13 @@
#urbm-app .bu-weekdays input:checked + span { background: var(--bu-accent) !important; border-color: var(--bu-accent) !important; color: #fff !important; } #urbm-app .bu-weekdays input:checked + span { background: var(--bu-accent) !important; border-color: var(--bu-accent) !important; color: #fff !important; }
.bu-custom-cron { margin-top: 14px; } .bu-custom-cron { margin-top: 14px; }
.bu-event-options { display: flex; flex-wrap: wrap; gap: 10px; } .bu-event-options { display: flex; flex-wrap: wrap; gap: 10px; }
.bu-progress-wrap { min-width: 280px; } .bu-progress-wrap { min-width: 0; width: 100%; }
.bu-progress-label { align-items: center; display: flex; font-size: 12px; gap: 8px; justify-content: space-between; margin-bottom: 5px; } .bu-progress-label { align-items: center; display: flex; font-size: 12px; gap: 8px; justify-content: space-between; margin-bottom: 5px; }
.bu-progress-label span { color: var(--bu-muted); } .bu-progress-label span { color: var(--bu-muted); overflow-wrap: anywhere; text-align: right; }
.bu-progress { background: var(--bu-panel-alt); border: 1px solid var(--bu-border); border-radius: 999px; height: 12px; overflow: hidden; } .bu-progress { background: var(--bu-panel-alt); border: 1px solid var(--bu-border); border-radius: 999px; height: 12px; overflow: hidden; }
.bu-progress span { background: var(--bu-accent); display: block; height: 100%; min-width: 0; transition: width .35s ease; } .bu-progress span { background: var(--bu-accent); display: block; height: 100%; min-width: 0; transition: width .35s ease; }
.bu-progress.indeterminate span { animation: bu-progress-scan 1.2s ease-in-out infinite alternate; } .bu-progress.indeterminate span { animation: bu-progress-scan 1.2s ease-in-out infinite alternate; }
.bu-current-file { color: var(--bu-muted); font-size: 12px; margin-top: 5px; max-width: 440px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .bu-current-file { color: var(--bu-muted); font-size: 12px; margin-top: 5px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bu-log-row td { border-top: 0 !important; padding-top: 0 !important; } .bu-log-row td { border-top: 0 !important; padding-top: 0 !important; }
.bu-live-log { background: #11161a; border: 1px solid var(--bu-border); border-radius: 6px; color: #e8edf1; margin: 2px 0 8px; padding: 9px 12px; } .bu-live-log { background: #11161a; border: 1px solid var(--bu-border); border-radius: 6px; color: #e8edf1; margin: 2px 0 8px; padding: 9px 12px; }
.bu-live-log summary { cursor: pointer; font-weight: 700; } .bu-live-log summary { cursor: pointer; font-weight: 700; }
@@ -141,6 +141,17 @@
.bu-table { border-collapse: collapse; color: var(--bu-text); width: 100%; } .bu-table { border-collapse: collapse; color: var(--bu-text); width: 100%; }
.bu-table th, .bu-table td { border-bottom: 1px solid var(--bu-border); color: var(--bu-text); padding: 12px 8px; text-align: left; vertical-align: top; } .bu-table th, .bu-table td { border-bottom: 1px solid var(--bu-border); color: var(--bu-text); padding: 12px 8px; text-align: left; vertical-align: top; }
.bu-table th { color: var(--bu-text); font-size: 13px; font-weight: 700; letter-spacing: .03em; opacity: .76; text-transform: uppercase; } .bu-table th { color: var(--bu-text); font-size: 13px; font-weight: 700; letter-spacing: .03em; opacity: .76; text-transform: uppercase; }
.bu-table-scroll { max-width: 100%; overflow-x: auto; }
.bu-runs-table { table-layout: fixed; }
.bu-runs-table .bu-run-task { width: 18%; }
.bu-runs-table .bu-run-status { width: 8%; }
.bu-runs-table .bu-run-created { width: 11%; }
.bu-runs-table .bu-run-progress { width: 27%; }
.bu-runs-table .bu-run-message { width: 30%; }
.bu-runs-table .bu-run-actions { width: 6%; }
.bu-runs-table th, .bu-runs-table td { min-width: 0; overflow-wrap: anywhere; word-break: break-word; }
.bu-runs-table .bu-run-message-cell { line-height: 1.45; white-space: normal; }
.bu-runs-table .bu-table-actions { min-width: 0; }
.bu-status { border: 1px solid currentColor; border-radius: 999px; display: inline-block; font-size: 12px; font-weight: 700; padding: 3px 8px; text-transform: uppercase; } .bu-status { border: 1px solid currentColor; border-radius: 999px; display: inline-block; font-size: 12px; font-weight: 700; padding: 3px 8px; text-transform: uppercase; }
.bu-status.success { background: rgba(8,122,85,.10); color: var(--bu-good); } .bu-status.success { background: rgba(8,122,85,.10); color: var(--bu-good); }
.bu-status.failed, .bu-status.cancelled { background: rgba(180,35,47,.10); color: var(--bu-bad); } .bu-status.failed, .bu-status.cancelled { background: rgba(180,35,47,.10); color: var(--bu-bad); }
+1 -1
View File
@@ -513,7 +513,7 @@
function runsTable(runs) { function runsTable(runs) {
if(!runs.length) return '<div class="bu-empty">Keine Aktivitäten vorhanden.</div>'; if(!runs.length) return '<div class="bu-empty">Keine Aktivitäten vorhanden.</div>';
const showLiveLog=state.config?.settings?.showLiveLog===true; const showLiveLog=state.config?.settings?.showLiveLog===true;
return `<table class="bu-table bu-runs-table"><thead><tr><th>Aufgabe</th><th>Status</th><th>Erstellt</th><th>Fortschritt</th><th>Meldung</th><th></th></tr></thead><tbody>${runs.map(r=>{const controls=r.status==='running'?button('Pause',`pause-run:${r.id}`)+button('Abbrechen',`cancel-run:${r.id}`,'danger'):r.status==='paused'?button('Fortsetzen',`resume-run:${r.id}`,'primary')+button('Abbrechen',`cancel-run:${r.id}`,'danger'):r.status==='queued'?button('Abbrechen',`cancel-run:${r.id}`,'danger'):'';return `<tr><td>${esc(taskLabels[r.taskType]||r.taskType)} ${esc(r.jobId||'')}</td><td>${status(r.status)}</td><td>${esc(new Date(r.createdAt).toLocaleString())}</td><td>${progressView(r)}</td><td>${esc(displayMessage(r.message))}</td><td>${actionGroup(controls)}</td></tr>${showLiveLog&&(r.liveLog||[]).length?`<tr class="bu-log-row"><td colspan="6">${liveLogView(r)}</td></tr>`:''}`;}).join('')}</tbody></table>`; return `<div class="bu-table-scroll"><table class="bu-table bu-runs-table"><colgroup><col class="bu-run-task"><col class="bu-run-status"><col class="bu-run-created"><col class="bu-run-progress"><col class="bu-run-message"><col class="bu-run-actions"></colgroup><thead><tr><th>Aufgabe</th><th>Status</th><th>Erstellt</th><th>Fortschritt</th><th>Meldung</th><th></th></tr></thead><tbody>${runs.map(r=>{const controls=r.status==='running'?button('Pause',`pause-run:${r.id}`)+button('Abbrechen',`cancel-run:${r.id}`,'danger'):r.status==='paused'?button('Fortsetzen',`resume-run:${r.id}`,'primary')+button('Abbrechen',`cancel-run:${r.id}`,'danger'):r.status==='queued'?button('Abbrechen',`cancel-run:${r.id}`,'danger'):'';return `<tr><td class="bu-run-task-cell">${esc(taskLabels[r.taskType]||r.taskType)} ${esc(r.jobId||'')}</td><td>${status(r.status)}</td><td>${esc(new Date(r.createdAt).toLocaleString())}</td><td>${progressView(r)}</td><td class="bu-run-message-cell">${esc(displayMessage(r.message))}</td><td>${controls?actionGroup(controls):''}</td></tr>${showLiveLog&&(r.liveLog||[]).length?`<tr class="bu-log-row"><td colspan="6">${liveLogView(r)}</td></tr>`:''}`;}).join('')}</tbody></table></div>`;
} }
function renderSettings() { function renderSettings() {