This commit is contained in:
ponzischeme89
2026-01-17 22:12:15 +13:00
parent 0f11b7ddbe
commit 7e6d55fef3
2 changed files with 0 additions and 693 deletions
-491
View File
@@ -1,491 +0,0 @@
# Component Reference
Complete guide to all Svelte components in SubPlotter.
---
## App.svelte
**Location**: `frontend/src/App.svelte`
Main application component with layout and routing.
### Features
- Tab-based navigation (Scanner / Settings)
- Health check on mount
- API configuration warning banner
- Gradient header with branding
- Responsive footer
### State
```javascript
currentView: 'scanner' | 'settings'
apiConfigured: boolean
selectedFiles: string[]
scanPanelKey: number // Forces refresh after processing
```
### Routing
Simple state-based routing - no router library needed:
```javascript
function navigateTo(view) {
currentView = view
}
```
### Styling
- Purple gradient header
- Dark mode support
- Responsive breakpoints at 768px
- Max width: 1200px
---
## SettingsPanel.svelte
**Location**: `frontend/src/components/SettingsPanel.svelte`
Configuration interface for API keys and behavior.
### Props
None (standalone component)
### Features
- API key input (password type)
- Directory path input
- Duration numeric input
- Load settings on mount
- Save with feedback messages
- Loading and error states
### State
```javascript
apiKey: string
defaultDirectory: string
duration: number
loading: boolean
saving: boolean
error: string | null
successMessage: string | null
```
### API Calls
- `getSettings()` on mount
- `updateSettings()` on save
### Usage
```svelte
<SettingsPanel />
```
---
## ScanPanel.svelte
**Location**: `frontend/src/components/ScanPanel.svelte`
Directory scanning interface with results display.
### Props (Exported)
```javascript
selectedFilePaths: string[] // Bind to get selected files
```
### Features
- Directory input field
- Start scan button
- Scanning progress indicator
- Last scan timestamp
- File count display
- Integrates MovieList component
- Loads previous scan results on mount
### State
```javascript
directory: string
files: FileInfo[]
scanning: boolean
error: string | null
lastScan: string | null
selectedFilePaths: string[]
```
### API Calls
- `getSettings()` on mount (for default directory)
- `getScanStatus()` on mount (load cached results)
- `startScan(directory)` on button click
### Usage
```svelte
<script>
let selected = []
</script>
<ScanPanel bind:selectedFilePaths={selected} />
```
### File Format
```javascript
{
path: string,
name: string,
has_plot: boolean,
status: string,
summary: string,
selected: boolean
}
```
---
## MovieList.svelte
**Location**: `frontend/src/components/MovieList.svelte`
Display and selection of scanned movie files.
### Props
```javascript
files: FileInfo[] // Array of file objects
onSelectionChange: (selectedPaths: string[]) => void
```
### Features
- Empty state message
- Select all checkbox
- Individual file checkboxes
- File name display
- Status badges
- Summary preview (truncated to 100 chars)
- Selected count in header
- Scrollable list (max-height: 500px)
### Methods
```javascript
toggleSelection(file) // Toggle individual file
toggleAll() // Toggle all files
formatSummary(summary) // Truncate long summaries
```
### Usage
```svelte
<MovieList
{files}
onSelectionChange={(paths) => console.log(paths)}
/>
```
### Styling
- Hover effects on rows
- Selected rows highlighted (blue tint)
- Dark mode support
---
## ActionToolbar.svelte
**Location**: `frontend/src/components/ActionToolbar.svelte`
Processing controls and results display.
### Props
```javascript
selectedFiles: string[] // Array of file paths
disabled: boolean // Disable when no API key
```
### Events
```javascript
'complete' // Dispatched after successful processing
// Detail: { results: ProcessResult[] }
```
### Features
- Large prominent action button
- Shows selected file count
- Confirmation modal before processing
- Results modal after processing
- Success/failure statistics
- Individual result breakdown
- Error handling and display
### State
```javascript
processing: boolean
showConfirmation: boolean
duration: number
results: ProcessResult[] | null
error: string | null
```
### Modals
**Confirmation Modal**:
- File count display
- Warning about file modification
- Backup information
- Cancel / Confirm buttons
**Results Modal**:
- Success/failure counts
- Per-file results list
- Color-coded success/failure
- Close button
### API Calls
- `getSettings()` before processing (get duration)
- `processFiles(files, duration)` on confirm
### Usage
```svelte
<ActionToolbar
{selectedFiles}
disabled={!apiConfigured}
on:complete={handleComplete}
/>
```
---
## StatusBadge.svelte
**Location**: `frontend/src/components/StatusBadge.svelte`
Reusable status indicator component.
### Props
```javascript
status: string // Default: 'Not Loaded'
```
### Supported Statuses
- `'Has Plot'` - Green (file already processed)
- `'Processed'` - Green (just processed)
- `'Not Loaded'` - Gray (not yet processed)
- `'Error'` - Red (processing failed)
- `'Skipped'` - Yellow (skipped, e.g., already has plot)
- `'Processing'` - Blue with pulse animation
### Styling
- Rounded badge design
- Color-coded by status
- Dark mode variants
- Pulse animation for processing state
### Usage
```svelte
<StatusBadge status="Has Plot" />
<StatusBadge status="Processing" />
<StatusBadge status="Error" />
```
---
## Component Hierarchy
```
App.svelte
├── SettingsPanel.svelte (when currentView === 'settings')
└── (when currentView === 'scanner')
├── ScanPanel.svelte
│ └── MovieList.svelte
│ └── StatusBadge.svelte (multiple instances)
└── ActionToolbar.svelte
```
---
## Common Patterns
### Loading States
```svelte
{#if loading}
<div class="loading">Loading...</div>
{:else}
<!-- Content -->
{/if}
```
### Error Display
```svelte
{#if error}
<div class="message message-error">{error}</div>
{/if}
```
### Success Messages
```svelte
{#if successMessage}
<div class="message message-success">{successMessage}</div>
{/if}
```
### Modal Pattern
```svelte
{#if showModal}
<div class="modal-overlay" on:click={closeModal}>
<div class="modal" on:click|stopPropagation>
<!-- Modal content -->
</div>
</div>
{/if}
```
### Reactive Statements
```svelte
$: selectedCount = files.filter(f => f.selected).length
$: hasSelection = selectedFiles.length > 0
```
---
## Styling Guidelines
### Color Palette
- Primary: `#3b82f6` (blue)
- Success: `#d1fae5` / `#065f46` (green)
- Error: `#fee2e2` / `#991b1b` (red)
- Warning: `#fef3c7` / `#92400e` (yellow)
- Processing: `#dbeafe` / `#1e40af` (blue)
### Dark Mode
All components support dark mode via:
```css
@media (prefers-color-scheme: dark) {
/* Dark styles */
}
```
### Layout
- Container max-width: 1200px
- Standard padding: 2rem (desktop), 1rem (mobile)
- Standard gap: 0.5rem to 1rem
- Border radius: 6px (small), 8px (large)
### Transitions
- Duration: 150ms to 200ms
- Timing: `cubic-bezier(0.4, 0, 0.2, 1)`
- Properties: background, border, color
---
## Component Communication
### Parent → Child (Props)
```svelte
<MovieList {files} disabled={true} />
```
### Child → Parent (Events)
```svelte
<!-- Child -->
<script>
import { createEventDispatcher } from 'svelte'
const dispatch = createEventDispatcher()
function handleClick() {
dispatch('complete', { data: 'value' })
}
</script>
<!-- Parent -->
<ActionToolbar on:complete={handleComplete} />
```
### Two-Way Binding
```svelte
<ScanPanel bind:selectedFilePaths={selected} />
```
### Callbacks
```svelte
<MovieList onSelectionChange={(paths) => { ... }} />
```
---
## Best Practices
1. **Keep components small** - Each component does one thing well
2. **Explicit state** - No hidden state or magic
3. **Clear props** - Document all props and their types
4. **Error handling** - Always handle loading and error states
5. **Accessibility** - Use semantic HTML and labels
6. **Responsive** - Test at mobile and desktop sizes
7. **Dark mode** - Support system preference
8. **No external state** - Use props and events, not stores
---
## Adding New Components
Template for new component:
```svelte
<script>
/**
* ComponentName - Brief description
* Props:
* propName: type - description
*/
import { onMount } from 'svelte'
export let propName = 'default'
let loading = false
let error = null
onMount(async () => {
// Initialization
})
async function handleAction() {
loading = true
error = null
try {
// API call or logic
} catch (err) {
error = err.message
} finally {
loading = false
}
}
</script>
<div class="component-name">
{#if loading}
<div class="loading">Loading...</div>
{:else if error}
<div class="error">{error}</div>
{:else}
<!-- Content -->
{/if}
</div>
<style>
.component-name {
/* Styles */
}
/* Dark mode */
@media (prefers-color-scheme: dark) {
/* Dark styles */
}
</style>
```
---
## Testing Components
While no test framework is included, you can test:
1. **Manually** - Run dev server and interact
2. **Browser DevTools** - Check props and state
3. **Console logs** - Add temporary logging
4. **Network tab** - Verify API calls
5. **Error scenarios** - Test with invalid data
For automated testing, consider:
- Vitest + Svelte Testing Library
- Playwright for E2E tests
-202
View File
@@ -1,202 +0,0 @@
# SubPlotter Database
SubPlotter uses SQLite with SQLAlchemy for persistent data storage.
## Database File
The database is stored in `subplotter.db` in the application root directory.
## Tables
### Settings
Stores application configuration (API key, default directory, duration, etc.)
**Columns:**
- `id` (Integer, Primary Key)
- `key` (String, Unique, Indexed) - Setting name
- `value` (Text) - Setting value (JSON encoded)
- `updated_at` (DateTime) - Last update timestamp
### ProcessingRun
Tracks each batch processing session
**Columns:**
- `id` (Integer, Primary Key)
- `started_at` (DateTime, Indexed) - When processing started
- `completed_at` (DateTime) - When processing completed
- `total_files` (Integer) - Total files in this run
- `successful_files` (Integer) - Successfully processed files
- `failed_files` (Integer) - Failed files
- `duration_seconds` (Float) - Total processing time
- `status` (String) - Run status: 'in_progress', 'completed', 'failed'
### FileResult
Stores individual file processing results
**Columns:**
- `id` (Integer, Primary Key)
- `run_id` (Integer, Foreign Key to ProcessingRun)
- `file_path` (String, Indexed) - Full path to file
- `file_name` (String) - Just the filename
- `success` (Boolean) - Whether processing succeeded
- `status` (String) - Status message
- `summary` (Text) - Plot summary added
- `error_message` (Text) - Error details if failed
- `processed_at` (DateTime) - When file was processed
- `duration` (Integer) - Subtitle duration in seconds
### ScanHistory
Tracks directory scan history
**Columns:**
- `id` (Integer, Primary Key)
- `directory` (String, Indexed) - Directory path scanned
- `scanned_at` (DateTime, Indexed) - When scan occurred
- `files_found` (Integer) - Number of SRT files found
- `files_with_plot` (Integer) - Files that already have plot summaries
- `scan_duration_ms` (Integer) - How long the scan took in milliseconds
## API Endpoints
### History Endpoints
**GET /api/history/runs?limit=50**
Get list of processing runs
```json
{
"success": true,
"runs": [
{
"id": 1,
"started_at": "2024-01-01T12:00:00",
"completed_at": "2024-01-01T12:05:00",
"total_files": 10,
"successful_files": 8,
"failed_files": 2,
"duration_seconds": 300.5,
"status": "completed"
}
]
}
```
**GET /api/history/runs/{run_id}**
Get detailed information about a specific run including all file results
```json
{
"success": true,
"run": {
"id": 1,
"started_at": "2024-01-01T12:00:00",
"completed_at": "2024-01-01T12:05:00",
"total_files": 10,
"successful_files": 8,
"failed_files": 2,
"duration_seconds": 300.5,
"status": "completed",
"file_results": [
{
"id": 1,
"file_path": "/path/to/movie.srt",
"file_name": "movie.srt",
"success": true,
"status": "Plot added successfully",
"summary": "A hero saves the day...",
"error_message": null,
"processed_at": "2024-01-01T12:00:30",
"duration": 40
}
]
}
}
```
**GET /api/history/scans?limit=50**
Get scan history
```json
{
"success": true,
"scans": [
{
"id": 1,
"directory": "C:\\Movies",
"scanned_at": "2024-01-01T12:00:00",
"files_found": 25,
"files_with_plot": 10,
"scan_duration_ms": 150
}
]
}
```
**GET /api/statistics**
Get overall statistics
```json
{
"success": true,
"statistics": {
"total_runs": 50,
"completed_runs": 48,
"total_files_processed": 500,
"successful_files": 450,
"failed_files": 50
}
}
```
## Migration
On first startup, SubPlotter automatically migrates settings from the legacy `settings.json` file to the database. The JSON file is kept for backward compatibility but all new settings are stored in the database.
## Database Manager Usage
```python
from core.database import DatabaseManager
# Initialize
db = DatabaseManager("subplotter.db")
# Settings operations
db.set_setting("api_key", "your-key")
api_key = db.get_setting("api_key", "")
all_settings = db.get_all_settings()
# Create a processing run
run_id = db.create_run(total_files=10)
# Add file results
db.add_file_result(
run_id=run_id,
file_path="/path/to/movie.srt",
success=True,
status="Plot added",
summary="A hero...",
duration=40
)
# Complete the run
db.complete_run(run_id, successful_files=8, failed_files=2)
# Query history
runs = db.get_run_history(limit=50)
run_details = db.get_run_details(run_id)
# Add scan history
db.add_scan_history(
directory="/path/to/movies",
files_found=25,
files_with_plot=10,
scan_duration_ms=150
)
# Get statistics
stats = db.get_statistics()
```
## Backup
The SQLite database file can be backed up simply by copying `subplotter.db` to a safe location.
## Reset Database
To reset the database, simply delete `subplotter.db` and restart the application. A new database will be created automatically.