Aniworld/docs/frontend_integration.md
Lukas 6a6ae7e059 fix: resolve all failing tests (701 tests now passing)
- Add missing src/server/api/__init__.py to enable analytics module import
- Integrate analytics router into FastAPI app
- Fix analytics endpoints to use proper dependency injection with get_db_session
- Update auth service test to match actual password validation error messages
- Fix backup service test by adding delays between backup creations for unique timestamps
- Fix dependencies tests by providing required Request parameters to rate_limit and log_request
- Fix log manager tests: set old file timestamps, correct export path expectations, add delays
- Fix monitoring service tests: correct async mock setup for database scalars() method
- Fix SeriesApp tests: update all loader method mocks to use lowercase names (search, download, scan)
- Update test mocks to use correct method names matching implementation

All 701 tests now passing with 0 failures.
2025-10-23 21:00:34 +02:00

21 KiB

Frontend Integration Guide

Complete guide for integrating the existing frontend assets with the FastAPI backend.

Table of Contents

  1. Overview
  2. Frontend Asset Structure
  3. API Integration
  4. WebSocket Integration
  5. Theme System
  6. Authentication Flow
  7. Error Handling
  8. Localization
  9. Accessibility Features
  10. Testing Integration

Overview

The Aniworld frontend uses vanilla JavaScript with modern ES6+ features, integrated with a FastAPI backend through REST API endpoints and WebSocket connections. The design follows Fluent UI principles with comprehensive accessibility support.

Key Technologies

  • Frontend: Vanilla JavaScript (ES6+), HTML5, CSS3
  • Backend: FastAPI, Python 3.10+
  • Communication: REST API, WebSocket
  • Styling: Custom CSS with Fluent UI design principles
  • Icons: Font Awesome 6.0.0

Frontend Asset Structure

Templates (src/server/web/templates/)

  • index.html - Main application interface
  • queue.html - Download queue management page
  • login.html - Authentication login page
  • setup.html - Initial setup page
  • error.html - Error display page

JavaScript Files (src/server/web/static/js/)

Core Application Files

  • app.js (2086 lines)

    • Main application logic
    • Series management
    • Download operations
    • Search functionality
    • Theme management
    • Authentication handling
  • queue.js (758 lines)

    • Download queue management
    • Queue reordering
    • Download progress tracking
    • Queue status updates
  • websocket_client.js (234 lines)

    • Native WebSocket wrapper
    • Socket.IO-like interface
    • Reconnection logic
    • Message routing

Feature Enhancement Files

  • accessibility_features.js - ARIA labels, keyboard navigation
  • advanced_search.js - Advanced search filtering
  • bulk_operations.js - Batch operations on series
  • color_contrast_compliance.js - WCAG color contrast validation
  • drag_drop.js - Drag-and-drop queue reordering
  • keyboard_shortcuts.js - Global keyboard shortcuts
  • localization.js - Multi-language support
  • mobile_responsive.js - Mobile-specific enhancements
  • multi_screen_support.js - Multi-monitor support
  • screen_reader_support.js - Screen reader compatibility
  • touch_gestures.js - Touch gesture support
  • undo_redo.js - Undo/redo functionality
  • user_preferences.js - User preference management

CSS Files (src/server/web/static/css/)

  • styles.css - Main stylesheet with Fluent UI design
  • ux_features.css - UX enhancements and accessibility styles

API Integration

Current API Endpoints Used

Authentication Endpoints

// Check authentication status
GET /api/auth/status
Headers: { Authorization: Bearer <token> }

// Login
POST /api/auth/login
Body: { password: string }
Response: { token: string, token_type: string }

// Logout
POST /api/auth/logout

Anime Endpoints

// List all anime
GET /api/v1/anime
Response: { success: bool, data: Array<Anime> }

// Search anime
GET /api/v1/anime/search?query=<search_term>
Response: { success: bool, data: Array<Anime> }

// Get anime details
GET /api/v1/anime/{anime_id}
Response: { success: bool, data: Anime }

Download Queue Endpoints

// Get queue status
GET /api/v1/download/queue
Response: { queue: Array<DownloadItem>, is_running: bool }

// Add to queue
POST /api/v1/download/queue
Body: { anime_id: string, episodes: Array<number> }

// Start queue
POST /api/v1/download/queue/start

// Stop queue
POST /api/v1/download/queue/stop

// Pause queue
POST /api/v1/download/queue/pause

// Resume queue
POST /api/v1/download/queue/resume

// Reorder queue
PUT /api/v1/download/queue/reorder
Body: { queue_order: Array<string> }

// Remove from queue
DELETE /api/v1/download/queue/{item_id}

Configuration Endpoints

// Get configuration
GET / api / v1 / config;
Response: {
    config: ConfigObject;
}

// Update configuration
PUT / api / v1 / config;
Body: ConfigObject;

API Call Pattern

All API calls follow this pattern in the JavaScript files:

async function apiCall(endpoint, options = {}) {
    try {
        const token = localStorage.getItem("access_token");
        const headers = {
            "Content-Type": "application/json",
            ...(token && { Authorization: `Bearer ${token}` }),
            ...options.headers,
        };

        const response = await fetch(endpoint, {
            ...options,
            headers,
        });

        if (!response.ok) {
            if (response.status === 401) {
                // Redirect to login
                window.location.href = "/login";
                return;
            }
            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }

        return await response.json();
    } catch (error) {
        console.error("API call failed:", error);
        throw error;
    }
}

Required API Updates

The following API endpoints need to be verified/updated to match frontend expectations:

  1. Response Format Consistency

    • All responses should include success boolean
    • Error responses should include error, message, and details
    • Success responses should include data field
  2. Authentication Flow

    • /api/auth/status endpoint for checking authentication
    • Proper 401 responses for unauthenticated requests
    • Token refresh mechanism (if needed)
  3. Queue Operations

    • Ensure queue reordering endpoint exists
    • Validate pause/resume functionality
    • Check queue status polling endpoint

WebSocket Integration

WebSocket Connection

The frontend uses a custom WebSocket client (websocket_client.js) that provides a Socket.IO-like interface over native WebSocket.

Connection Endpoint

const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
const host = window.location.host;
const wsUrl = `${protocol}//${host}/ws/connect`;

WebSocket Events

Events Sent by Frontend

// Join a room (for targeted updates)
socket.emit("join", { room: "downloads" });
socket.emit("join", { room: "download_progress" });

// Leave a room
socket.emit("leave", { room: "downloads" });

// Custom events (as needed)
socket.emit("custom_event", { data: "value" });

Events Received by Frontend

Connection Events
socket.on("connect", () => {
    // Connection established
});

socket.on("disconnect", (data) => {
    // Connection lost - data: { code, reason }
});

socket.on("connected", (data) => {
    // Server confirmation - data: { message, timestamp }
});
Queue Events
// Queue status updates
socket.on("queue_status", (data) => {
    // data: { queue_status: { queue: [], is_running: bool } }
});

socket.on("queue_updated", (data) => {
    // Legacy event - same as queue_status
});

// Download lifecycle
socket.on("queue_started", () => {
    // Queue processing started
});

socket.on("download_started", (data) => {
    // Individual download started
    // data: { serie_name, episode }
});

socket.on("download_progress", (data) => {
    // Download progress update
    // data: { serie_name, episode, progress, speed, eta }
});

socket.on("download_complete", (data) => {
    // Download completed
    // data: { serie_name, episode }
});

socket.on("download_completed", (data) => {
    // Legacy event - same as download_complete
});

socket.on("download_failed", (data) => {
    // Download failed
    // data: { serie_name, episode, error }
});

socket.on("download_error", (data) => {
    // Legacy event - same as download_failed
});

socket.on("download_queue_completed", () => {
    // All downloads in queue completed
});

socket.on("download_stop_requested", () => {
    // Queue stop requested
});
Scan Events
socket.on("scan_started", () => {
    // Library scan started
});

socket.on("scan_progress", (data) => {
    // Scan progress update
    // data: { current, total, percentage }
});

socket.on("scan_completed", (data) => {
    // Scan completed
    // data: { total_series, new_series, updated_series }
});

socket.on("scan_failed", (data) => {
    // Scan failed
    // data: { error }
});

Backend WebSocket Requirements

The backend WebSocket implementation (src/server/api/websocket.py) should:

  1. Accept connections at /ws/connect
  2. Handle room management (join/leave messages)
  3. Broadcast events to appropriate rooms
  4. Support message format:
    {
      "event": "event_name",
      "data": { ... }
    }
    

Theme System

Theme Implementation

The application supports light and dark modes with persistence.

Theme Toggle

// Toggle theme
document.documentElement.setAttribute("data-theme", "light|dark");

// Store preference
localStorage.setItem("theme", "light|dark");

// Load on startup
const savedTheme = localStorage.getItem("theme") || "light";
document.documentElement.setAttribute("data-theme", savedTheme);

CSS Variables

Themes are defined using CSS custom properties:

:root[data-theme="light"] {
    --bg-primary: #ffffff;
    --bg-secondary: #f5f5f5;
    --text-primary: #000000;
    --text-secondary: #666666;
    --accent-color: #0078d4;
    /* ... more variables */
}

:root[data-theme="dark"] {
    --bg-primary: #1e1e1e;
    --bg-secondary: #2d2d2d;
    --text-primary: #ffffff;
    --text-secondary: #cccccc;
    --accent-color: #60a5fa;
    /* ... more variables */
}

Fluent UI Design Principles

The frontend follows Microsoft Fluent UI design guidelines:

  • Rounded corners: 4px border radius
  • Shadows: Subtle elevation shadows
  • Transitions: Smooth 200-300ms transitions
  • Typography: System font stack
  • Spacing: 8px grid system
  • Colors: Accessible color palette

Authentication Flow

Authentication States

// State management
const authStates = {
    UNAUTHENTICATED: "unauthenticated",
    AUTHENTICATED: "authenticated",
    SETUP_REQUIRED: "setup_required",
};

Authentication Check

On page load, the application checks authentication status:

async checkAuthentication() {
    // Skip check on public pages
    const currentPath = window.location.pathname;
    if (currentPath === '/login' || currentPath === '/setup') {
        return;
    }

    try {
        const token = localStorage.getItem('access_token');

        if (!token) {
            window.location.href = '/login';
            return;
        }

        const response = await fetch('/api/auth/status', {
            headers: { 'Authorization': `Bearer ${token}` }
        });

        if (!response.ok) {
            if (response.status === 401) {
                localStorage.removeItem('access_token');
                window.location.href = '/login';
            }
        }
    } catch (error) {
        console.error('Auth check failed:', error);
        window.location.href = '/login';
    }
}

Login Flow

async login(password) {
    try {
        const response = await fetch('/api/auth/login', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ password })
        });

        if (response.ok) {
            const data = await response.json();
            localStorage.setItem('access_token', data.token);
            window.location.href = '/';
        } else {
            // Show error message
            this.showError('Invalid password');
        }
    } catch (error) {
        console.error('Login failed:', error);
        this.showError('Login failed');
    }
}

Logout Flow

async logout() {
    try {
        await fetch('/api/auth/logout', { method: 'POST' });
    } finally {
        localStorage.removeItem('access_token');
        window.location.href = '/login';
    }
}

Error Handling

Frontend Error Display

The application uses toast notifications for errors:

showToast(message, type = 'info') {
    const toast = document.createElement('div');
    toast.className = `toast toast-${type}`;
    toast.textContent = message;

    document.body.appendChild(toast);

    setTimeout(() => {
        toast.classList.add('show');
    }, 100);

    setTimeout(() => {
        toast.classList.remove('show');
        setTimeout(() => toast.remove(), 300);
    }, 3000);
}

API Error Handling

async function handleApiError(error, response) {
    if (response) {
        const data = await response.json().catch(() => ({}));

        // Show user-friendly error message
        const message = data.message || `Error: ${response.status}`;
        this.showToast(message, "error");

        // Log details for debugging
        console.error("API Error:", {
            status: response.status,
            error: data.error,
            message: data.message,
            details: data.details,
        });

        // Handle specific status codes
        if (response.status === 401) {
            // Redirect to login
            localStorage.removeItem("access_token");
            window.location.href = "/login";
        }
    } else {
        // Network error
        this.showToast("Network error. Please check your connection.", "error");
        console.error("Network error:", error);
    }
}

Expected Error Response Format

The backend should return errors in this format:

{
    "success": false,
    "error": "ERROR_CODE",
    "message": "Human-readable error message",
    "details": {
        "field": "error_field",
        "reason": "specific_reason"
    },
    "request_id": "uuid"
}

Localization

The application includes a localization system (localization.js) for multi-language support.

Localization Usage

// Initialize localization
const localization = new Localization();

// Set language
localization.setLanguage("en"); // or 'de', 'es', etc.

// Get translation
const text = localization.get("key", "default_value");

// Update all page text
localization.updatePageText();

Text Keys

Elements with data-text attributes are automatically translated:

<span data-text="download-queue">Download Queue</span>
<button data-text="start-download">Start Download</button>

Adding New Translations

Translations are defined in localization.js:

const translations = {
    en: {
        "download-queue": "Download Queue",
        "start-download": "Start Download",
        // ... more keys
    },
    de: {
        "download-queue": "Download-Warteschlange",
        "start-download": "Download starten",
        // ... more keys
    },
};

Accessibility Features

The application includes comprehensive accessibility support.

Keyboard Navigation

All interactive elements are keyboard accessible:

  • Tab/Shift+Tab: Navigate between elements
  • Enter/Space: Activate buttons
  • Escape: Close modals/dialogs
  • Arrow Keys: Navigate lists

Custom keyboard shortcuts are defined in keyboard_shortcuts.js.

Screen Reader Support

ARIA labels and live regions are implemented:

<button aria-label="Start download" aria-describedby="download-help">
    <i class="fas fa-download" aria-hidden="true"></i>
</button>

<div role="status" aria-live="polite" id="status-message"></div>

Color Contrast

The application ensures WCAG AA compliance for color contrast:

  • Normal text: 4.5:1 minimum
  • Large text: 3:1 minimum
  • Interactive elements: 3:1 minimum

color_contrast_compliance.js validates contrast ratios.

Touch Support

Touch gestures are supported for mobile devices:

  • Swipe: Navigate between sections
  • Long press: Show context menu
  • Pinch: Zoom (where applicable)

Testing Integration

Frontend Testing Checklist

  • API Integration

    • All API endpoints return expected response format
    • Error responses include proper error codes
    • Authentication flow works correctly
    • Token refresh mechanism works (if implemented)
  • WebSocket Integration

    • WebSocket connects successfully
    • All expected events are received
    • Reconnection works after disconnect
    • Room-based broadcasting works correctly
  • UI/UX

    • Theme toggle persists across sessions
    • All pages are responsive (mobile, tablet, desktop)
    • Animations are smooth and performant
    • Toast notifications display correctly
  • Authentication

    • Login redirects to home page
    • Logout clears session and redirects
    • Protected pages redirect unauthenticated users
    • Token expiration handled gracefully
  • Accessibility

    • Keyboard navigation works on all pages
    • Screen reader announces important changes
    • Color contrast meets WCAG AA standards
    • Focus indicators are visible
  • Localization

    • All text is translatable
    • Language selection persists
    • Translations are complete for all supported languages
  • Error Handling

    • Network errors show appropriate messages
    • API errors display user-friendly messages
    • Fatal errors redirect to error page
    • Errors are logged for debugging

Integration Test Examples

API Integration Test

describe("API Integration", () => {
    test("should authenticate and fetch anime list", async () => {
        // Login
        const loginResponse = await fetch("/api/auth/login", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ password: "test_password" }),
        });

        const { token } = await loginResponse.json();
        expect(token).toBeDefined();

        // Fetch anime
        const animeResponse = await fetch("/api/v1/anime", {
            headers: { Authorization: `Bearer ${token}` },
        });

        const data = await animeResponse.json();
        expect(data.success).toBe(true);
        expect(Array.isArray(data.data)).toBe(true);
    });
});

WebSocket Integration Test

describe("WebSocket Integration", () => {
    test("should connect and receive events", (done) => {
        const socket = new WebSocketClient();

        socket.on("connect", () => {
            expect(socket.isConnected).toBe(true);

            // Join room
            socket.emit("join", { room: "downloads" });

            // Wait for queue_status event
            socket.on("queue_status", (data) => {
                expect(data).toHaveProperty("queue_status");
                socket.disconnect();
                done();
            });
        });

        socket.connect();
    });
});

Frontend Integration Checklist

Phase 1: API Endpoint Verification

  • Verify /api/auth/status endpoint exists and returns proper format
  • Verify /api/auth/login returns token in expected format
  • Verify /api/auth/logout endpoint exists
  • Verify /api/v1/anime returns list with success and data fields
  • Verify /api/v1/anime/search endpoint exists
  • Verify /api/v1/download/queue endpoints match frontend expectations
  • Verify error responses include success, error, message, details

Phase 2: WebSocket Integration

  • Verify WebSocket endpoint is /ws/connect
  • Verify room join/leave functionality
  • Verify all queue events are emitted properly
  • Verify scan events are emitted properly
  • Test reconnection logic
  • Test message broadcasting to rooms

Phase 3: Frontend Code Updates

  • Update app.js API calls to match backend endpoints
  • Update queue.js API calls to match backend endpoints
  • Verify websocket_client.js message format matches backend
  • Update error handling to parse new error format
  • Test authentication flow end-to-end
  • Verify theme persistence works

Phase 4: UI/UX Polish

  • Verify responsive design on mobile devices
  • Test keyboard navigation on all pages
  • Verify screen reader compatibility
  • Test color contrast in both themes
  • Verify all animations are smooth
  • Test touch gestures on mobile

Phase 5: Testing

  • Write integration tests for API endpoints
  • Write integration tests for WebSocket events
  • Write UI tests for critical user flows
  • Test error scenarios (network errors, auth failures)
  • Test performance under load
  • Test accessibility with screen reader

Conclusion

This guide provides a comprehensive overview of the frontend integration requirements. All JavaScript files should be reviewed and updated to match the documented API endpoints and WebSocket events. The backend should ensure it provides the expected response formats and event structures.

For questions or issues, refer to:

  • API Reference: docs/api_reference.md
  • User Guide: docs/user_guide.md
  • Deployment Guide: docs/deployment.md