Files
sofarr/public/index.html
T
gronod b9c8c0be87
Build and Push Docker Image / build (push) Successful in 1m28s
CI / Security audit (push) Has been cancelled
CI / Tests & coverage (push) Has been cancelled
CI / Swagger Validation & Coverage (push) Has been cancelled
style(ui): unify tab headers layout, typography, and icons (closes #72)
2026-05-28 18:12:53 +01:00

333 lines
23 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>sofarr - Your Downloads Dashboard</title>
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32.png">
<link rel="apple-touch-icon" sizes="192x192" href="favicon-192.png">
<meta name="theme-color" content="#1a1a2e">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- Splash Screen -->
<div id="splash-screen" class="splash-screen">
<img src="images/sofarr-flashscreen.png" alt="sofarr" class="splash-logo">
</div>
<div class="app">
<!-- Login Form -->
<div id="login-container" class="login-container hidden">
<div class="login-box">
<img src="images/sofarr-flashscreen.png" alt="sofarr" class="login-logo">
<p class="login-subtitle">Login with your Emby credentials</p>
<form id="login-form">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" id="password" name="password" required>
</div>
<div class="form-group form-group--checkbox">
<label class="checkbox-label">
<input type="checkbox" id="remember-me" name="rememberMe">
<span>Keep me logged in</span>
</label>
</div>
<button type="submit" class="login-btn">Login</button>
</form>
<div id="login-error" class="error-message hidden"></div>
</div>
</div>
<!-- Dashboard -->
<div id="dashboard-container" class="dashboard-container hidden">
<header class="app-header">
<h1><a href="#" class="title-link" id="title-home-link"><img src="favicon-192.png" alt="" class="title-logo">sofarr</a></h1>
<div class="header-controls">
<div class="theme-switcher">
<button class="theme-btn active" data-theme="light">Light</button>
<button class="theme-btn" data-theme="dark">Dark</button>
<button class="theme-btn" data-theme="mono">Mono</button>
</div>
<div id="admin-controls" class="admin-controls hidden">
<label class="toggle-label">
<input type="checkbox" id="show-all-toggle">
<span>Show all users</span>
</label>
<button id="status-btn" class="status-btn">Status</button>
</div>
<div class="user-info">
<span class="user-label">Current User:</span>
<span class="user-name" id="currentUser">-</span>
<button id="logout-btn" class="logout-btn">Logout</button>
</div>
</div>
</header>
<div id="status-panel" class="status-panel hidden">
<!-- Status content gets rendered here -->
<div id="status-content"><p class="status-loading">Loading status...</p></div>
</div>
<!-- Webhooks Configuration Panel (sibling to status-panel) -->
<div class="webhooks-section hidden" id="webhooks-section">
<div class="webhooks-header" id="webhooks-header">
<h2>⚡ Webhooks Configuration</h2>
<span class="webhooks-toggle" id="webhooks-toggle"></span>
</div>
<div class="webhooks-content hidden" id="webhooks-content">
<div id="webhook-loading" class="webhook-loading hidden">Loading webhook status...</div>
<!-- Sonarr Webhook -->
<div class="webhook-instance">
<h3>Sonarr</h3>
<div class="webhook-status">
<span class="status-indicator" id="sonarr-status">○ Disabled</span>
<button id="enable-sonarr-webhook" class="enable-webhook-btn hidden">Enable Sofarr Webhooks</button>
<button id="test-sonarr-webhook" class="test-webhook-btn hidden">Test</button>
</div>
<div class="webhook-triggers hidden" id="sonarr-triggers">
<div class="trigger-item"><span class="trigger-label">On Grab</span><span class="trigger-value" id="sonarr-onGrab"></span></div>
<div class="trigger-item"><span class="trigger-label">On Download</span><span class="trigger-value" id="sonarr-onDownload"></span></div>
<div class="trigger-item"><span class="trigger-label">On Import</span><span class="trigger-value" id="sonarr-onImport"></span></div>
<div class="trigger-item"><span class="trigger-label">On Upgrade</span><span class="trigger-value" id="sonarr-onUpgrade"></span></div>
</div>
<div class="webhook-stats hidden" id="sonarr-stats">
<div class="webhook-stats-title">Statistics</div>
<div class="webhook-stats-grid">
<div class="webhook-stat"><span class="webhook-stat-label">Events Received</span><span class="webhook-stat-value" id="sonarr-events">0</span></div>
<div class="webhook-stat"><span class="webhook-stat-label">Polls Skipped</span><span class="webhook-stat-value" id="sonarr-polls">0</span></div>
<div class="webhook-stat"><span class="webhook-stat-label">Last Event</span><span class="webhook-stat-value" id="sonarr-last">Never</span></div>
</div>
</div>
</div>
<!-- Radarr Webhook -->
<div class="webhook-instance">
<h3>Radarr</h3>
<div class="webhook-status">
<span class="status-indicator" id="radarr-status">○ Disabled</span>
<button id="enable-radarr-webhook" class="enable-webhook-btn hidden">Enable Sofarr Webhooks</button>
<button id="test-radarr-webhook" class="test-webhook-btn hidden">Test</button>
</div>
<div class="webhook-triggers hidden" id="radarr-triggers">
<div class="trigger-item"><span class="trigger-label">On Grab</span><span class="trigger-value" id="radarr-onGrab"></span></div>
<div class="trigger-item"><span class="trigger-label">On Download</span><span class="trigger-value" id="radarr-onDownload"></span></div>
<div class="trigger-item"><span class="trigger-label">On Import</span><span class="trigger-value" id="radarr-onImport"></span></div>
<div class="trigger-item"><span class="trigger-label">On Upgrade</span><span class="trigger-value" id="radarr-onUpgrade"></span></div>
</div>
<div class="webhook-stats hidden" id="radarr-stats">
<div class="webhook-stats-title">Statistics</div>
<div class="webhook-stats-grid">
<div class="webhook-stat"><span class="webhook-stat-label">Events Received</span><span class="webhook-stat-value" id="radarr-events">0</span></div>
<div class="webhook-stat"><span class="webhook-stat-label">Polls Skipped</span><span class="webhook-stat-value" id="radarr-polls">0</span></div>
<div class="webhook-stat"><span class="webhook-stat-label">Last Event</span><span class="webhook-stat-value" id="radarr-last">Never</span></div>
</div>
</div>
</div>
<!-- Ombi Webhook -->
<div class="webhook-instance">
<h3>Ombi</h3>
<div class="webhook-status">
<span class="status-indicator" id="ombi-status">○ Disabled</span>
<button id="enable-ombi-webhook" class="enable-webhook-btn hidden">Enable Sofarr Webhooks</button>
<button id="test-ombi-webhook" class="test-webhook-btn hidden">Test</button>
</div>
<div class="webhook-triggers hidden" id="ombi-triggers">
<div class="trigger-item"><span class="trigger-label">Request Available</span><span class="trigger-value" id="ombi-requestAvailable"></span></div>
<div class="trigger-item"><span class="trigger-label">Request Approved</span><span class="trigger-value" id="ombi-requestApproved"></span></div>
<div class="trigger-item"><span class="trigger-label">Request Declined</span><span class="trigger-value" id="ombi-requestDeclined"></span></div>
<div class="trigger-item"><span class="trigger-label">Request Pending</span><span class="trigger-value" id="ombi-requestPending"></span></div>
<div class="trigger-item"><span class="trigger-label">Request Processing</span><span class="trigger-value" id="ombi-requestProcessing"></span></div>
</div>
<div class="webhook-stats hidden" id="ombi-stats">
<div class="webhook-stats-title">Statistics</div>
<div class="webhook-stats-grid">
<div class="webhook-stat"><span class="webhook-stat-label">Events Received</span><span class="webhook-stat-value" id="ombi-events">0</span></div>
<div class="webhook-stat"><span class="webhook-stat-label">Polls Skipped</span><span class="webhook-stat-value" id="ombi-polls">0</span></div>
<div class="webhook-stat"><span class="webhook-stat-label">Last Event</span><span class="webhook-stat-value" id="ombi-last">Never</span></div>
</div>
</div>
</div>
</div>
</div>
<div id="error-message" class="error-message hidden"></div>
<div id="loading" class="loading hidden">Loading downloads...</div>
<div class="main-tabs">
<div class="tab-bar">
<button class="tab-btn active" data-tab="downloads">Active Downloads</button>
<button class="tab-btn" data-tab="requests">Requests</button>
<button class="tab-btn" data-tab="history">Recently Completed</button>
</div>
<div class="tab-panel" id="tab-downloads">
<div class="downloads-container">
<div class="downloads-header tab-header">
<div class="tab-header-title">
<h2><span class="tab-header-icon">📥</span> Active Downloads</h2>
<p class="tab-header-subtitle">Track and manage your active media downloads in real-time</p>
</div>
<div class="downloads-controls tab-header-controls">
<label class="download-client-label" for="download-client-filter">Download client:</label>
<div class="download-client-filter" id="download-client-filter">
<button class="download-client-dropdown-btn" id="download-client-dropdown-btn" type="button" aria-expanded="false">
<span id="download-client-selected-text">All clients</span>
<span class="dropdown-arrow"></span>
</button>
<div class="download-client-dropdown" id="download-client-dropdown">
<div class="download-client-dropdown-header">
<button class="download-client-dropdown-btn-small" id="download-client-select-all" type="button">Select All</button>
<button class="download-client-dropdown-btn-small" id="download-client-deselect-all" type="button">Deselect All</button>
</div>
<div class="download-client-options" id="download-client-options">
<!-- Options will be populated by JavaScript -->
</div>
</div>
</div>
</div>
</div>
<div id="no-downloads" class="no-downloads hidden">
<p>No downloads found for your user.</p>
<p>Make sure your shows and movies are tagged with your username in Sonarr/Radarr.</p>
</div>
<div id="downloads-list" class="downloads-list"></div>
</div>
</div>
<div class="tab-panel hidden" id="tab-requests">
<div class="requests-container">
<div class="requests-header tab-header">
<div class="tab-header-title">
<h2><span class="tab-header-icon">📨</span> Requests</h2>
<p class="tab-header-subtitle">Browse, filter, and track requests synced from Ombi</p>
</div>
<div class="requests-controls tab-header-controls">
<!-- Media Type Filter -->
<div class="request-filter" id="request-type-filter">
<label class="request-filter-label">Type:</label>
<button class="request-filter-btn" id="request-type-filter-btn" type="button" aria-expanded="false">
<span id="request-type-selected-text">All</span>
<span class="dropdown-arrow"></span>
</button>
<div class="request-filter-dropdown" id="request-type-filter-dropdown">
<div class="request-filter-dropdown-header">
<button class="request-filter-dropdown-btn-small" id="request-type-select-all" type="button">Select All</button>
<button class="request-filter-dropdown-btn-small" id="request-type-deselect-all" type="button">Deselect All</button>
</div>
<div class="request-filter-options" id="request-type-options">
<div class="request-filter-option" data-value="movie">
<input type="checkbox" id="request-type-movie" class="request-filter-checkbox" checked>
<label for="request-type-movie">Movies</label>
</div>
<div class="request-filter-option" data-value="tv">
<input type="checkbox" id="request-type-tv" class="request-filter-checkbox" checked>
<label for="request-type-tv">TV Shows</label>
</div>
</div>
</div>
</div>
<!-- Status Filter -->
<div class="request-filter" id="request-status-filter">
<label class="request-filter-label">Status:</label>
<button class="request-filter-btn" id="request-status-filter-btn" type="button" aria-expanded="false">
<span id="request-status-selected-text">All</span>
<span class="dropdown-arrow"></span>
</button>
<div class="request-filter-dropdown" id="request-status-filter-dropdown">
<div class="request-filter-dropdown-header">
<button class="request-filter-dropdown-btn-small" id="request-status-select-all" type="button">Select All</button>
<button class="request-filter-dropdown-btn-small" id="request-status-deselect-all" type="button">Deselect All</button>
</div>
<div class="request-filter-options" id="request-status-options">
<div class="request-filter-option" data-value="pending">
<input type="checkbox" id="request-status-pending" class="request-filter-checkbox">
<label for="request-status-pending">Pending</label>
</div>
<div class="request-filter-option" data-value="approved">
<input type="checkbox" id="request-status-approved" class="request-filter-checkbox">
<label for="request-status-approved">Approved</label>
</div>
<div class="request-filter-option" data-value="available">
<input type="checkbox" id="request-status-available" class="request-filter-checkbox">
<label for="request-status-available">Available</label>
</div>
<div class="request-filter-option" data-value="denied">
<input type="checkbox" id="request-status-denied" class="request-filter-checkbox">
<label for="request-status-denied">Denied</label>
</div>
</div>
</div>
</div>
<!-- Sort Dropdown -->
<div class="request-sort">
<label class="request-filter-label" for="request-sort-select">Sort:</label>
<select id="request-sort-select" class="request-sort-select">
<option value="requestedDate_desc">Newest to oldest</option>
<option value="requestedDate_asc">Oldest to newest</option>
<option value="title_asc">AZ</option>
<option value="title_desc">ZA</option>
</select>
</div>
<!-- Search Input -->
<div class="request-search">
<input type="text" id="request-search-input" class="request-search-input" placeholder="Search by title...">
</div>
</div>
</div>
<div id="no-requests" class="no-requests hidden">
<p>No requests found.</p>
</div>
<div id="requests-list" class="requests-list"></div>
</div>
</div>
<div class="tab-panel hidden" id="tab-history">
<div class="history-container" id="history-container">
<div class="history-header tab-header">
<div class="tab-header-title">
<h2><span class="tab-header-icon">📜</span> Recently Completed</h2>
<p class="tab-header-subtitle">Review successful imports and troubleshoot failed upgrade attempts</p>
</div>
<div class="history-controls tab-header-controls">
<label class="history-days-label" for="history-days">Last</label>
<input type="number" id="history-days" class="history-days-input" value="7" min="1" max="90">
<span class="history-days-label">days</span>
<button id="history-refresh-btn" class="history-refresh-btn" title="Refresh history">&#8635;</button>
<label class="history-toggle-label" id="ignore-available-label" data-tooltip="Hide failed downloads where the item is already available on disk (i.e. a failed upgrade attempt)">
<input type="checkbox" id="ignore-available-toggle">
<span>Hide upgrade failures</span>
</label>
</div>
</div>
<div id="history-loading" class="history-loading hidden">Loading history...</div>
<div id="history-error" class="history-error hidden"></div>
<div id="no-history" class="no-history hidden">
<p>No completed downloads found in this period.</p>
</div>
<div id="history-list" class="history-list"></div>
</div>
</div>
</div>
<footer class="app-footer">
<p>Ensure your media is tagged with your username in Sonarr/Radarr to match downloads to users.</p>
<a href="https://git.i3omb.com/Gandalf/sofarr" target="_blank" rel="noopener noreferrer" class="app-version" id="app-version"></a>
</footer>
</div>
</div>
<script src="app.js"></script>
</body>
</html>