feat(UI): initial working frontend UI

This commit is contained in:
2025-10-09 17:12:55 +13:00
parent e8972cae38
commit 9e61d18bf6
26 changed files with 6885 additions and 3 deletions
+86
View File
@@ -0,0 +1,86 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Authentication Failed - BDFR Web Interface</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
margin: 0;
padding: 0;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.error-container {
background: white;
padding: 2rem;
border-radius: 10px;
box-shadow: 0 10px 25px rgba(0,0,0,0.1);
text-align: center;
max-width: 400px;
width: 90%;
}
.error-icon {
font-size: 3rem;
color: #f44336;
margin-bottom: 1rem;
}
.error-title {
color: #333;
margin-bottom: 1rem;
font-size: 1.5rem;
}
.error-message {
color: #666;
margin-bottom: 1.5rem;
line-height: 1.5;
}
.error-details {
background: #f5f5f5;
padding: 1rem;
border-radius: 5px;
font-family: monospace;
font-size: 0.8rem;
color: #888;
margin-bottom: 1.5rem;
text-align: left;
white-space: pre-wrap;
word-break: break-all;
}
.retry-button {
background: #667eea;
color: white;
padding: 0.75rem 1.5rem;
border: none;
border-radius: 5px;
text-decoration: none;
display: inline-block;
margin-top: 1rem;
transition: background 0.3s;
}
.retry-button:hover {
background: #5a67d8;
}
</style>
</head>
<body>
<div class="error-container">
<div class="error-icon"></div>
<h1 class="error-title">Authentication Failed</h1>
<p class="error-message">
There was an error during the authentication process. This might be due to:
</p>
<ul style="text-align: left; color: #666; margin: 1rem 0;">
<li>Invalid or expired authorization code</li>
<li>Mismatched redirect URI configuration</li>
<li>Reddit OAuth app not properly configured</li>
</ul>
<div class="error-details">{{ error }}</div>
<a href="/?auth_error=true" class="retry-button">Return to Main Page</a>
</div>
</body>
</html>
+82
View File
@@ -0,0 +1,82 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Authentication Successful - BDFR Web Interface</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
margin: 0;
padding: 0;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.success-container {
background: white;
padding: 2rem;
border-radius: 10px;
box-shadow: 0 10px 25px rgba(0,0,0,0.1);
text-align: center;
max-width: 400px;
width: 90%;
}
.success-icon {
font-size: 3rem;
color: #4CAF50;
margin-bottom: 1rem;
}
.success-title {
color: #333;
margin-bottom: 1rem;
font-size: 1.5rem;
}
.success-message {
color: #666;
margin-bottom: 1.5rem;
line-height: 1.5;
}
.redirect-message {
color: #888;
font-size: 0.9rem;
margin-top: 1rem;
}
.spinner {
border: 3px solid #f3f3f3;
border-top: 3px solid #667eea;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 1s linear infinite;
margin: 0 auto 1rem;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div class="success-container">
<div class="success-icon"></div>
<h1 class="success-title">Authentication Successful!</h1>
<p class="success-message">
You have successfully authenticated with Reddit. You can now use all features of the BDFR Web Interface.
</p>
<div class="spinner"></div>
<p class="redirect-message">
Redirecting you back to the main interface...
</p>
</div>
<script>
// Redirect to main page after 3 seconds
setTimeout(function() {
window.location.href = '/?authenticated=true';
}, 3000);
</script>
</body>
</html>
+209
View File
@@ -0,0 +1,209 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BDFR Web Interface</title>
<link rel="stylesheet" href="/static/css/style.css">
</head>
<body>
<div class="container">
<header>
<h1>Bulk Downloader for Reddit</h1>
<p class="subtitle">Web Interface</p>
<!-- Authentication Status -->
<div id="authSection" class="auth-section" style="display: none;">
<div class="auth-status">
<div class="auth-info">
<span class="auth-label">Reddit Account:</span>
<span id="authUser" class="auth-user">-</span>
<span id="authStatus" class="auth-status-indicator">🔴 Not Connected</span>
</div>
<div class="auth-actions">
<button id="loginBtn" class="btn btn-small btn-outline">🔐 Login with Reddit</button>
<button id="logoutBtn" class="btn btn-small btn-outline" style="display: none;">🚪 Logout</button>
</div>
</div>
</div>
</header>
<main>
<!-- Unified Download Form Section -->
<section class="download-section">
<div class="form-container-unified">
<div class="form-card-unified">
<h2>📥 Download Reddit Content</h2>
<form id="unifiedForm" class="download-form">
<!-- Mode Selection -->
<div class="form-section mode-section">
<h4>🎯 Download Mode</h4>
<div class="radio-group mode-radio-group">
<label class="radio-label mode-option" data-tooltip="Download media files (images, videos, gifs) from posts">
<input type="radio" name="download_mode" value="download" checked>
<span class="radio-custom"></span>
<span class="mode-label">
<strong>Download</strong>
<small>Media files only</small>
</span>
</label>
<label class="radio-label mode-option" data-tooltip="Save post metadata (title, author, comments) as JSON/XML without downloading media">
<input type="radio" name="download_mode" value="archive">
<span class="radio-custom"></span>
<span class="mode-label">
<strong>Archive</strong>
<small>Metadata only</small>
</span>
</label>
<label class="radio-label mode-option" data-tooltip="Download media files AND save metadata - complete backup of posts">
<input type="radio" name="download_mode" value="clone">
<span class="radio-custom"></span>
<span class="mode-label">
<strong>Clone</strong>
<small>Media + Metadata</small>
</span>
</label>
</div>
</div>
<!-- Source Type Selection -->
<div class="form-section">
<h4>📍 Source Type</h4>
<div class="radio-group">
<label class="radio-label">
<input type="radio" name="source_type" value="subreddit" checked>
<span class="radio-custom"></span>
Subreddit
</label>
<label class="radio-label">
<input type="radio" name="source_type" value="user">
<span class="radio-custom"></span>
User
</label>
</div>
</div>
<!-- Source Name Input -->
<div class="form-group">
<label for="sourceName" id="sourceNameLabel">Subreddit Name:</label>
<input type="text" id="sourceName" name="source_name" placeholder="e.g., python, machinelearning" required>
<small class="form-help" id="sourceNameHelp">Enter subreddit name without 'r/'</small>
</div>
<!-- Filter Options -->
<div class="form-row">
<div class="form-group">
<label for="limit">Limit:</label>
<input type="number" id="limit" name="limit" value="25" min="1" max="1000">
<small class="form-help">Max posts to process (1-1000)</small>
</div>
<div class="form-group">
<label for="sort">Sort by:</label>
<select id="sort" name="sort">
<option value="hot">Hot</option>
<option value="top" selected>Top</option>
<option value="new">New</option>
<option value="rising">Rising</option>
<option value="controversial">Controversial</option>
</select>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="timeFilter">Time Filter:</label>
<select id="timeFilter" name="time_filter">
<option value="">All Time</option>
<option value="hour">Past Hour</option>
<option value="day">Past Day</option>
<option value="week">Past Week</option>
<option value="month">Past Month</option>
<option value="year">Past Year</option>
</select>
</div>
<div class="form-group">
<label for="minScore">Min Score:</label>
<input type="number" id="minScore" name="min_score" value="" placeholder="0">
<small class="form-help">Minimum upvotes</small>
</div>
</div>
<!-- Advanced Options -->
<div class="form-section">
<h4>⚙️ Advanced Options</h4>
<div class="checkbox-group">
<label class="checkbox-label">
<input type="checkbox" id="noDupes" name="no_dupes">
<span class="checkmark"></span>
Avoid Duplicates
</label>
<label class="checkbox-label" style="margin-left: 30px; font-size: 0.9em;">
<input type="checkbox" id="simpleCheck" name="simple_check">
<span class="checkmark"></span>
Use Simple Check (faster URL-based detection)
</label>
<label class="checkbox-label">
<input type="checkbox" id="makeHardLinks" name="make_hard_links">
<span class="checkmark"></span>
Create Hard Links
</label>
</div>
</div>
<input type="hidden" id="authState" name="auth_state" value="">
<button type="submit" class="btn btn-primary">🚀 Start Download</button>
</form>
</div>
</div>
</section>
<!-- Progress Section -->
<section class="progress-section">
<h2>📊 Download Progress</h2>
<div id="progressContainer" class="progress-container">
<div class="no-downloads">
<div class="empty-state">
<div class="empty-icon">📥</div>
<p>No active downloads</p>
<p>Start a download above to see progress here.</p>
</div>
</div>
</div>
<!-- Active Downloads List -->
<div id="downloadsList" class="downloads-list" style="display: none;">
<div class="downloads-header">
<h3>Active Downloads</h3>
</div>
<div id="downloadsItems" class="downloads-items"></div>
</div>
</section>
<!-- Status Section -->
<section class="status-section">
<div class="status-card">
<h3>System Status</h3>
<div class="status-item">
<span class="status-label">BDFR Status:</span>
<span id="bdfrStatus" class="status-value">Checking...</span>
</div>
<div class="status-item">
<span class="status-label">WebSocket:</span>
<span id="wsStatus" class="status-value">Disconnected</span>
</div>
</div>
</section>
</main>
<footer>
<p>&copy; 2024 BDFR Web Interface. Powered by FastAPI.</p>
</footer>
</div>
<script src="/static/js/app.js"></script>
</body>
</html>