mirror of
https://github.com/ceratic/MediaCollectorLibary.git
synced 2026-05-13 23:56:46 +02:00
369 lines
22 KiB
Twig
369 lines
22 KiB
Twig
{% extends 'admin/layout.twig' %}
|
|
|
|
{% block content %}
|
|
<!-- Navigation -->
|
|
<nav class="navbar navbar-expand-lg navbar-light bg-light mb-4 rounded">
|
|
<div class="container-fluid">
|
|
<div class="navbar-nav me-auto">
|
|
<a class="nav-link" href="{{ path_for('admin.index') }}">
|
|
<i class="fas fa-tachometer-alt me-2"></i>Dashboard
|
|
</a>
|
|
{% if is_admin() %}
|
|
<a class="nav-link" href="{{ path_for('admin.sources') }}">
|
|
<i class="fas fa-database me-2"></i>Sources
|
|
</a>
|
|
{% endif %}
|
|
<a class="nav-link active" href="{{ path_for('admin.settings') }}">
|
|
<i class="fas fa-cog me-2"></i>Settings
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<div class="mb-4">
|
|
<h1 class="display-4 fw-bold text-dark">Admin Settings</h1>
|
|
<p class="lead text-muted">Configure your media sources and application settings</p>
|
|
</div>
|
|
|
|
{% if success %}
|
|
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
|
{{ success }}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- General Settings -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h2 class="h5 mb-0">General Settings</h2>
|
|
<p class="text-muted mb-0">Configure general application settings</p>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
<form method="post">
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="setting_sync_interval" class="form-label">Default Sync Interval (minutes)</label>
|
|
<input type="number" class="form-control" id="setting_sync_interval" name="setting_sync_interval"
|
|
value="{{ settings.sync_interval ?? 60 }}" min="5" max="1440">
|
|
<div class="form-text">How often to check for new content (5-1440 minutes)</div>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<label for="setting_max_sync_items" class="form-label">Max Items per Sync</label>
|
|
<input type="number" class="form-control" id="setting_max_sync_items" name="setting_max_sync_items"
|
|
value="{{ settings.max_sync_items ?? 1000 }}" min="100" max="10000">
|
|
<div class="form-text">Maximum number of items to process in a single sync operation</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<div class="form-check">
|
|
<input type="checkbox" class="form-check-input" id="setting_enable_notifications"
|
|
name="setting_enable_notifications" {{ settings.enable_notifications ? 'checked' : '' }}>
|
|
<label class="form-check-label" for="setting_enable_notifications">
|
|
Enable sync notifications
|
|
</label>
|
|
</div>
|
|
<div class="form-text">Send notifications when sync operations complete</div>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<div class="form-check">
|
|
<input type="checkbox" class="form-check-input" id="setting_auto_cleanup"
|
|
name="setting_auto_cleanup" {{ settings.auto_cleanup ? 'checked' : '' }}>
|
|
<label class="form-check-label" for="setting_auto_cleanup">
|
|
Auto cleanup old logs
|
|
</label>
|
|
</div>
|
|
<div class="form-text">Automatically remove sync logs older than 30 days</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-end">
|
|
<button type="submit" class="btn btn-primary">Save General Settings</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Source Settings -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h2 class="h5 mb-0">Source Configuration</h2>
|
|
<p class="text-muted mb-0">Configure your media sources and their sync settings</p>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
<form method="post">
|
|
{% for source in sources %}
|
|
<div class="border rounded p-3 mb-4">
|
|
<h4 class="mb-3">{{ source.display_name }}</h4>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="sources_{{ source.id }}_api_url" class="form-label">API URL</label>
|
|
<input type="url" class="form-control" id="sources_{{ source.id }}_api_url"
|
|
name="sources[{{ source.id }}][api_url]" value="{{ source.api_url }}">
|
|
<div class="form-text">Base URL for the {{ source.name }} API</div>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<label for="sources_{{ source.id }}_api_key" class="form-label">API Key</label>
|
|
<input type="password" class="form-control" id="sources_{{ source.id }}_api_key"
|
|
name="sources[{{ source.id }}][api_key]" value="{{ source.api_key }}">
|
|
<div class="form-text">API key for authenticating with {{ source.name }}</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Source-specific configuration -->
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="sources_{{ source.id }}_config_username" class="form-label">Username</label>
|
|
<input type="text" class="form-control" id="sources_{{ source.id }}_config_username"
|
|
name="sources[{{ source.id }}][config][username]"
|
|
value="{{ source.config.username ?? '' }}">
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<label for="sources_{{ source.id }}_config_sync_type" class="form-label">Default Sync Type</label>
|
|
<select class="form-select" id="sources_{{ source.id }}_config_sync_type"
|
|
name="sources[{{ source.id }}][config][sync_type]">
|
|
<option value="full" {{ (source.config.sync_type ?? 'full') == 'full' ? 'selected' : '' }}>Full Sync</option>
|
|
<option value="incremental" {{ (source.config.sync_type ?? 'full') == 'incremental' ? 'selected' : '' }}>Incremental Sync</option>
|
|
{% if source.name == 'jellyfin' %}
|
|
<option value="all" {{ (source.config.sync_type ?? 'full') == 'all' ? 'selected' : '' }}>All Content</option>
|
|
<option value="movies" {{ (source.config.sync_type ?? 'full') == 'movies' ? 'selected' : '' }}>Movies Only</option>
|
|
<option value="tvshows" {{ (source.config.sync_type ?? 'full') == 'tvshows' ? 'selected' : '' }}>TV Shows Only</option>
|
|
{% endif %}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Source-specific settings based on type -->
|
|
{% if source.name == 'jellyfin' %}
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="sources_{{ source.id }}_config_libraries" class="form-label">Library IDs</label>
|
|
<input type="text" class="form-control" id="sources_{{ source.id }}_config_libraries"
|
|
name="sources[{{ source.id }}][config][libraries]"
|
|
value="{{ source.config.libraries ?? '' }}"
|
|
placeholder="e.g. 12345678-1234-1234-1234-123456789012">
|
|
<div class="form-text">Comma-separated list of Jellyfin library IDs to sync</div>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<label for="sources_{{ source.id }}_config_user_id" class="form-label">User ID</label>
|
|
<input type="text" class="form-control" id="sources_{{ source.id }}_config_user_id"
|
|
name="sources[{{ source.id }}][config][user_id]"
|
|
value="{{ source.config.user_id ?? '' }}"
|
|
placeholder="e.g. 12345678-1234-1234-1234-123456789012">
|
|
<div class="form-text">Jellyfin user ID for accessing content</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if source.name == 'xbvr' %}
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="sources_{{ source.id }}_config_quality_filter" class="form-label">Quality Filter</label>
|
|
<select class="form-select" id="sources_{{ source.id }}_config_quality_filter"
|
|
name="sources[{{ source.id }}][config][quality_filter]">
|
|
<option value="">All Qualities</option>
|
|
<option value="4k" {{ (source.config.quality_filter ?? '') == '4k' ? 'selected' : '' }}>4K Only</option>
|
|
<option value="1080p" {{ (source.config.quality_filter ?? '') == '1080p' ? 'selected' : '' }}>1080p Only</option>
|
|
<option value="720p" {{ (source.config.quality_filter ?? '') == '720p' ? 'selected' : '' }}>720p Only</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<label for="sources_{{ source.id }}_config_rating_filter" class="form-label">Minimum Rating</label>
|
|
<select class="form-select" id="sources_{{ source.id }}_config_rating_filter"
|
|
name="sources[{{ source.id }}][config][rating_filter]">
|
|
<option value="">No Filter</option>
|
|
<option value="3" {{ (source.config.rating_filter ?? '') == '3' ? 'selected' : '' }}>3+ Stars</option>
|
|
<option value="4" {{ (source.config.rating_filter ?? '') == '4' ? 'selected' : '' }}>4+ Stars</option>
|
|
<option value="5" {{ (source.config.rating_filter ?? '') == '5' ? 'selected' : '' }}>5 Stars Only</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if source.name == 'stash' %}
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="sources_{{ source.id }}_config_include_tags" class="form-label">Include Tags</label>
|
|
<input type="text" class="form-control" id="sources_{{ source.id }}_config_include_tags"
|
|
name="sources[{{ source.id }}][config][include_tags]"
|
|
value="{{ source.config.include_tags ?? '' }}"
|
|
placeholder="e.g. VR,4K,Favorite">
|
|
<div class="form-text">Comma-separated list of tags to include (empty for all)</div>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<label for="sources_{{ source.id }}_config_exclude_tags" class="form-label">Exclude Tags</label>
|
|
<input type="text" class="form-control" id="sources_{{ source.id }}_config_exclude_tags"
|
|
name="sources[{{ source.id }}][config][exclude_tags]"
|
|
value="{{ source.config.exclude_tags ?? '' }}"
|
|
placeholder="e.g. Low Quality,Test">
|
|
<div class="form-text">Comma-separated list of tags to exclude</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="row">
|
|
<div class="col-12 mb-3">
|
|
<div class="form-check">
|
|
<input type="checkbox" class="form-check-input" id="sources_{{ source.id }}_is_active"
|
|
name="sources[{{ source.id }}][is_active]" {{ source.is_active ? 'checked' : '' }}>
|
|
<label class="form-check-label" for="sources_{{ source.id }}_is_active">
|
|
Enable this source for syncing
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
|
|
<div class="d-flex justify-content-end">
|
|
<button type="submit" class="btn btn-primary">Save Source Settings</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Media Type Visibility Settings -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h2 class="h5 mb-0">Media Type Visibility</h2>
|
|
<p class="text-muted mb-0">Control which media types are visible to non-authenticated users</p>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
<form method="post">
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="media_visibility_games" class="form-label">Games</label>
|
|
<select class="form-select" id="media_visibility_games" name="media_visibility[games]">
|
|
<option value="public" {{ (settings.media_visibility.games ?? 'authenticated') == 'public' ? 'selected' : '' }}>Visible to everyone</option>
|
|
<option value="authenticated" {{ (settings.media_visibility.games ?? 'authenticated') == 'authenticated' ? 'selected' : '' }}>Authenticated users only</option>
|
|
<option value="hidden" {{ (settings.media_visibility.games ?? 'authenticated') == 'hidden' ? 'selected' : '' }}>Hidden from all users</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<label for="media_visibility_movies" class="form-label">Movies</label>
|
|
<select class="form-select" id="media_visibility_movies" name="media_visibility[movies]">
|
|
<option value="public" {{ (settings.media_visibility.movies ?? 'authenticated') == 'public' ? 'selected' : '' }}>Visible to everyone</option>
|
|
<option value="authenticated" {{ (settings.media_visibility.movies ?? 'authenticated') == 'authenticated' ? 'selected' : '' }}>Authenticated users only</option>
|
|
<option value="hidden" {{ (settings.media_visibility.movies ?? 'authenticated') == 'hidden' ? 'selected' : '' }}>Hidden from all users</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="media_visibility_tvshows" class="form-label">TV Shows</label>
|
|
<select class="form-select" id="media_visibility_tvshows" name="media_visibility[tvshows]">
|
|
<option value="public" {{ (settings.media_visibility.tvshows ?? 'authenticated') == 'public' ? 'selected' : '' }}>Visible to everyone</option>
|
|
<option value="authenticated" {{ (settings.media_visibility.tvshows ?? 'authenticated') == 'authenticated' ? 'selected' : '' }}>Authenticated users only</option>
|
|
<option value="hidden" {{ (settings.media_visibility.tvshows ?? 'authenticated') == 'hidden' ? 'selected' : '' }}>Hidden from all users</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<label for="media_visibility_music" class="form-label">Music</label>
|
|
<select class="form-select" id="media_visibility_music" name="media_visibility[music]">
|
|
<option value="public" {{ (settings.media_visibility.music ?? 'authenticated') == 'public' ? 'selected' : '' }}>Visible to everyone</option>
|
|
<option value="authenticated" {{ (settings.media_visibility.music ?? 'authenticated') == 'authenticated' ? 'selected' : '' }}>Authenticated users only</option>
|
|
<option value="hidden" {{ (settings.media_visibility.music ?? 'authenticated') == 'hidden' ? 'selected' : '' }}>Hidden from all users</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="media_visibility_adult" class="form-label">Adult Videos</label>
|
|
<select class="form-select" id="media_visibility_adult" name="media_visibility[adult]">
|
|
<option value="public" {{ (settings.media_visibility.adult ?? 'authenticated') == 'public' ? 'selected' : '' }}>Visible to everyone</option>
|
|
<option value="authenticated" {{ (settings.media_visibility.adult ?? 'authenticated') == 'authenticated' ? 'selected' : '' }}>Authenticated users only</option>
|
|
<option value="hidden" {{ (settings.media_visibility.adult ?? 'authenticated') == 'hidden' ? 'selected' : '' }}>Hidden from all users</option>
|
|
</select>
|
|
<div class="form-text">Adult content should typically require authentication</div>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<label for="media_visibility_actors" class="form-label">Actors/Performers</label>
|
|
<select class="form-select" id="media_visibility_actors" name="media_visibility[actors]">
|
|
<option value="public" {{ (settings.media_visibility.actors ?? 'authenticated') == 'public' ? 'selected' : '' }}>Visible to everyone</option>
|
|
<option value="authenticated" {{ (settings.media_visibility.actors ?? 'authenticated') == 'authenticated' ? 'selected' : '' }}>Authenticated users only</option>
|
|
<option value="hidden" {{ (settings.media_visibility.actors ?? 'authenticated') == 'hidden' ? 'selected' : '' }}>Hidden from all users</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-end">
|
|
<button type="submit" class="btn btn-primary">Save Media Visibility Settings</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Security Settings -->
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h2 class="h5 mb-0">Security Settings</h2>
|
|
<p class="text-muted mb-0">Configure security and access settings</p>
|
|
</div>
|
|
|
|
<div class="card-body">
|
|
<form method="post">
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<label for="setting_session_timeout" class="form-label">Session Timeout (minutes)</label>
|
|
<input type="number" class="form-control" id="setting_session_timeout" name="setting_session_timeout"
|
|
value="{{ settings.session_timeout ?? 30 }}" min="5" max="480">
|
|
<div class="form-text">User sessions will expire after this many minutes of inactivity</div>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<label for="setting_max_login_attempts" class="form-label">Max Login Attempts</label>
|
|
<input type="number" class="form-control" id="setting_max_login_attempts" name="setting_max_login_attempts"
|
|
value="{{ settings.max_login_attempts ?? 5 }}" min="3" max="10">
|
|
<div class="form-text">Number of failed login attempts before account lockout</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-md-6 mb-3">
|
|
<div class="form-check">
|
|
<input type="checkbox" class="form-check-input" id="setting_require_https"
|
|
name="setting_require_https" {{ settings.require_https ? 'checked' : '' }}>
|
|
<label class="form-check-label" for="setting_require_https">
|
|
Require HTTPS
|
|
</label>
|
|
</div>
|
|
<div class="form-text">Force all connections to use HTTPS</div>
|
|
</div>
|
|
|
|
<div class="col-md-6 mb-3">
|
|
<div class="form-check">
|
|
<input type="checkbox" class="form-check-input" id="setting_enable_audit_log"
|
|
name="setting_enable_audit_log" {{ settings.enable_audit_log ? 'checked' : '' }}>
|
|
<label class="form-check-label" for="setting_enable_audit_log">
|
|
Enable audit logging
|
|
</label>
|
|
</div>
|
|
<div class="form-text">Log all admin actions for security auditing</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex justify-content-end">
|
|
<button type="submit" class="btn btn-primary">Save Security Settings</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|