updates
This commit is contained in:
-491
@@ -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
@@ -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.
|
|
||||||
Reference in New Issue
Block a user