From 60b346aa330dcfcfcd9b333300580a97abd275a2 Mon Sep 17 00:00:00 2001 From: Broque Thomas <26755000+Nezreka@users.noreply.github.com> Date: Mon, 25 May 2026 08:19:05 -0700 Subject: [PATCH] Standardize auto-sync modal cards Bring Auto-Sync automation and run-history cards closer to the Automations page pattern with status dots, flow chips, compact metadata, and denser run preview details. --- webui/static/auto-sync.js | 37 ++++++++-- webui/static/style.css | 143 ++++++++++++++++++++++++++------------ 2 files changed, 133 insertions(+), 47 deletions(-) diff --git a/webui/static/auto-sync.js b/webui/static/auto-sync.js index b9899fce..83fc38e6 100644 --- a/webui/static/auto-sync.js +++ b/webui/static/auto-sync.js @@ -469,13 +469,27 @@ function autoSyncHistoryEntryHtml(entry, index = 0) { return `
- ${_esc(autoSyncHistoryStatusLabel(status))} +
- ${_esc(playlistName)} +
+ ${_esc(playlistName)} + ${_esc(autoSyncHistoryStatusLabel(status))} +
+
+ ${_esc(entry.trigger_source || 'pipeline')} + + Refresh + + Discover + + Sync + wishlist +
${_esc(summary)}
${autoSyncHistoryPreviewPill('Tracks', before.track_count, after.track_count, trackDelta)} ${autoSyncHistoryPreviewPill('Discovered', before.discovered_count, after.discovered_count, discoveredDelta)} + ${autoSyncHistoryPreviewPill('Wishlisted', before.wishlisted_count, after.wishlisted_count, wishlistDelta)} + ${autoSyncHistoryPreviewPill('Library', before.in_library_count, after.in_library_count, libraryDelta)}
@@ -552,6 +566,12 @@ function autoSyncHistoryStatusLabel(status) { return status || 'Run'; } +function autoSyncHistoryStatusClass(status) { + if (status === 'completed' || status === 'finished') return 'enabled'; + if (status === 'error' || status === 'skipped') return 'disabled'; + return 'enabled'; +} + function autoSyncDurationLabel(seconds) { const total = Math.max(0, Math.round(parseFloat(seconds) || 0)); if (total < 60) return `${total}s`; @@ -600,15 +620,24 @@ function autoSyncAutomationCardHtml(auto, playlists) { const trigger = _autoFormatTrigger(auto.trigger_type, auto.trigger_config || {}); const enabled = auto.enabled !== false && auto.enabled !== 0; const next = auto.next_run ? autoSyncNextRunLabel(auto.next_run) : 'not scheduled'; + const sourceLabel = playlist ? autoSyncSourceLabel(playlist.source) : (cfg.all === true || cfg.all === 'true' ? 'All sources' : 'Pipeline'); return `
+
- ${enabled ? 'Enabled' : 'Disabled'} ${_esc(auto.name || 'Playlist Pipeline')}
+
+ ${_esc(trigger)} + + Playlist pipeline + + Refresh + sync +
- ${_esc(trigger)} + ${enabled ? 'Enabled' : 'Disabled'} + ${_esc(sourceLabel)} ${_esc(target)} ${_esc(next)}
diff --git a/webui/static/style.css b/webui/static/style.css index b9a75954..ef29229d 100644 --- a/webui/static/style.css +++ b/webui/static/style.css @@ -11927,16 +11927,17 @@ body.helper-mode-active #dashboard-activity-feed:hover { display: flex; align-items: center; justify-content: space-between; - gap: 16px; - padding: 14px 16px; - border: 1px solid rgba(255, 255, 255, 0.08); - border-radius: 8px; - background: rgba(255, 255, 255, 0.035); + gap: 12px; + padding: 12px 14px; + border: 1px solid rgba(255, 255, 255, 0.07); + border-radius: 10px; + background: rgba(22, 22, 22, 0.95); + overflow: hidden; } .auto-sync-automation-card:hover { - border-color: rgba(255, 255, 255, 0.14); - background: rgba(255, 255, 255, 0.055); + border-color: rgba(var(--accent-rgb), 0.2); + background: rgba(28, 28, 28, 0.98); } .auto-sync-automation-main { @@ -11953,12 +11954,66 @@ body.helper-mode-active #dashboard-activity-feed:hover { .auto-sync-automation-title-row strong { color: rgba(255, 255, 255, 0.88); - font-size: 14px; + font-size: 13px; + font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.auto-sync-card-status-dot { + width: 8px; + height: 8px; + border-radius: 50%; + flex-shrink: 0; +} + +.auto-sync-card-status-dot.enabled { + background: #4ade80; + box-shadow: 0 0 6px rgba(74, 222, 128, 0.4); +} + +.auto-sync-card-status-dot.disabled { + background: #555; +} + +.auto-sync-card-flow { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 6px; + margin-top: 5px; +} + +.auto-sync-card-flow .flow-trigger, +.auto-sync-card-flow .flow-action, +.auto-sync-card-flow .flow-notify { + font-size: 11px; + padding: 2px 8px; + border-radius: 10px; + white-space: nowrap; +} + +.auto-sync-card-flow .flow-trigger { + background: rgba(var(--accent-rgb), 0.12); + color: rgb(var(--accent-light-rgb)); +} + +.auto-sync-card-flow .flow-action { + background: rgba(88, 101, 242, 0.12); + color: #7289da; +} + +.auto-sync-card-flow .flow-notify { + background: rgba(250, 204, 21, 0.1); + color: #fbbf24; +} + +.auto-sync-card-flow .flow-arrow { + color: rgba(255, 255, 255, 0.25); + font-size: 12px; +} + .auto-sync-status { padding: 3px 7px; border-radius: 999px; @@ -11982,15 +12037,16 @@ body.helper-mode-active #dashboard-activity-feed:hover { display: flex; flex-wrap: wrap; gap: 8px; - margin-top: 8px; + margin-top: 7px; } .auto-sync-automation-meta span { - padding: 4px 8px; - border-radius: 6px; - background: rgba(255, 255, 255, 0.05); - color: rgba(255, 255, 255, 0.48); - font-size: 11px; + padding: 3px 7px; + border-radius: 8px; + background: rgba(255, 255, 255, 0.045); + color: rgba(255, 255, 255, 0.42); + font-size: 10px; + font-weight: 700; } .auto-sync-automation-lock { @@ -12025,13 +12081,11 @@ body.helper-mode-active #dashboard-activity-feed:hover { .auto-sync-history-entry { display: block; min-height: 84px; - border: 1px solid rgba(255, 255, 255, 0.1); + border: 1px solid rgba(255, 255, 255, 0.07); border-radius: 10px; - background: - linear-gradient(135deg, rgba(255, 255, 255, 0.055), rgba(255, 255, 255, 0.025)), - rgba(255, 255, 255, 0.035); + background: rgba(22, 22, 22, 0.95); overflow: hidden; - box-shadow: 0 10px 26px rgba(0, 0, 0, 0.14); + box-shadow: none; } .auto-sync-history-entry:empty { @@ -12048,21 +12102,18 @@ body.helper-mode-active #dashboard-activity-feed:hover { } .auto-sync-history-entry:hover { - border-color: rgba(var(--accent-rgb), 0.3); - background: - linear-gradient(135deg, rgba(var(--accent-rgb), 0.075), rgba(255, 255, 255, 0.028)), - rgba(255, 255, 255, 0.04); + border-color: rgba(var(--accent-rgb), 0.2); + background: rgba(28, 28, 28, 0.98); } .auto-sync-history-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; - gap: 14px; - min-height: 84px; - padding: 15px 16px; + gap: 12px; + min-height: 96px; + padding: 13px 14px; cursor: pointer; - background: rgba(255, 255, 255, 0.018); } .auto-sync-history-status { @@ -12095,25 +12146,32 @@ body.helper-mode-active #dashboard-activity-feed:hover { min-width: 0; } -.auto-sync-history-main strong, -.auto-sync-history-main small { - display: block; - overflow: hidden; - text-overflow: ellipsis; +.auto-sync-history-title-row { + display: flex; + align-items: center; + gap: 8px; + min-width: 0; } -.auto-sync-history-main strong { +.auto-sync-history-title-row strong { + min-width: 0; color: rgba(255, 255, 255, 0.88); - font-size: 14px; + font-size: 13px; + font-weight: 600; line-height: 1.25; + overflow: hidden; + text-overflow: ellipsis; white-space: nowrap; } .auto-sync-history-main small { + display: block; margin-top: 3px; - color: rgba(255, 255, 255, 0.5); - font-size: 12px; + color: rgba(255, 255, 255, 0.4); + font-size: 11px; line-height: 1.3; + overflow: hidden; + text-overflow: ellipsis; white-space: normal; } @@ -12121,17 +12179,16 @@ body.helper-mode-active #dashboard-activity-feed:hover { display: flex; flex-wrap: wrap; gap: 6px; - margin-top: 9px; + margin-top: 7px; } .auto-sync-history-preview span { - padding: 4px 7px; - border-radius: 6px; - background: rgba(var(--accent-rgb), 0.1); - border: 1px solid rgba(var(--accent-rgb), 0.16); - color: rgb(var(--accent-light-rgb)); + padding: 3px 7px; + border-radius: 8px; + background: rgba(255, 255, 255, 0.045); + color: rgba(255, 255, 255, 0.42); font-size: 10px; - font-weight: 800; + font-weight: 700; } .auto-sync-history-meta {