Files
duplicati_preview/public/index.html
T

236 lines
11 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Duplicati Control Center</title>
<link rel="stylesheet" href="/styles.css">
</head>
<body>
<main class="shell">
<section class="hero hero-compact">
<div>
<p class="eyebrow">Zero-Bandwidth Duplicati Web Client</p>
<h1>Duplicati Control Center</h1>
</div>
<p class="lead">
Manage task databases, Server DB metadata, global WebDAV defaults, and site-wide HTTPS/TLS settings here.
Browsing, enhancement, preview, and download stay in the per-source and per-file workspaces.
</p>
</section>
<div class="auth-toolbar">
<span id="authStatus" class="auth-status">Loading login state...</span>
<button id="logoutButton" class="ghost-button" type="button">Sign out</button>
</div>
<div id="feedback" class="feedback" hidden></div>
<section class="workspace-shell">
<aside class="workspace-nav" aria-label="Control Center menu">
<a class="workspace-nav-link" href="#overview" data-view-link="overview">Overview</a>
<a class="workspace-nav-link" href="#sources" data-view-link="sources">Sources</a>
<a class="workspace-nav-link" href="#upload" data-view-link="upload">Upload task DB</a>
<a class="workspace-nav-link" href="#server-db" data-view-link="server-db">Server DB</a>
<a class="workspace-nav-link" href="#defaults" data-view-link="defaults">Global WebDAV</a>
<a class="workspace-nav-link" href="#tls" data-view-link="tls">HTTPS / TLS</a>
</aside>
<div class="workspace-content">
<section class="workspace-panel" data-view-panel="overview">
<div class="panel stack-gap">
<div class="panel-header">
<div>
<p class="section-label">Overview</p>
<h2>System summary</h2>
</div>
</div>
<div id="overviewSummary" class="summary-card">Loading overview...</div>
</div>
</section>
<section class="workspace-panel" data-view-panel="sources" hidden>
<div class="panel panel-spacious">
<div class="panel-header">
<div>
<p class="section-label">Sources</p>
<h2>Uploaded task databases</h2>
</div>
<button id="refreshButton" class="ghost-button" type="button">Refresh</button>
</div>
<p class="panel-copy">
Each uploaded Duplicati task database becomes one source. Open a source workbench to browse files,
start enhancement, or jump into the file workspace.
</p>
<div id="sourceList" class="source-list empty-state">Loading sources...</div>
</div>
</section>
<section class="workspace-panel" data-view-panel="upload" hidden>
<div class="panel">
<div class="panel-header">
<div>
<p class="section-label">Task DB</p>
<h2>Add a new source</h2>
</div>
</div>
<p class="panel-copy">
Upload a Duplicati task database such as <code>TMQRJYNADS.sqlite</code>. Re-uploading the same file
reuses the existing source instead of creating a duplicate.
</p>
<form id="uploadForm" class="upload-form">
<label class="file-picker">
<span>Select task SQLite file</span>
<input id="databaseInput" name="database" type="file" accept=".sqlite,.db,application/octet-stream">
</label>
<div class="form-actions">
<button id="uploadButton" class="primary-button" type="submit">Upload as new source</button>
</div>
</form>
</div>
</section>
<section class="workspace-panel" data-view-panel="server-db" hidden>
<div class="panel stack-gap">
<div class="panel-header">
<div>
<p class="section-label">Server DB</p>
<h2>Upload Duplicati-server.sqlite</h2>
</div>
</div>
<p class="panel-copy">
The server database lets the UI resolve friendly task names and infer default target URLs from
Duplicati metadata.
</p>
<form id="serverDbForm" class="upload-form">
<label class="file-picker">
<span>Select server database</span>
<input id="serverDbInput" name="database" type="file" accept=".sqlite,.db,application/octet-stream">
</label>
<div class="form-actions">
<button id="serverDbUploadButton" class="ghost-button" type="submit">Upload Server DB</button>
</div>
</form>
<div id="serverDbSummary" class="summary-card">Loading Server DB status...</div>
</div>
</section>
<section class="workspace-panel" data-view-panel="defaults" hidden>
<div class="panel stack-gap">
<div class="panel-header">
<div>
<p class="section-label">Global WebDAV</p>
<h2>Shared defaults</h2>
</div>
</div>
<p class="panel-copy">
Save credentials and a fallback base URL once when most tasks share the same WebDAV settings.
</p>
<form id="globalDefaultsForm" class="secret-form">
<label>
<span>Fallback WebDAV Base URL</span>
<input id="globalWebdavBaseUrl" name="webdavBaseUrl" type="url" placeholder="Optional shared base URL">
</label>
<label>
<span>Authentication mode</span>
<select id="globalAuthMode" name="authMode">
<option value="">Auto / inherited</option>
<option value="basic">Basic</option>
<option value="anonymous">Anonymous</option>
</select>
</label>
<label>
<span>Username</span>
<input id="globalUsername" name="username" type="text" placeholder="Optional shared username">
</label>
<label>
<span>Password</span>
<input id="globalPassword" name="password" type="password" placeholder="Optional shared password">
</label>
<label>
<span>Backup passphrase</span>
<input id="globalPassphrase" name="passphrase" type="password" placeholder="Optional shared passphrase">
</label>
<div class="form-actions">
<button id="globalDefaultsSaveButton" class="ghost-button" type="submit">Save defaults</button>
</div>
</form>
<div id="globalDefaultsSummary" class="summary-card">Loading WebDAV defaults...</div>
</div>
</section>
<section class="workspace-panel" data-view-panel="tls" hidden>
<div class="panel stack-gap">
<div class="panel-header">
<div>
<p class="section-label">HTTPS / TLS</p>
<h2>Domain and certificate settings</h2>
</div>
</div>
<p class="panel-copy">
HTTP and HTTPS stay enabled side-by-side. If no custom certificate is configured, the service keeps a
self-signed certificate ready so HTTPS is always available.
</p>
<div id="tlsSummary" class="summary-card">Loading TLS configuration...</div>
<form id="tlsJsonForm" class="secret-form">
<label>
<span>Certificate mode</span>
<select id="tlsMode" name="mode">
<option value="self-signed">Self-signed</option>
<option value="custom-pem">Custom PEM</option>
</select>
</label>
<label>
<span>Primary domain</span>
<input id="tlsPrimaryDomain" name="primaryDomain" type="text" placeholder="Example: preview.example.com">
</label>
<label>
<span>Additional SAN entries</span>
<textarea id="tlsSubjectAltNames" name="subjectAltNames" rows="3" placeholder="One hostname or IP per line. Comma-separated values also work."></textarea>
</label>
<label>
<span>Certificate PEM</span>
<textarea id="tlsCertPem" name="certPem" rows="8" placeholder="-----BEGIN CERTIFICATE-----"></textarea>
</label>
<label>
<span>Private key PEM</span>
<textarea id="tlsKeyPem" name="keyPem" rows="8" placeholder="-----BEGIN PRIVATE KEY-----"></textarea>
</label>
<label>
<span>Optional chain PEM</span>
<textarea id="tlsChainPem" name="chainPem" rows="6" placeholder="Optional intermediate certificates"></textarea>
</label>
<div class="form-actions">
<button id="tlsSaveButton" class="primary-button" type="submit">Save and apply</button>
<button id="tlsDeleteCustomButton" class="ghost-button danger-button" type="button">Delete custom cert and fall back</button>
</div>
</form>
<form id="tlsUploadForm" class="upload-form">
<label class="file-picker">
<span>Upload certificate file</span>
<input id="tlsCertificateInput" name="certificate" type="file" accept=".pem,.crt,.cer,text/plain">
</label>
<label class="file-picker">
<span>Upload private key file</span>
<input id="tlsPrivateKeyInput" name="privateKey" type="file" accept=".pem,.key,text/plain">
</label>
<label class="file-picker">
<span>Upload optional chain file</span>
<input id="tlsChainInput" name="chain" type="file" accept=".pem,.crt,.cer,text/plain">
</label>
<div class="form-actions">
<button id="tlsUploadButton" class="ghost-button" type="submit">Apply uploaded certificate</button>
</div>
</form>
</div>
</section>
</div>
</section>
</main>
<script type="module" src="/app.js"></script>
</body>
</html>