diff --git a/containers/libreportal/frontend/components/apps/overview/css/overview.css b/containers/libreportal/frontend/components/apps/overview/css/overview.css index 6ef6b3e..df162aa 100644 --- a/containers/libreportal/frontend/components/apps/overview/css/overview.css +++ b/containers/libreportal/frontend/components/apps/overview/css/overview.css @@ -195,17 +195,67 @@ padding: 12px 14px; } .ov-row-head .updater-row-ver { margin-left: auto; } -.ov-row-head .ov-row-actions { margin-left: 12px; } -.ov-chevron { - flex: 0 0 auto; - display: inline-block; - font-size: .8rem; - opacity: .7; - transition: transform .18s ease; -} -.ov-row-head[aria-expanded="true"] .ov-chevron { transform: rotate(90deg); } +.ov-row-head .ov-row-actions { margin-left: 12px; display: flex; align-items: center; gap: 8px; } .ov-row-head:focus-visible { outline: 2px solid rgba(var(--page-updater-rgb), .7); outline-offset: -2px; } +/* Tasks-style app row: icon tile + status pill + Details toggle -------------- */ +.ov-row-icon { + flex: 0 0 auto; + width: 32px; + height: 32px; + border-radius: 8px; + object-fit: contain; + padding: 3px; + border: 1px solid var(--border-color, rgba(255, 255, 255, .14)); + background: rgba(255, 255, 255, .04); +} +.ov-status { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 2px 9px; + border-radius: 999px; + font-size: .72rem; + font-weight: 600; + letter-spacing: .02em; + white-space: nowrap; +} +.ov-status-ok { + background: rgba(var(--status-success-rgb), .18); + border: 1px solid rgba(var(--status-success-rgb), .45); + color: #86efac; +} +.ov-status-update { + background: rgba(var(--status-warning-rgb), .18); + border: 1px solid rgba(var(--status-warning-rgb), .5); + color: #fcd34d; +} +.ov-status-unknown { + background: rgba(255, 255, 255, .06); + border: 1px solid rgba(255, 255, 255, .16); + color: var(--text-muted, rgba(255, 255, 255, .6)); +} +.ov-details-btn { + display: inline-flex; + align-items: center; + gap: 4px; + padding: 4px 10px; + border-radius: 6px; + border: 1px solid var(--border-color, rgba(255, 255, 255, .14)); + background: rgba(255, 255, 255, .04); + color: var(--text-secondary, rgba(255, 255, 255, .7)); + font-size: .72rem; + cursor: pointer; + transition: background .15s ease, border-color .15s ease, color .15s ease; +} +.ov-details-btn:hover { + background: rgba(var(--page-updater-rgb), .16); + border-color: rgba(var(--page-updater-rgb), .5); + color: #fff; +} +.ov-details-btn svg { transition: transform .18s ease; } +.ov-row-head[aria-expanded="true"] .ov-details-btn svg { transform: rotate(180deg); } + .ov-row-details { display: none; padding: 4px 16px 16px; border-top: 1px solid var(--border-color, rgba(255, 255, 255, .1)); } .ov-row-details.ov-open { display: block; } diff --git a/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js b/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js index 6690776..168bcbc 100644 --- a/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js +++ b/containers/libreportal/frontend/components/apps/overview/js/overview-manager.js @@ -538,23 +538,25 @@ class OverviewManager { updateRow(a) { const esc = (s) => this.escape(s); + const slug = esc(a.name); + const name = esc((window.getAppDisplayName ? window.getAppDisplayName(a.name) : null) || a.displayName || a.name); const cur = esc(a.current_version || a.current_image || '—'); const avail = a.update_available ? esc(a.available_version || a.available_image || 'newer') : null; - const badge = a.update_available - ? `update` - : (a.scanned ? `up to date` : `unscanned`); + const status = a.update_available + ? `↑ Update available` + : (a.scanned ? `✓ Up to date` : `• Unscanned`); const sev = a.worstSeverity ? `${a.worstSeverity}` : ''; const updBtn = a.update_available - ? `` + ? `` : ''; - return `
-