refactor(docs): restructure navigation as state machine

Replaced linear flow diagram with explicit state definitions and
transition table. Removes MIGRATION_GUIDE.md (merged into main docs).
This commit is contained in:
2026-06-07 20:02:51 +02:00
parent 4e0c66ea9e
commit b800158648
2 changed files with 111 additions and 195 deletions

View File

@@ -4,54 +4,56 @@ This document describes the setup flow navigation, covering how users progress f
## Overview
The application uses a middleware-based redirect system to ensure users complete setup before accessing the main app. The flow involves multiple pages handling setup completion, unresolved folder detection, and initialization.
The application uses a middleware-based redirect system to enforce a strict state machine. Users must complete each phase before accessing the next. Attempting to bypass the current phase redirects to the appropriate page.
## Setup Flow
## State Machine
```
┌─────────────────────────────────────────────────────────────────────┐
SETUP FLOW
├─────────────────────────────────────────────────────────────────────┤
│ │
/setup ──► /loading ──► /setup/unresolved ──► /loading ──► /login
(first (Series Scan + (has folders) (all resolved)
time) NFO Scan)
│ │
[Done button] ──► marks complete
│ │
/loading (NFO phase runs again)
└────────┴─────────────────────────────────────┘
│ │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────
NAVIGATION STATES
├─────────────────────────────────────────────────────────────────────────
NO_SETUP ──────────► SETUP_COMPLETE ──────────► UNRESOLVED_PENDING
│ │ │
│ │ │
│ ▼ ▼
/setup /loading /setup/unresolved │
(series scan) (resolve folders)
UNRESOLVED_DONE ───────┐
NFO_SCAN_PENDING
/loading
(NFO scan) │
│ ▼ │
│ COMPLETE │
│ │ │
│ ▼ │
│ /login │
│ │
└─────────────────────────────────────────────────────────────────────────┘
```
**New Navigation Order:**
1. `/setup` → Initial configuration
2. `/loading` → Series scan + NFO scan
3. `/setup/unresolved` → Resolve folders (if any)
4. `/loading` → NFO scan runs again
5. `/login` → Authentication
## State Definitions
**Key Changes:**
- After `/setup/unresolved`, the "Done" button marks the phase as complete
- Revisiting `/setup/unresolved` after completion → redirects to `/loading`
- `/loading` always goes to `/setup/unresolved` if unresolved folders exist
- NFO scan runs as a separate phase after series sync during initialization
| State | Condition | Target Page |
|-------|-----------|-------------|
| `NO_SETUP` | No master password configured | `/setup` |
| `SETUP_COMPLETE` | Initial config passed, loading not started | `/loading` |
| `UNRESOLVED_PENDING` | Setup done, unresolved exist, not marked done | `/setup/unresolved` |
| `UNRESOLVED_DONE` | Unresolved phase marked complete, NFO scan pending | `/loading` |
| `NFO_SCAN_PENDING` | Unresolved done, NFO scan incomplete | `/loading` |
| `COMPLETE` | All phases finished | `/login` |
## Middleware: SetupRedirectMiddleware
**File:** `src/server/middleware/setup_redirect.py`
The middleware intercepts all requests and redirects to `/setup` if:
- No master password is configured
- Configuration file is missing or invalid
The middleware intercepts all requests and enforces the state machine.
### Exempt Paths (always accessible)
@@ -68,13 +70,47 @@ The middleware intercepts all requests and redirects to `/setup` if:
### Middleware Logic
1. **Setup incomplete** → Redirect to `/setup`
2. **Setup complete, accessing `/setup`** → Redirect to `/login`
3. **Setup complete, accessing `/loading`** → Allow access (page handles its own redirect)
4. **Setup complete, accessing `/setup/unresolved`**:
- If `unresolved_completed` flag is set → Redirect to `/loading`
- Otherwise → Allow access
5. **API requests during setup** → Return 503 with `setup_url`
The middleware checks the current state and redirects accordingly:
```
1. NO_SETUP state:
→ Redirect ALL requests to /setup
→ Exception: /setup itself is accessible
2. SETUP_COMPLETE state:
→ Redirect /setup to /loading
→ Redirect any other page to /loading
3. UNRESOLVED_PENDING state (unresolved folders exist, not marked done):
→ Redirect /setup to /setup/unresolved
→ Redirect /loading to /setup/unresolved
→ Allow access to /setup/unresolved
→ Redirect any other page to /setup/unresolved
4. UNRESOLVED_DONE state (unresolved marked done, NFO scan pending):
→ Redirect /setup to /loading
→ Redirect /setup/unresolved to /loading
→ Redirect any other page to /loading
5. NFO_SCAN_PENDING state:
→ Redirect /setup to /loading
→ Redirect /setup/unresolved to /loading
→ Allow access to /loading (NFO phase runs)
→ Redirect any other page to /loading
6. COMPLETE state (loading finished):
→ Redirect /setup, /loading, /setup/unresolved to /login
→ Allow access to /login and main app
```
### Phase Tracking Flags
| Flag | Purpose |
|------|---------|
| `setup_complete` | Initial configuration was saved |
| `unresolved_completed` | User clicked "Done" on unresolved page |
| `loading_complete` | Series scan + initial loading finished |
| `nfo_scan_complete` | Final NFO scan finished |
## Pages
@@ -87,8 +123,11 @@ Handles initial configuration:
- Anime directory selection
- Database initialization
**Post-completion flow:**
- Redirects to `/loading` to begin initialization
**Allowed in states:** `NO_SETUP`
**Post-completion:**
- Sets `setup_complete` flag
- Redirects to `/loading`
### 2. Loading Page (`/loading`)
@@ -99,25 +138,28 @@ Shows initialization progress via WebSocket:
- Database population
- Logo/image loading
**Post-initialization flow:**
**Allowed in states:** `SETUP_COMPLETE`, `UNRESOLVED_DONE`, `NFO_SCAN_PENDING`
**Post-initialization (series scan complete):**
```javascript
async function checkUnresolvedAndProceed() {
// Fetch unresolved folders via API
const res = await fetch('/api/setup/unresolved', {
headers: { 'Authorization': `Bearer ${token}` }
});
const folders = await res.json();
if (folders.length > 0) {
// Has unresolved folders → go to resolution page
window.location.href = '/setup/unresolved';
} else {
// No unresolved folders → go to login
window.location.href = '/login';
}
}
```
**Post-NFO scan:**
- Sets `nfo_scan_complete` flag
- Redirects to `/login`
### 3. Unresolved Folders Page (`/setup/unresolved`)
**File:** `src/server/web/templates/unresolved.html`
@@ -127,24 +169,16 @@ Allows manual resolution of folders that couldn't be auto-matched:
- Provides search suggestions
- Input field for entering provider key
- Resolve/delete actions
- **Done button** at top to complete the phase without resolving all folders
- **Done button** to complete the phase without resolving all folders
**Post-resolution flow:**
```javascript
// After clicking "Done" button
async function handleDone() {
// Call API to mark phase as complete
await fetch('/api/setup/unresolved/done', { method: 'POST' });
// Redirect to loading for final NFO scan
window.location.href = '/loading';
}
```
**Allowed in states:** `UNRESOLVED_PENDING`
**Done button behavior:**
- Marks all remaining folders as handled
- Sets `unresolved_completed` flag in config
- Redirects to `/loading` to run final NFO scan
- After completion, `/setup/unresolved` becomes inaccessible (redirects to `/loading`)
- Sets `unresolved_completed` flag
- Redirects to `/loading` for final NFO scan
**After completion:**
- Any access redirects to `/loading`
### 4. Login Page (`/login`)
@@ -152,6 +186,8 @@ async function handleDone() {
Authentication page. After successful login → redirect to `/` (main app).
**Allowed in states:** `COMPLETE`
## API Endpoints
### Unresolved Folders API
@@ -177,7 +213,7 @@ Authentication page. After successful login → redirect to `/` (main app).
| File | Purpose |
|------|---------|
| `src/server/middleware/setup_redirect.py` | Redirect middleware |
| `src/server/middleware/setup_redirect.py` | Redirect middleware (state machine) |
| `src/server/controllers/page_controller.py` | Page route handlers |
| `src/server/web/templates/setup.html` | Setup template |
| `src/server/web/templates/loading.html` | Loading template |
@@ -185,22 +221,13 @@ Authentication page. After successful login → redirect to `/` (main app).
| `src/server/api/setup_endpoints.py` | Unresolved folders API |
| `src/server/database/service.py` | UnresolvedFolderService |
## Common Issues
## Navigation Summary
### Redirect Loop
**Symptom:** Browser keeps redirecting between pages.
**Causes:**
1. `loading.html` always redirected to `/setup/unresolved` without checking if any exist
2. `unresolved.html` redirected to `/` which middleware redirected back to `/login`
**Fix:** See the navigation logic updates in loading.html and unresolved.html.
### Can't Access Unresolved Page After Setup
**Symptom:** Middleware redirects to `/login` instead of allowing access to `/setup/unresolved`.
**Cause:** `/setup/unresolved` is in the exempt paths but the request may not be reaching it due to completion check timing.
**Fix:** The middleware allows access to `/loading` which handles the redirect to `/setup/unresolved` after initialization.
| Current State | Access `/setup` | Access `/loading` | Access `/setup/unresolved` |
|--------------|-----------------|-------------------|---------------------------|
| NO_SETUP | ✅ Allowed | ❌ → `/setup` | ❌ → `/setup` |
| SETUP_COMPLETE | ❌ → `/loading` | ✅ Allowed | ❌ → `/loading` |
| UNRESOLVED_PENDING | ❌ → `/setup/unresolved` | ❌ → `/setup/unresolved` | ✅ Allowed |
| UNRESOLVED_DONE | ❌ → `/loading` | ✅ Allowed (NFO phase) | ❌ → `/loading` |
| NFO_SCAN_PENDING | ❌ → `/loading` | ✅ Allowed (NFO phase) | ❌ → `/loading` |
| COMPLETE | ❌ → `/login` | ❌ → `/login` | ❌ → `/login` |