- 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.
21 KiB
Frontend Integration Guide
Complete guide for integrating the existing frontend assets with the FastAPI backend.
Table of Contents
- Overview
- Frontend Asset Structure
- API Integration
- WebSocket Integration
- Theme System
- Authentication Flow
- Error Handling
- Localization
- Accessibility Features
- 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 interfacequeue.html- Download queue management pagelogin.html- Authentication login pagesetup.html- Initial setup pageerror.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 navigationadvanced_search.js- Advanced search filteringbulk_operations.js- Batch operations on seriescolor_contrast_compliance.js- WCAG color contrast validationdrag_drop.js- Drag-and-drop queue reorderingkeyboard_shortcuts.js- Global keyboard shortcutslocalization.js- Multi-language supportmobile_responsive.js- Mobile-specific enhancementsmulti_screen_support.js- Multi-monitor supportscreen_reader_support.js- Screen reader compatibilitytouch_gestures.js- Touch gesture supportundo_redo.js- Undo/redo functionalityuser_preferences.js- User preference management
CSS Files (src/server/web/static/css/)
styles.css- Main stylesheet with Fluent UI designux_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:
-
Response Format Consistency
- All responses should include
successboolean - Error responses should include
error,message, anddetails - Success responses should include
datafield
- All responses should include
-
Authentication Flow
/api/auth/statusendpoint for checking authentication- Proper 401 responses for unauthenticated requests
- Token refresh mechanism (if needed)
-
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:
- Accept connections at
/ws/connect - Handle room management (join/leave messages)
- Broadcast events to appropriate rooms
- 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/statusendpoint exists and returns proper format - Verify
/api/auth/loginreturns token in expected format - Verify
/api/auth/logoutendpoint exists - Verify
/api/v1/animereturns list withsuccessanddatafields - Verify
/api/v1/anime/searchendpoint exists - Verify
/api/v1/download/queueendpoints 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.jsAPI calls to match backend endpoints - Update
queue.jsAPI calls to match backend endpoints - Verify
websocket_client.jsmessage 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