feat(setup): add done button and integrate NFO scan into initialization

- Add /api/setup/unresolved/done endpoint to mark phase complete
- NFO scan now runs after series sync during initialization
- Middleware redirects to /login after setup complete (was /loading)
- Done button allows skipping folder resolution with redirect to NFO scan phase
This commit is contained in:
2026-06-06 23:47:48 +02:00
parent be7b210959
commit 275aeb4544
7 changed files with 332 additions and 31 deletions

View File

@@ -281,11 +281,13 @@
let isComplete = false;
const stepOrder = [
'series_sync'
'series_sync',
'nfo_scan'
];
const stepTitles = {
'series_sync': 'Syncing Series Database'
'series_sync': 'Syncing Series Database',
'nfo_scan': 'Scanning NFO Files'
};
function connectWebSocket() {
@@ -305,6 +307,14 @@
room: 'system'
}
}));
// Subscribe to scan room for NFO scan progress
ws.send(JSON.stringify({
action: 'join',
data: {
room: 'scan'
}
}));
};
ws.onmessage = (event) => {
@@ -349,6 +359,12 @@
const data = message.data || message;
const { type, status, title, message: msg, percent, current, total, metadata } = data;
// Handle NFO scan events
if (type === 'nfo_scan_started' || type === 'nfo_scan_progress' || type === 'nfo_scan_completed') {
handleNfoScanUpdate(data);
return;
}
// Determine step ID based on type and metadata
let stepId = metadata?.step_id || type;
@@ -370,6 +386,75 @@
}
}
function handleNfoScanUpdate(data) {
const stepId = 'nfo_scan';
if (!steps.has(stepId)) {
createStep(stepId, stepTitles[stepId] || 'Scanning NFO Files');
}
const stepEl = steps.get(stepId);
if (!stepEl) return;
const iconEl = stepEl.querySelector('.step-icon');
const statusEl = stepEl.querySelector('.step-status');
const messageEl = stepEl.querySelector('.step-message');
const progressEl = stepEl.querySelector('.step-progress');
const progressFillEl = stepEl.querySelector('.progress-bar-fill');
const progressTextEl = stepEl.querySelector('.progress-text');
const nfoData = data.data || data;
const { status, message, current, total, key, folder } = nfoData;
// Update status
stepEl.className = 'progress-step';
if (status === 'started') {
stepEl.classList.add('active');
iconEl.className = 'fas fa-circle-notch fa-spin step-icon loading';
statusEl.textContent = 'Starting...';
} else if (status === 'in_progress') {
stepEl.classList.add('active');
iconEl.className = 'fas fa-circle-notch fa-spin step-icon loading';
statusEl.textContent = 'In Progress...';
} else if (status === 'completed') {
stepEl.classList.add('completed');
iconEl.className = 'fas fa-check-circle step-icon completed';
statusEl.textContent = 'Complete';
} else if (status === 'failed') {
stepEl.classList.add('error');
iconEl.className = 'fas fa-exclamation-circle step-icon error';
statusEl.textContent = 'Failed';
}
// Update message - show current folder being processed
if (message) {
messageEl.textContent = message;
messageEl.style.display = 'block';
} else if (key && folder) {
messageEl.textContent = `Processing: ${folder}`;
messageEl.style.display = 'block';
}
// Update progress bar
if (current > 0 && total > 0) {
const actualPercent = (current / total) * 100;
progressEl.style.display = 'block';
progressFillEl.style.width = `${actualPercent}%`;
progressTextEl.textContent = `${current}/${total} series`;
} else if (percent > 0) {
progressEl.style.display = 'block';
progressFillEl.style.width = `${percent}%`;
progressTextEl.textContent = `${Math.round(percent)}%`;
}
// Check for completion
if (data.type === 'nfo_scan_completed') {
setTimeout(() => {
checkUnresolvedAndProceed();
}, 1000);
}
}
function createStep(stepId, title) {
const container = document.getElementById('progressContainer');
@@ -475,8 +560,8 @@
}
async function checkUnresolvedAndProceed() {
// Fetch unresolved folders and only redirect if there are any
// Otherwise go directly to login
// Always check for unresolved folders first
// After setup -> loading, always go through unresolved if there are any
try {
const token = localStorage.getItem('auth_token');
const res = await fetch('/api/setup/unresolved', {
@@ -493,7 +578,7 @@
} catch (err) {
console.error('Failed to check unresolved folders:', err);
}
// No unresolved folders or error - go to login
// No unresolved folders - go to login
window.location.href = '/login';
}