Recover migration results after refresh

This commit is contained in:
Paul Huliganga 2026-04-22 11:23:51 -04:00
parent fb54426bea
commit 9f27b95f07
1 changed files with 67 additions and 3 deletions

View File

@ -8,11 +8,53 @@ import { refreshTemplates } from './templates.js';
// ── Helpers ──────────────────────────────────────────────────────────────── // ── Helpers ────────────────────────────────────────────────────────────────
const _RESULTS_STORAGE_KEY = 'migrator_last_batch_results';
function getSettings() { function getSettings() {
try { return JSON.parse(localStorage.getItem('migrator_settings')) || {}; } try { return JSON.parse(localStorage.getItem('migrator_settings')) || {}; }
catch { return {}; } catch { return {}; }
} }
function persistLastResults(results) {
try {
sessionStorage.setItem(_RESULTS_STORAGE_KEY, JSON.stringify(results));
} catch {
// Best-effort only.
}
}
function loadPersistedResults() {
try {
const raw = sessionStorage.getItem(_RESULTS_STORAGE_KEY);
return raw ? JSON.parse(raw) : null;
} catch {
return null;
}
}
function buildResultsFromHistory(history) {
if (!history || !history.length) return null;
const sorted = [...history].sort((a, b) => String(b.timestamp || '').localeCompare(String(a.timestamp || '')));
const newestTimestamp = sorted[0]?.timestamp;
const recentBatch = sorted.filter(item => item.timestamp === newestTimestamp);
if (!recentBatch.length) return null;
return {
status: 'completed',
completed_at: newestTimestamp,
results: recentBatch,
summary: {
total: recentBatch.length,
success: recentBatch.filter(r => r.status === 'success').length,
failed: recentBatch.filter(r => r.status === 'failed' || r.status === 'blocked').length,
skipped: recentBatch.filter(r => r.status === 'skipped').length,
dry_run: recentBatch.filter(r => r.status === 'dry_run').length,
},
recovered_from_history: true,
};
}
// ── Options modal ────────────────────────────────────────────────────────── // ── Options modal ──────────────────────────────────────────────────────────
export function showOptionsModal(ids) { export function showOptionsModal(ids) {
@ -230,6 +272,7 @@ export async function pollJob(jobId, onProgress) {
if (data.status === 'done' || data.status === 'complete' || data.status === 'completed') { if (data.status === 'done' || data.status === 'complete' || data.status === 'completed') {
setState('lastMigrationResults', data); setState('lastMigrationResults', data);
persistLastResults(data);
resolve(data); resolve(data);
} else if (data.status === 'failed') { } else if (data.status === 'failed') {
reject(new Error('Migration job failed')); reject(new Error('Migration job failed'));
@ -248,16 +291,30 @@ export async function pollJob(jobId, onProgress) {
// ── Results view ─────────────────────────────────────────────────────────── // ── Results view ───────────────────────────────────────────────────────────
export function renderResults() { export async function renderResults() {
const outlet = document.getElementById('router-outlet'); const outlet = document.getElementById('router-outlet');
const results = state.lastMigrationResults; let results = state.lastMigrationResults || loadPersistedResults();
if (!results) {
try {
const data = await api.migrate.history();
results = buildResultsFromHistory(data.history || []);
} catch {
results = null;
}
}
if (results) {
setState('lastMigrationResults', results);
persistLastResults(results);
}
if (!results) { if (!results) {
outlet.innerHTML = ` outlet.innerHTML = `
<div class="empty-state"> <div class="empty-state">
<div class="empty-state-icon">📊</div> <div class="empty-state-icon">📊</div>
<div class="empty-state-title">No migration results yet</div> <div class="empty-state-title">No migration results yet</div>
<div class="empty-state-sub">Run a migration from the <a href="#/templates" style="color:var(--cobalt)">Templates</a> view to see results here.</div> <div class="empty-state-sub">Run a migration from the <a href="#/templates" style="color:var(--cobalt)">Templates</a> view to see results here. If templates already exist in DocuSign, use History &amp; Audit to review older runs.</div>
</div>`; </div>`;
return; return;
} }
@ -288,6 +345,13 @@ export function renderResults() {
</div> </div>
</div> </div>
${results.recovered_from_history ? `
<div class="callout info">
<span class="callout-icon"></span>
These results were recovered from recent migration history after the page state was reset.
</div>
` : ''}
<!-- Summary stat cards --> <!-- Summary stat cards -->
<div class="stat-grid" style="grid-template-columns:repeat(${summary.dry_run ? 6 : 5},1fr)"> <div class="stat-grid" style="grid-template-columns:repeat(${summary.dry_run ? 6 : 5},1fr)">
<div class="stat-card green"> <div class="stat-card green">