diff --git a/web/static/css/modals.css b/web/static/css/modals.css index 9e52c20..432a7bf 100644 --- a/web/static/css/modals.css +++ b/web/static/css/modals.css @@ -118,6 +118,7 @@ .progress-template-row { display: flex; align-items: center; + flex-wrap: wrap; gap: 10px; padding: 8px 12px; background: var(--ecru); @@ -126,6 +127,16 @@ } .progress-template-name { flex: 1; font-weight: 500; } .progress-template-status { font-size: 16px; flex-shrink: 0; } +.progress-template-error { + flex-basis: 100%; + font-size: 11px; + color: var(--error, #c0392b); + margin-top: -4px; + padding-left: 2px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} /* ── Project switcher modal ── */ .project-list { diff --git a/web/static/js/migration.js b/web/static/js/migration.js index 47fe536..32099d2 100644 --- a/web/static/js/migration.js +++ b/web/static/js/migration.js @@ -162,15 +162,36 @@ async function _startMigration(ids, wrapper) { const statusEl = row.querySelector('.progress-template-status'); if (!statusEl) return; statusEl.className = 'progress-template-status'; - if (r.status === 'success') statusEl.textContent = r.action === 'created' ? '✅' : r.action === 'dry_run' ? '🔍' : '✏️'; + if (r.status === 'success') statusEl.textContent = r.action === 'created' ? '✅' : r.action === 'dry_run' ? '🔍' : '✏️'; else if (r.status === 'skipped') statusEl.textContent = '⏭'; else if (r.status === 'blocked') statusEl.textContent = '🚫'; - else statusEl.textContent = '❌'; + else statusEl.textContent = '❌'; + + if (r.status === 'blocked' || r.status === 'error' || r.status === 'failed') { + const msg = r.error || (r.blockers||[])[0] || 'Migration failed'; + let hint = row.querySelector('.progress-template-error'); + if (!hint) { + hint = document.createElement('div'); + hint.className = 'progress-template-error'; + row.appendChild(hint); + } + hint.textContent = msg; + } }); }); // Migration done — show "View Results" button + const allResults = (jobData.results || []); + const failCount = allResults.filter(r => r.status === 'blocked' || r.status === 'error' || r.status === 'failed').length; document.getElementById('prog-label') && (document.getElementById('prog-label').textContent = 'Done!'); + + if (failCount > 0) { + const hint = document.createElement('div'); + hint.style.cssText = 'font-size:12px;color:var(--text-muted);margin-top:10px;text-align:center'; + hint.textContent = `${failCount} template${failCount > 1 ? 's' : ''} had issues — select View Results for details.`; + body.appendChild(hint); + } + footer.innerHTML = `