198 lines
9.6 KiB
HTML
198 lines
9.6 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>PDF Splitter</title>
|
|
<meta name="description" content="Split PDF chapters and pages with a modern web interface">
|
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📄</text></svg>">
|
|
<link rel="stylesheet" href="style.css">
|
|
</head>
|
|
<body>
|
|
|
|
<!-- Header -->
|
|
<header id="header">
|
|
<div class="header-brand">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="header-icon"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="9" y1="15" x2="15" y2="15"/></svg>
|
|
<h1>PDF Splitter</h1>
|
|
</div>
|
|
<button id="btn-admin-settings" class="admin-only icon-btn" aria-label="Admin Settings" title="Admin Settings">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
|
|
</button>
|
|
</header>
|
|
|
|
<!-- Main Layout -->
|
|
<main id="app">
|
|
<!-- Sidebar -->
|
|
<aside id="sidebar">
|
|
|
|
<!-- File Upload -->
|
|
<section class="card">
|
|
<h2 class="card-label">Source PDF</h2>
|
|
<label id="btn-open" class="btn-primary" for="file-input-hidden">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
|
|
Choose File
|
|
</label>
|
|
<input type="file" id="file-input-hidden" accept=".pdf" style="display:none">
|
|
<div id="file-info" class="file-info hidden">
|
|
<div id="file-name" class="file-name"></div>
|
|
<div id="file-pages" class="file-meta"></div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- Chapters -->
|
|
<section class="card" id="chapter-section">
|
|
<div class="card-header">
|
|
<h2 class="card-label">Chapters</h2>
|
|
<div id="depth-control" class="depth-control hidden">
|
|
<label class="depth-label" for="depth-select">Detail</label>
|
|
<select id="depth-select" class="depth-select">
|
|
<option value="1">Chapters</option>
|
|
<option value="2">Sections</option>
|
|
<option value="99">All</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div id="chapter-loading" class="status-msg hidden">
|
|
<div class="spinner"></div>
|
|
<span>Detecting chapters…</span>
|
|
</div>
|
|
<div id="chapter-none" class="status-msg hidden">
|
|
<span>No chapters detected. Use page selection below.</span>
|
|
</div>
|
|
<div id="chapter-search-wrap" class="chapter-search-wrap hidden">
|
|
<svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
|
|
<input type="text" id="chapter-search" class="chapter-search" placeholder="Search chapters…" autocomplete="off" spellcheck="false">
|
|
</div>
|
|
<div id="chapter-list" class="chapter-list"></div>
|
|
</section>
|
|
|
|
<!-- Page Input -->
|
|
<section class="card">
|
|
<h2 class="card-label">Pages / Ranges</h2>
|
|
<div class="input-hint">e.g. 1-10, 15, 20-25</div>
|
|
<input type="text" id="page-input" class="text-input" placeholder="">
|
|
</section>
|
|
|
|
<!-- Action -->
|
|
<section class="card action-card">
|
|
<div class="page-count-row">
|
|
<span class="count-label">Selected pages</span>
|
|
<span id="page-count" class="count-value">0</span>
|
|
</div>
|
|
<button id="btn-split" class="btn-accent" disabled>
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
|
|
Split & Download
|
|
</button>
|
|
</section>
|
|
</aside>
|
|
|
|
<!-- Resize Handle -->
|
|
<div id="resize-handle" class="resize-handle"></div>
|
|
|
|
<!-- Preview Panel -->
|
|
<section id="preview">
|
|
<div id="preview-empty" class="preview-placeholder">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.2" class="placeholder-icon"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
|
|
<p>Upload a PDF and choose pages to preview</p>
|
|
</div>
|
|
<div id="preview-grid" class="preview-grid hidden"></div>
|
|
|
|
<!-- Lightbox -->
|
|
<div id="lightbox" class="lightbox hidden">
|
|
<div class="lightbox-backdrop"></div>
|
|
<div class="lightbox-content">
|
|
<button id="lightbox-close" class="lightbox-close" aria-label="Close">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="6" y1="6" x2="18" y2="18"/><line x1="18" y1="6" x2="6" y2="18"/></svg>
|
|
</button>
|
|
<div class="lightbox-page-info" id="lightbox-page-info"></div>
|
|
<div class="lightbox-canvas-wrap">
|
|
<canvas id="lightbox-canvas"></canvas>
|
|
</div>
|
|
<div class="lightbox-nav">
|
|
<button id="lightbox-prev" class="lightbox-nav-btn" aria-label="Previous">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 18 9 12 15 6"/></svg>
|
|
</button>
|
|
<button id="lightbox-next" class="lightbox-nav-btn" aria-label="Next">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 6 15 12 9 18"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<!-- Drop Overlay -->
|
|
<div id="drop-overlay" class="drop-overlay hidden">
|
|
<div class="drop-overlay-content">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="drop-icon"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>
|
|
<p>Drop PDF here</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Upload Progress -->
|
|
<div id="upload-overlay" class="upload-overlay hidden">
|
|
<div class="upload-overlay-content">
|
|
<div class="spinner large"></div>
|
|
<p id="upload-status">Uploading PDF…</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Login Overlay -->
|
|
<div id="login-overlay" class="login-overlay hidden">
|
|
<div class="login-box">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="login-icon"><rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
|
|
<h2>Protected Access</h2>
|
|
<p>Please enter the application password.</p>
|
|
<form id="login-form">
|
|
<input type="password" id="login-password" placeholder="Password" autocomplete="current-password" autofocus>
|
|
<button type="submit" class="btn-accent">Unlock</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Admin Modal -->
|
|
<div id="admin-modal" class="lightbox hidden">
|
|
<div class="lightbox-backdrop"></div>
|
|
<div class="admin-panel card">
|
|
<button id="admin-close" class="admin-close" aria-label="Close">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
|
</button>
|
|
<h2 class="admin-title">Admin Dashboard</h2>
|
|
|
|
<div class="admin-section">
|
|
<h3>Server Stats</h3>
|
|
<div class="admin-stats" id="admin-stats-container">
|
|
<div class="spinner"></div> Loading…
|
|
</div>
|
|
</div>
|
|
|
|
<div class="admin-section">
|
|
<h3>Actions</h3>
|
|
<div class="admin-actions">
|
|
<button id="btn-admin-clear-cache" class="btn-primary">Clear PDF Cache</button>
|
|
<button id="btn-admin-clear-logins" class="btn-primary">Reset Login Locks</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="admin-section">
|
|
<h3>Change User Password</h3>
|
|
<p class="admin-hint">Updates the normal APP_PASSWORD instantly in memory. (Will revert on container restart unless you change it in Unraid).</p>
|
|
<form id="admin-password-form" class="admin-password-form">
|
|
<input type="password" id="admin-new-password" class="text-input" placeholder="New User Password" required>
|
|
<button type="submit" class="btn-primary">Update</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Toast container -->
|
|
<div id="toast-container"></div>
|
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
|
|
<script>
|
|
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
|
|
</script>
|
|
<script src="app.js"></script>
|
|
</body>
|
|
</html>
|