Fix auto-sync history card expansion

Bind run history card expand interactions after the modal renders instead of relying on inline handlers, and reshape the run cards into a clearer two-row layout with controlled metadata, preview chips, and roomier expanded detail padding.
This commit is contained in:
Broque Thomas 2026-05-25 08:28:36 -07:00
parent e86e74d640
commit 81ad3079b4
2 changed files with 72 additions and 29 deletions

View file

@ -245,6 +245,7 @@ function renderAutoSyncScheduleModal() {
<div class="auto-sync-tab-panel ${historyActive ? 'active' : ''}" id="auto-sync-history-panel">${historyPanel}</div> <div class="auto-sync-tab-panel ${historyActive ? 'active' : ''}" id="auto-sync-history-panel">${historyPanel}</div>
</div> </div>
`; `;
bindAutoSyncHistoryCardInteractions(overlay);
} }
function setAutoSyncTab(tab) { function setAutoSyncTab(tab) {
@ -460,8 +461,8 @@ function autoSyncHistoryEntryHtml(entry, index = 0) {
const playlistName = entry.playlist_name || after.name || before.name || `Playlist #${entry.playlist_id || 'unknown'}`; const playlistName = entry.playlist_name || after.name || before.name || `Playlist #${entry.playlist_id || 'unknown'}`;
const summary = entry.summary || autoSyncHistoryFallbackSummary(before, after, status); const summary = entry.summary || autoSyncHistoryFallbackSummary(before, after, status);
return ` return `
<article class="auto-sync-history-entry" id="${entryId}-card"> <article class="auto-sync-history-entry" id="${entryId}-card" data-history-entry="${entryId}">
<div class="auto-sync-history-row" role="button" tabindex="0" aria-expanded="false" aria-controls="${entryId}" onclick="autoSyncToggleHistoryEntry('${entryId}')" onkeydown="autoSyncHistoryEntryKeydown(event, '${entryId}')"> <div class="auto-sync-history-row" role="button" tabindex="0" aria-expanded="false" aria-controls="${entryId}" data-history-toggle="${entryId}">
<span class="auto-sync-card-status-dot ${autoSyncHistoryStatusClass(status)}"></span> <span class="auto-sync-card-status-dot ${autoSyncHistoryStatusClass(status)}"></span>
<div class="auto-sync-history-main"> <div class="auto-sync-history-main">
<div class="auto-sync-history-title-row"> <div class="auto-sync-history-title-row">
@ -478,18 +479,18 @@ function autoSyncHistoryEntryHtml(entry, index = 0) {
<span class="flow-notify">Sync + wishlist</span> <span class="flow-notify">Sync + wishlist</span>
</div> </div>
<small>${_esc(summary)}</small> <small>${_esc(summary)}</small>
<div class="auto-sync-history-preview">
${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)}
</div>
</div> </div>
<div class="auto-sync-history-meta"> <div class="auto-sync-history-meta">
${started ? `<span>${_esc(started)}</span>` : ''} ${started ? `<span>${_esc(started)}</span>` : ''}
${duration ? `<span>${_esc(duration)}</span>` : ''} ${duration ? `<span>${_esc(duration)}</span>` : ''}
<span>${_esc(entry.trigger_source || 'pipeline')}</span> <span>${_esc(entry.trigger_source || 'pipeline')}</span>
<span class="auto-sync-history-expand-label">Expand</span> <button type="button" class="auto-sync-history-expand-label" data-history-toggle-button="${entryId}">View details</button>
</div>
<div class="auto-sync-history-preview">
${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)}
</div> </div>
</div> </div>
<div id="${entryId}" class="auto-sync-history-detail"> <div id="${entryId}" class="auto-sync-history-detail">
@ -521,6 +522,21 @@ function autoSyncNormalizeHistoryEntry(entry, index) {
}; };
} }
function bindAutoSyncHistoryCardInteractions(root = document) {
root.querySelectorAll('[data-history-toggle]').forEach(row => {
const entryId = row.dataset.historyToggle;
row.addEventListener('click', () => autoSyncToggleHistoryEntry(entryId));
row.addEventListener('keydown', event => autoSyncHistoryEntryKeydown(event, entryId));
});
root.querySelectorAll('[data-history-toggle-button]').forEach(button => {
const entryId = button.dataset.historyToggleButton;
button.addEventListener('click', event => {
event.stopPropagation();
autoSyncToggleHistoryEntry(entryId);
});
});
}
function autoSyncParseHistoryObject(value) { function autoSyncParseHistoryObject(value) {
if (!value) return {}; if (!value) return {};
if (typeof value === 'object') return value; if (typeof value === 'object') return value;

View file

@ -12080,9 +12080,8 @@ body.helper-mode-active #dashboard-activity-feed:hover {
.auto-sync-history-entry { .auto-sync-history-entry {
display: block; display: block;
min-height: 84px;
border: 1px solid rgba(255, 255, 255, 0.07); border: 1px solid rgba(255, 255, 255, 0.07);
border-radius: 10px; border-radius: 12px;
background: rgba(22, 22, 22, 0.95); background: rgba(22, 22, 22, 0.95);
overflow: hidden; overflow: hidden;
box-shadow: none; box-shadow: none;
@ -12113,11 +12112,14 @@ body.helper-mode-active #dashboard-activity-feed:hover {
.auto-sync-history-row { .auto-sync-history-row {
display: grid; display: grid;
grid-template-columns: auto minmax(0, 1fr) auto; grid-template-columns: 16px minmax(280px, 1fr) minmax(160px, auto);
grid-template-areas:
"dot main meta"
". preview meta";
align-items: center; align-items: center;
gap: 12px; gap: 10px 16px;
min-height: 96px; min-height: 118px;
padding: 13px 14px; padding: 18px 20px;
cursor: pointer; cursor: pointer;
} }
@ -12153,7 +12155,9 @@ body.helper-mode-active #dashboard-activity-feed:hover {
} }
.auto-sync-history-main { .auto-sync-history-main {
grid-area: main;
min-width: 0; min-width: 0;
max-width: 760px;
} }
.auto-sync-history-title-row { .auto-sync-history-title-row {
@ -12161,13 +12165,14 @@ body.helper-mode-active #dashboard-activity-feed:hover {
align-items: center; align-items: center;
gap: 8px; gap: 8px;
min-width: 0; min-width: 0;
margin-bottom: 8px;
} }
.auto-sync-history-title-row strong { .auto-sync-history-title-row strong {
min-width: 0; min-width: 0;
color: rgba(255, 255, 255, 0.88); color: rgba(255, 255, 255, 0.88);
font-size: 13px; font-size: 15px;
font-weight: 600; font-weight: 700;
line-height: 1.25; line-height: 1.25;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
@ -12176,52 +12181,60 @@ body.helper-mode-active #dashboard-activity-feed:hover {
.auto-sync-history-main small { .auto-sync-history-main small {
display: block; display: block;
margin-top: 3px; margin-top: 8px;
color: rgba(255, 255, 255, 0.4); color: rgba(255, 255, 255, 0.4);
font-size: 11px; font-size: 12px;
line-height: 1.3; line-height: 1.45;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: normal; white-space: normal;
} }
.auto-sync-history-preview { .auto-sync-history-preview {
grid-area: preview;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 6px; gap: 8px;
margin-top: 7px; max-width: 760px;
} }
.auto-sync-history-preview span { .auto-sync-history-preview span {
padding: 3px 7px; padding: 6px 9px;
border-radius: 8px; border-radius: 8px;
background: rgba(255, 255, 255, 0.045); background: rgba(255, 255, 255, 0.045);
color: rgba(255, 255, 255, 0.42); color: rgba(255, 255, 255, 0.52);
font-size: 10px; font-size: 11px;
font-weight: 700; font-weight: 700;
} }
.auto-sync-history-meta { .auto-sync-history-meta {
grid-area: meta;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: flex-end; justify-content: flex-end;
align-content: center;
align-items: center;
gap: 6px; gap: 6px;
max-width: 190px; max-width: 240px;
} }
.auto-sync-history-meta span, .auto-sync-history-meta span,
.auto-sync-history-result span { .auto-sync-history-result span,
.auto-sync-history-meta button {
padding: 4px 7px; padding: 4px 7px;
border-radius: 6px; border-radius: 6px;
background: rgba(255, 255, 255, 0.055); background: rgba(255, 255, 255, 0.055);
border: 0;
color: rgba(255, 255, 255, 0.48); color: rgba(255, 255, 255, 0.48);
font-size: 10px; font-size: 10px;
font-weight: 700; font-weight: 700;
font-family: inherit;
} }
.auto-sync-history-meta .auto-sync-history-expand-label { .auto-sync-history-meta .auto-sync-history-expand-label {
border: 1px solid rgba(var(--accent-rgb), 0.18); border: 1px solid rgba(var(--accent-rgb), 0.18);
color: rgb(var(--accent-light-rgb)); color: rgb(var(--accent-light-rgb));
cursor: pointer;
padding-right: 20px; padding-right: 20px;
position: relative; position: relative;
} }
@ -12248,9 +12261,13 @@ body.helper-mode-active #dashboard-activity-feed:hover {
border-color: rgba(var(--accent-rgb), 0.35); border-color: rgba(var(--accent-rgb), 0.35);
} }
.auto-sync-history-entry .auto-sync-card-status-dot {
grid-area: dot;
}
.auto-sync-history-detail { .auto-sync-history-detail {
display: none; display: none;
padding: 16px; padding: 18px 20px 20px 52px;
border-top: 1px solid rgba(255, 255, 255, 0.07); border-top: 1px solid rgba(255, 255, 255, 0.07);
} }
@ -12558,8 +12575,14 @@ body.helper-mode-active #dashboard-activity-feed:hover {
} }
.auto-sync-history-row { .auto-sync-history-row {
grid-template-columns: 1fr; grid-template-columns: 12px minmax(0, 1fr);
grid-template-areas:
"dot main"
". preview"
". meta";
align-items: flex-start; align-items: flex-start;
min-height: 0;
padding: 16px;
} }
.auto-sync-history-meta { .auto-sync-history-meta {
@ -12567,6 +12590,10 @@ body.helper-mode-active #dashboard-activity-feed:hover {
max-width: none; max-width: none;
} }
.auto-sync-history-detail {
padding: 16px;
}
.auto-sync-history-stats { .auto-sync-history-stats {
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
} }