Harden auto-sync history row rendering
Normalize sparse playlist pipeline history rows before rendering and add a visible fallback for empty entries so the Run History tab cannot collapse into unreadable divider lines.
This commit is contained in:
parent
06c76bbcaf
commit
119e8f1599
2 changed files with 53 additions and 2 deletions
|
|
@ -438,13 +438,14 @@ function renderAutoSyncHistoryPanel(history, total) {
|
|||
<button onclick="refreshAutoSyncScheduleModal()">Refresh</button>
|
||||
</div>
|
||||
<div class="auto-sync-history-list">
|
||||
${history.map(autoSyncHistoryEntryHtml).join('')}
|
||||
${history.map((entry, index) => autoSyncHistoryEntryHtml(entry, index)).join('')}
|
||||
${total > history.length ? `<div class="auto-sync-history-total">Showing ${history.length} of ${total} runs</div>` : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function autoSyncHistoryEntryHtml(entry) {
|
||||
function autoSyncHistoryEntryHtml(entry, index = 0) {
|
||||
entry = autoSyncNormalizeHistoryEntry(entry, index);
|
||||
const status = entry.status || 'completed';
|
||||
const before = entry.before_json || {};
|
||||
const after = entry.after_json || {};
|
||||
|
|
@ -499,6 +500,40 @@ function autoSyncHistoryEntryHtml(entry) {
|
|||
`;
|
||||
}
|
||||
|
||||
function autoSyncNormalizeHistoryEntry(entry, index) {
|
||||
if (!entry || typeof entry !== 'object') {
|
||||
return {
|
||||
id: `unknown-${index}`,
|
||||
status: 'completed',
|
||||
playlist_name: 'Playlist pipeline run',
|
||||
trigger_source: 'pipeline',
|
||||
summary: 'Run history entry did not include detailed metadata.',
|
||||
before_json: {},
|
||||
after_json: {},
|
||||
result_json: {},
|
||||
};
|
||||
}
|
||||
return {
|
||||
...entry,
|
||||
id: entry.id ?? `history-${index}`,
|
||||
before_json: autoSyncParseHistoryObject(entry.before_json),
|
||||
after_json: autoSyncParseHistoryObject(entry.after_json),
|
||||
result_json: autoSyncParseHistoryObject(entry.result_json),
|
||||
};
|
||||
}
|
||||
|
||||
function autoSyncParseHistoryObject(value) {
|
||||
if (!value) return {};
|
||||
if (typeof value === 'object') return value;
|
||||
if (typeof value !== 'string') return {};
|
||||
try {
|
||||
const parsed = JSON.parse(value);
|
||||
return parsed && typeof parsed === 'object' ? parsed : {};
|
||||
} catch (_err) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function autoSyncHistoryFallbackSummary(before, after, status) {
|
||||
const beforeTracks = parseInt(before.track_count, 10) || 0;
|
||||
const afterTracks = parseInt(after.track_count, 10) || 0;
|
||||
|
|
|
|||
|
|
@ -12023,6 +12023,8 @@ 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-radius: 10px;
|
||||
background:
|
||||
|
|
@ -12032,6 +12034,19 @@ body.helper-mode-active #dashboard-activity-feed:hover {
|
|||
box-shadow: 0 10px 26px rgba(0, 0, 0, 0.14);
|
||||
}
|
||||
|
||||
.auto-sync-history-entry:empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.auto-sync-history-entry:empty::before {
|
||||
content: 'Run history entry unavailable. Refresh after the next playlist pipeline run.';
|
||||
color: rgba(255, 255, 255, 0.58);
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.auto-sync-history-entry:hover {
|
||||
border-color: rgba(var(--accent-rgb), 0.3);
|
||||
background:
|
||||
|
|
@ -12047,6 +12062,7 @@ body.helper-mode-active #dashboard-activity-feed:hover {
|
|||
min-height: 84px;
|
||||
padding: 15px 16px;
|
||||
cursor: pointer;
|
||||
background: rgba(255, 255, 255, 0.018);
|
||||
}
|
||||
|
||||
.auto-sync-history-status {
|
||||
|
|
|
|||
Loading…
Reference in a new issue