728 lines
37 KiB
HTML
728 lines
37 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>NFOGuard - Database Management</title>
|
|
<link rel="stylesheet" href="/static/css/styles.css?v=2.10.0-skipped-tracking">
|
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
|
</head>
|
|
<body>
|
|
<div class="app-container">
|
|
<!-- Header -->
|
|
<header class="app-header">
|
|
<div class="header-content">
|
|
<h1><i class="fas fa-shield-alt"></i> NFOGuard <span style="font-size: 0.5em; color: #888;">v2.10.0-skipped-tracking</span></h1>
|
|
<p>Database Management & Reporting</p>
|
|
</div>
|
|
<div class="auth-status" id="auth-status" style="display: none;">
|
|
<span class="auth-user">
|
|
<i class="fas fa-user"></i> <span id="auth-username">Loading...</span>
|
|
</span>
|
|
<button class="auth-logout" id="logout-btn" onclick="logout()">
|
|
<i class="fas fa-sign-out-alt"></i> Logout
|
|
</button>
|
|
</div>
|
|
<nav class="nav-tabs">
|
|
<button class="nav-tab active" data-tab="dashboard">
|
|
<i class="fas fa-tachometer-alt"></i> Dashboard
|
|
</button>
|
|
<button class="nav-tab" data-tab="movies">
|
|
<i class="fas fa-film"></i> Movies
|
|
</button>
|
|
<button class="nav-tab" data-tab="tv">
|
|
<i class="fas fa-tv"></i> TV Series
|
|
</button>
|
|
<button class="nav-tab" data-tab="reports">
|
|
<i class="fas fa-chart-bar"></i> Reports
|
|
</button>
|
|
<button class="nav-tab" data-tab="scheduled-scans">
|
|
<i class="fas fa-clock"></i> Scheduled Scans
|
|
</button>
|
|
<button class="nav-tab" data-tab="tools">
|
|
<i class="fas fa-tools"></i> Tools
|
|
</button>
|
|
</nav>
|
|
</header>
|
|
|
|
<!-- Main Content -->
|
|
<main class="main-content">
|
|
<!-- Dashboard Tab -->
|
|
<div class="tab-content active" id="dashboard">
|
|
<div class="dashboard-grid">
|
|
<div class="stat-card">
|
|
<div class="stat-icon movies">
|
|
<i class="fas fa-film"></i>
|
|
</div>
|
|
<div class="stat-info">
|
|
<h3 id="movies-total">-</h3>
|
|
<p>Total Movies</p>
|
|
<small id="movies-with-dates">- with dates</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="stat-card">
|
|
<div class="stat-icon tv">
|
|
<i class="fas fa-tv"></i>
|
|
</div>
|
|
<div class="stat-info">
|
|
<h3 id="series-total">-</h3>
|
|
<p>TV Series</p>
|
|
<small id="episodes-total">- episodes</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="stat-card">
|
|
<div class="stat-icon missing">
|
|
<i class="fas fa-exclamation-triangle"></i>
|
|
</div>
|
|
<div class="stat-info">
|
|
<h3 id="missing-dates-total">-</h3>
|
|
<p>Missing Dates</p>
|
|
<small id="no-valid-source-total">- no valid source</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="stat-card">
|
|
<div class="stat-icon activity">
|
|
<i class="fas fa-history"></i>
|
|
</div>
|
|
<div class="stat-info">
|
|
<h3 id="recent-activity">-</h3>
|
|
<p>Recent Activity</p>
|
|
<small>Last 7 days</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="stat-card" style="cursor: pointer;" onclick="showSkippedItems()">
|
|
<div class="stat-icon" style="background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%);">
|
|
<i class="fas fa-ban"></i>
|
|
</div>
|
|
<div class="stat-info">
|
|
<h3 id="skipped-total">-</h3>
|
|
<p>Skipped Items</p>
|
|
<small id="skipped-breakdown">- movies, - episodes</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="dashboard-charts">
|
|
<div class="chart-card">
|
|
<h3><i class="fas fa-chart-pie"></i> Movie Sources</h3>
|
|
<div id="movie-sources-chart" class="chart-container"></div>
|
|
</div>
|
|
<div class="chart-card">
|
|
<h3><i class="fas fa-chart-pie"></i> Episode Sources</h3>
|
|
<div id="episode-sources-chart" class="chart-container"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Movies Tab -->
|
|
<div class="tab-content" id="movies">
|
|
<div class="content-header">
|
|
<h2><i class="fas fa-film"></i> Movies Database</h2>
|
|
<div class="content-controls">
|
|
<div class="search-controls">
|
|
<div class="search-box">
|
|
<i class="fas fa-search"></i>
|
|
<input type="text" id="movies-search" placeholder="Search title/path...">
|
|
</div>
|
|
<div class="search-box">
|
|
<i class="fas fa-hashtag"></i>
|
|
<input type="text" id="movies-imdb-search" placeholder="Search IMDb ID...">
|
|
</div>
|
|
</div>
|
|
<div class="filter-controls">
|
|
<select id="movies-filter-date">
|
|
<option value="">All Movies</option>
|
|
<option value="true">With Dates</option>
|
|
<option value="false">Missing Dates</option>
|
|
<option value="skipped">Skipped</option>
|
|
</select>
|
|
<select id="movies-filter-source">
|
|
<option value="">All Sources</option>
|
|
</select>
|
|
<button class="btn btn-primary" onclick="refreshMovies()">
|
|
<i class="fas fa-sync"></i> Refresh
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="table-container">
|
|
<table class="data-table sortable-table" id="movies-table">
|
|
<thead>
|
|
<tr>
|
|
<th class="sortable" onclick="sortTable('movies-tbody', 0, 'text')" style="cursor: pointer;">
|
|
Title <i class="fas fa-sort"></i>
|
|
</th>
|
|
<th class="sortable" onclick="sortTable('movies-tbody', 1, 'text')" style="cursor: pointer;">
|
|
IMDb ID <i class="fas fa-sort"></i>
|
|
</th>
|
|
<th class="sortable" onclick="sortTable('movies-tbody', 2, 'date')" style="cursor: pointer;">
|
|
Movie Released <i class="fas fa-sort"></i>
|
|
</th>
|
|
<th class="sortable" onclick="sortTable('movies-tbody', 3, 'date')" style="cursor: pointer;">
|
|
Date Added to Library <i class="fas fa-sort"></i>
|
|
</th>
|
|
<th class="sortable" onclick="sortTable('movies-tbody', 4, 'text')" style="cursor: pointer;">
|
|
Source <i class="fas fa-sort"></i>
|
|
</th>
|
|
<th class="sortable" onclick="sortTable('movies-tbody', 5, 'text')" style="cursor: pointer;">
|
|
Date Type <i class="fas fa-sort"></i>
|
|
</th>
|
|
<th class="sortable" onclick="sortTable('movies-tbody', 6, 'text')" style="cursor: pointer;">
|
|
Video File <i class="fas fa-sort"></i>
|
|
</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="movies-tbody">
|
|
<tr>
|
|
<td colspan="8" class="loading">Loading movies...</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="pagination" id="movies-pagination"></div>
|
|
</div>
|
|
|
|
<!-- TV Series Tab -->
|
|
<div class="tab-content" id="tv">
|
|
<div class="content-header">
|
|
<h2><i class="fas fa-tv"></i> TV Series Database</h2>
|
|
<div class="content-controls">
|
|
<div class="search-controls">
|
|
<div class="search-box">
|
|
<i class="fas fa-search"></i>
|
|
<input type="text" id="series-search" placeholder="Search title/path...">
|
|
</div>
|
|
<div class="search-box">
|
|
<i class="fas fa-hashtag"></i>
|
|
<input type="text" id="series-imdb-search" placeholder="Search IMDb ID...">
|
|
</div>
|
|
</div>
|
|
<div class="filter-controls">
|
|
<select id="series-filter-date">
|
|
<option value="">All Series</option>
|
|
<option value="complete">Fully Dated</option>
|
|
<option value="incomplete">Missing Dates</option>
|
|
<option value="none">No Dates</option>
|
|
</select>
|
|
<select id="series-filter-source">
|
|
<option value="">All Sources</option>
|
|
</select>
|
|
<button class="btn btn-primary" onclick="refreshSeries()">
|
|
<i class="fas fa-sync"></i> Refresh
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="table-container">
|
|
<table class="data-table sortable-table" id="series-table">
|
|
<thead>
|
|
<tr>
|
|
<th class="sortable" onclick="sortTable('series-tbody', 0, 'text')" style="cursor: pointer;">
|
|
Series Title <i class="fas fa-sort"></i>
|
|
</th>
|
|
<th class="sortable" onclick="sortTable('series-tbody', 1, 'text')" style="cursor: pointer;">
|
|
IMDb ID <i class="fas fa-sort"></i>
|
|
</th>
|
|
<th class="sortable" onclick="sortTable('series-tbody', 2, 'number')" style="cursor: pointer;">
|
|
Episodes <i class="fas fa-sort"></i>
|
|
</th>
|
|
<th class="sortable" onclick="sortTable('series-tbody', 3, 'number')" style="cursor: pointer;">
|
|
With Dates <i class="fas fa-sort"></i>
|
|
</th>
|
|
<th class="sortable" onclick="sortTable('series-tbody', 4, 'number')" style="cursor: pointer;">
|
|
With Video <i class="fas fa-sort"></i>
|
|
</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="series-tbody">
|
|
<tr>
|
|
<td colspan="6" class="loading">Loading series...</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="pagination" id="series-pagination"></div>
|
|
</div>
|
|
|
|
<!-- Reports Tab -->
|
|
<div class="tab-content" id="reports">
|
|
<div class="content-header">
|
|
<h2><i class="fas fa-chart-bar"></i> Missing Dates Report</h2>
|
|
<div class="content-controls">
|
|
<button class="btn btn-primary" onclick="refreshReport()">
|
|
<i class="fas fa-sync"></i> Refresh Report
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="report-summary" id="report-summary">
|
|
<div class="summary-card">
|
|
<h3>Movies</h3>
|
|
<p><span id="report-movies-with">-</span> with dates</p>
|
|
<p><span id="report-movies-missing">-</span> missing dates</p>
|
|
</div>
|
|
<div class="summary-card">
|
|
<h3>Episodes</h3>
|
|
<p><span id="report-episodes-with">-</span> with dates</p>
|
|
<p><span id="report-episodes-missing">-</span> missing dates</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="report-content">
|
|
<div class="report-section">
|
|
<h3><i class="fas fa-film"></i> Movies Missing Dates</h3>
|
|
<div class="table-container">
|
|
<table class="data-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Title</th>
|
|
<th>IMDb ID</th>
|
|
<th>Released</th>
|
|
<th>Source</th>
|
|
<th>Smart Fix</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="report-movies-tbody">
|
|
<tr>
|
|
<td colspan="5" class="loading">Loading report...</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="report-section">
|
|
<h3><i class="fas fa-tv"></i> Episodes Missing Dates</h3>
|
|
<div class="table-container">
|
|
<table class="data-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Series</th>
|
|
<th>Episode</th>
|
|
<th>IMDb ID</th>
|
|
<th>Aired</th>
|
|
<th>Source</th>
|
|
<th>Smart Fix</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="report-episodes-tbody">
|
|
<tr>
|
|
<td colspan="6" class="loading">Loading report...</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Scheduled Scans Tab -->
|
|
<div class="tab-content" id="scheduled-scans">
|
|
<div class="content-header">
|
|
<h2><i class="fas fa-clock"></i> Scheduled Scans</h2>
|
|
<button class="btn btn-primary" id="add-schedule-btn">
|
|
<i class="fas fa-plus"></i> Add Schedule
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Active Schedules Section -->
|
|
<div class="section-card">
|
|
<h3><i class="fas fa-list"></i> Active Schedules</h3>
|
|
<div class="table-container">
|
|
<table class="data-table" id="schedules-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Type</th>
|
|
<th>Mode</th>
|
|
<th>Schedule</th>
|
|
<th>Last Run</th>
|
|
<th>Next Run</th>
|
|
<th>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="schedules-table-body">
|
|
<!-- Schedules will be loaded here -->
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Execution History Section -->
|
|
<div class="section-card">
|
|
<h3><i class="fas fa-history"></i> Recent Executions</h3>
|
|
<div class="table-container">
|
|
<table class="data-table" id="executions-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Schedule</th>
|
|
<th>Started</th>
|
|
<th>Duration</th>
|
|
<th>Status</th>
|
|
<th>Items Processed</th>
|
|
<th>Items Skipped</th>
|
|
<th>Items Failed</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="executions-table-body">
|
|
<!-- Executions will be loaded here -->
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Tools Tab -->
|
|
<div class="tab-content" id="tools">
|
|
<div class="content-header">
|
|
<h2><i class="fas fa-tools"></i> Database Tools</h2>
|
|
</div>
|
|
|
|
<div class="tools-grid">
|
|
<div class="tool-card">
|
|
<h3><i class="fas fa-exchange-alt"></i> Bulk Source Update</h3>
|
|
<p>Change source for multiple items at once</p>
|
|
<form id="bulk-update-form">
|
|
<div class="form-group">
|
|
<label>Media Type:</label>
|
|
<select id="bulk-media-type" required>
|
|
<option value="">Select type...</option>
|
|
<option value="movies">Movies</option>
|
|
<option value="episodes">Episodes</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>From Source:</label>
|
|
<input type="text" id="bulk-old-source" placeholder="e.g., no_valid_date_source" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>To Source:</label>
|
|
<select id="bulk-new-source" required>
|
|
<option value="">Select new source...</option>
|
|
<option value="airdate">Air Date</option>
|
|
<option value="digital_release">Digital Release</option>
|
|
<option value="manual">Manual</option>
|
|
<option value="radarr:db.history.import">Radarr Import</option>
|
|
<option value="sonarr:history.import">Sonarr Import</option>
|
|
</select>
|
|
</div>
|
|
<button type="submit" class="btn btn-warning">
|
|
<i class="fas fa-exchange-alt"></i> Update Sources
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="tool-card">
|
|
<h3><i class="fas fa-search"></i> Manual Scan</h3>
|
|
<p>Scan specific folders or perform full library scans</p>
|
|
<form id="manual-scan-form">
|
|
<div class="form-group">
|
|
<label>Scan Type:</label>
|
|
<select id="scan-type" required>
|
|
<option value="both">TV Shows & Movies</option>
|
|
<option value="tv">TV Shows Only</option>
|
|
<option value="movies">Movies Only</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Scan Mode:</label>
|
|
<select id="scan-mode" required>
|
|
<option value="smart">Smart (Recommended)</option>
|
|
<option value="full">Full Scan</option>
|
|
<option value="incomplete">Incomplete Only</option>
|
|
</select>
|
|
</div>
|
|
<div class="form-group">
|
|
<label>Specific Path (Optional):</label>
|
|
<input type="text" id="scan-path" placeholder="e.g., /mnt/unionfs/Media/TV/Series Name" title="Leave empty for full library scan">
|
|
<small>Leave empty to scan entire library</small>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="fas fa-play"></i> Start Scan
|
|
</button>
|
|
</form>
|
|
<div id="scan-status" class="scan-status" style="display: none;">
|
|
<div class="scan-progress">
|
|
<div class="progress-bar">
|
|
<div class="progress-fill" id="scan-progress-bar"></div>
|
|
</div>
|
|
<div class="scan-info">
|
|
<span id="scan-current-operation">Initializing...</span>
|
|
<span id="scan-progress-text">0%</span>
|
|
</div>
|
|
</div>
|
|
<button class="btn btn-secondary btn-sm" onclick="stopScanPolling()">
|
|
<i class="fas fa-times"></i> Hide Status
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tool-card">
|
|
<h3><i class="fas fa-database"></i> Database Statistics</h3>
|
|
<p>View detailed database information</p>
|
|
<div class="stats-display" id="detailed-stats">
|
|
<p>Click refresh to load detailed statistics</p>
|
|
</div>
|
|
<button class="btn btn-secondary" onclick="loadDetailedStats()">
|
|
<i class="fas fa-sync"></i> Refresh Stats
|
|
</button>
|
|
</div>
|
|
|
|
<div class="tool-card">
|
|
<h3><i class="fas fa-upload"></i> Populate Database</h3>
|
|
<p>Bulk import data from Radarr/Sonarr into NFOGuard database</p>
|
|
<form id="populate-form">
|
|
<div class="form-group">
|
|
<label>Media Type:</label>
|
|
<select id="populate-media-type" required>
|
|
<option value="both">Movies & TV Shows</option>
|
|
<option value="movies">Movies Only</option>
|
|
<option value="tv">TV Shows Only</option>
|
|
</select>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary">
|
|
<i class="fas fa-play"></i> Start Population
|
|
</button>
|
|
</form>
|
|
<div id="populate-status" class="scan-status" style="display: none;">
|
|
<div class="scan-progress">
|
|
<div class="progress-bar">
|
|
<div class="progress-fill" id="populate-progress-bar"></div>
|
|
</div>
|
|
<div class="scan-info">
|
|
<span id="populate-current-operation">Running...</span>
|
|
<span id="populate-progress-text">In Progress</span>
|
|
</div>
|
|
</div>
|
|
<div id="populate-results" class="stats-display" style="margin-top: 10px;"></div>
|
|
<button class="btn btn-secondary btn-sm" onclick="stopPopulatePolling()">
|
|
<i class="fas fa-times"></i> Hide Status
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
<!-- Smart Fix Modal -->
|
|
<div class="modal" id="smart-fix-modal">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3 id="smart-fix-title">Choose Date Source</h3>
|
|
<button class="modal-close" onclick="closeSmartFixModal()">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div id="smart-fix-content">
|
|
<p>Loading available options...</p>
|
|
</div>
|
|
<div class="form-actions">
|
|
<button type="button" class="btn btn-secondary" onclick="closeSmartFixModal()">Cancel</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Edit Modal -->
|
|
<div class="modal" id="edit-modal">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3 id="modal-title">Edit Entry</h3>
|
|
<button class="modal-close" onclick="closeModal()">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="edit-form">
|
|
<input type="hidden" id="edit-imdb-id">
|
|
<input type="hidden" id="edit-season">
|
|
<input type="hidden" id="edit-episode">
|
|
<input type="hidden" id="edit-media-type">
|
|
|
|
<div class="form-group">
|
|
<label for="edit-dateadded">Date Added:</label>
|
|
<input type="datetime-local" id="edit-dateadded">
|
|
<small>Leave empty to clear date</small>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="edit-source">Source:</label>
|
|
<select id="edit-source" required>
|
|
<option value="manual">Manual</option>
|
|
<option value="airdate">Air Date</option>
|
|
<option value="digital_release">Digital Release</option>
|
|
<option value="radarr:db.history.import">Radarr Import</option>
|
|
<option value="sonarr:history.import">Sonarr Import</option>
|
|
<option value="no_valid_date_source">No Valid Source</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-actions">
|
|
<button type="button" class="btn btn-secondary" onclick="closeModal()">Cancel</button>
|
|
<button type="submit" class="btn btn-primary">Save Changes</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Schedule Modal -->
|
|
<div class="modal" id="schedule-modal">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3 id="schedule-modal-title">Add New Schedule</h3>
|
|
<button class="modal-close" onclick="closeScheduleModal()">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<form id="schedule-form">
|
|
<input type="hidden" id="schedule-id">
|
|
|
|
<div class="form-group">
|
|
<label for="schedule-name">Schedule Name:</label>
|
|
<input type="text" id="schedule-name" required placeholder="e.g., Daily TV Incomplete Scan">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="schedule-description">Description:</label>
|
|
<textarea id="schedule-description" placeholder="Optional description of what this schedule does"></textarea>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<div class="form-group">
|
|
<label for="schedule-media-type">Media Type:</label>
|
|
<select id="schedule-media-type" required>
|
|
<option value="both">Both TV Shows & Movies</option>
|
|
<option value="tv">TV Shows Only</option>
|
|
<option value="movies">Movies Only</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="schedule-scan-mode">Scan Mode:</label>
|
|
<select id="schedule-scan-mode" required>
|
|
<option value="smart">Smart (Recommended)</option>
|
|
<option value="incomplete">Incomplete Only</option>
|
|
<option value="full">Full Scan</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="schedule-cron">Schedule (Cron Expression):</label>
|
|
<div class="cron-input-container">
|
|
<input type="text" id="schedule-cron" required placeholder="0 2 * * *" pattern="^(\*|[0-5]?\d|\*\/[0-9]+)(\s+(\*|[0-5]?\d|\*\/[0-9]+)){4}$">
|
|
<button type="button" class="btn btn-secondary btn-sm" id="cron-builder-btn">
|
|
<i class="fas fa-magic"></i> Builder
|
|
</button>
|
|
</div>
|
|
<small class="help-text">
|
|
Examples: "0 2 * * *" (daily at 2 AM), "0 2 * * 0" (weekly on Sunday at 2 AM)
|
|
</small>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="schedule-paths">Specific Paths (Optional):</label>
|
|
<textarea id="schedule-paths" placeholder="Leave empty to scan entire library, or specify paths separated by commas"></textarea>
|
|
<small class="help-text">
|
|
Example: /media/TV/Series Name, /media/Movies/Movie Name
|
|
</small>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" id="schedule-enabled" checked>
|
|
<span class="checkmark"></span>
|
|
Enable this schedule
|
|
</label>
|
|
</div>
|
|
|
|
<div class="form-actions">
|
|
<button type="button" class="btn btn-secondary" onclick="closeScheduleModal()">Cancel</button>
|
|
<button type="submit" class="btn btn-primary">
|
|
<span id="schedule-submit-text">Create Schedule</span>
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Cron Builder Modal -->
|
|
<div class="modal" id="cron-builder-modal">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3>Cron Expression Builder</h3>
|
|
<button class="modal-close" onclick="closeCronBuilder()">×</button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="cron-builder">
|
|
<div class="cron-presets">
|
|
<h4>Quick Presets:</h4>
|
|
<div class="preset-buttons">
|
|
<button type="button" class="btn btn-outline" onclick="setCronPreset('0 2 * * *')">Daily at 2 AM</button>
|
|
<button type="button" class="btn btn-outline" onclick="setCronPreset('0 2 * * 0')">Weekly (Sunday 2 AM)</button>
|
|
<button type="button" class="btn btn-outline" onclick="setCronPreset('0 2 1 * *')">Monthly (1st at 2 AM)</button>
|
|
<button type="button" class="btn btn-outline" onclick="setCronPreset('0 */6 * * *')">Every 6 Hours</button>
|
|
<button type="button" class="btn btn-outline" onclick="setCronPreset('0 */12 * * *')">Every 12 Hours</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="cron-fields">
|
|
<h4>Custom Schedule:</h4>
|
|
<div class="field-group">
|
|
<label>Minute (0-59):</label>
|
|
<input type="text" id="cron-minute" value="0" placeholder="0">
|
|
</div>
|
|
<div class="field-group">
|
|
<label>Hour (0-23):</label>
|
|
<input type="text" id="cron-hour" value="2" placeholder="2">
|
|
</div>
|
|
<div class="field-group">
|
|
<label>Day of Month (1-31):</label>
|
|
<input type="text" id="cron-day" value="*" placeholder="*">
|
|
</div>
|
|
<div class="field-group">
|
|
<label>Month (1-12):</label>
|
|
<input type="text" id="cron-month" value="*" placeholder="*">
|
|
</div>
|
|
<div class="field-group">
|
|
<label>Day of Week (0-6):</label>
|
|
<input type="text" id="cron-dow" value="*" placeholder="*">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="cron-preview">
|
|
<h4>Preview:</h4>
|
|
<div class="cron-expression">
|
|
<code id="cron-preview-text">0 2 * * *</code>
|
|
</div>
|
|
<div class="cron-description" id="cron-description">
|
|
Runs daily at 2:00 AM
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-actions">
|
|
<button type="button" class="btn btn-secondary" onclick="closeCronBuilder()">Cancel</button>
|
|
<button type="button" class="btn btn-primary" onclick="applyCronExpression()">Use This Schedule</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Toast Notifications -->
|
|
<div class="toast-container" id="toast-container"></div>
|
|
|
|
<script src="/static/js/app.js?v=2.10.0-skipped-tracking">
|
|
</body>
|
|
</html> |