arr-summary/templates/settings.html
Barely Removable 18c7719cd7
All checks were successful
Deploy / deploy (push) Successful in 23s
Extract CSS/JS to static files, wrap header pills, add version footer
The palette lived in a :root block duplicated across all three
templates, so every reshade meant three edits — and drifted twice in
practice (the favicon hardcoded its own hex; stale danger-border rgba
literals survived two palette changes). Move tokens to a single
static/css/base.css, derive every dim/border tint from the four source
hues with color-mix, and point the favicon at one static/favicon.svg.

Also splits the 1558-line dashboard.html into template + static assets:
662 lines of CSS and 396 of JS were re-sent uninlined on every load
with no browser caching, which costs real time on the remote/cellular
access this app is built for. Templates drop to 501/42/107 lines.
Server-rendered config (timezone, script_root) now arrives via
<body data-*>; wiring URL_BASE to request.script_root also fixes /api/*
fetches for a future subpath mount, which the hardcoded "" would break.

Header service pills now wrap instead of scrolling — they were clipped
at narrow widths, and a hidden pill is a service whose status you
cannot see. Verified 0 clipped and no page overflow at 320/375/700/1280.

Footer gains a version and date so the running build is identifiable
without trusting the Unraid Docker tab's cached container IDs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 14:27:52 -07:00

107 lines
4.5 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Settings — Media Centre</title>
<link rel="icon" href="{{ url_for('static', filename='favicon.svg') }}">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="{{ url_for('static', filename='css/base.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='css/settings.css') }}">
</head>
<body data-url-base="{{ request.script_root }}">
<header>
<svg width="30" height="30" viewBox="0 0 100 100" aria-hidden="true">
<rect width="100" height="100" rx="22" fill="var(--accent)"/>
<path d="M40 32 L72 50 L40 68 Z" fill="var(--bg)"/>
</svg>
<h1>Settings</h1>
<a href="{{ url_for('dashboard') }}" class="back-btn">← Dashboard</a>
</header>
<main>
<div class="grid">
<!-- General -->
<div class="card full">
<div class="card-header"><h2>General</h2></div>
<div class="card-body">
<div class="field">
<label for="timezone">Timezone</label>
<select id="timezone">
{% set tzs = [
'America/New_York','America/Chicago','America/Denver','America/Los_Angeles',
'America/Toronto','America/Vancouver','America/Phoenix','America/Halifax',
'Europe/London','Europe/Paris','Europe/Berlin','Europe/Amsterdam',
'Europe/Stockholm','Europe/Rome','Europe/Madrid','Europe/Zurich',
'Australia/Sydney','Australia/Melbourne','Australia/Brisbane','Australia/Perth',
'Pacific/Auckland','Asia/Tokyo','Asia/Singapore','Asia/Dubai','Asia/Kolkata'
] %}
{% for tz in tzs %}
<option value="{{ tz }}" {% if tz == timezone %}selected{% endif %}>{{ tz }}</option>
{% endfor %}
</select>
</div>
<div class="field">
<label for="arr_host">Host IP (ARR_HOST)</label>
<input type="text" id="arr_host" value="{{ arr_host }}" placeholder="e.g. 192.168.86.33">
<p class="hint">LAN address of the machine running Sonarr, Radarr, and the rest.</p>
</div>
<button class="save" onclick="saveGeneral()">Save general</button>
</div>
</div>
<!-- Change password -->
<div class="card full">
<div class="card-header"><h2>Change password</h2></div>
<div class="card-body">
<div class="field">
<label for="pw_current">Current password</label>
<input type="password" id="pw_current" autocomplete="current-password">
</div>
<div class="field">
<label for="pw_new">New password</label>
<input type="password" id="pw_new" placeholder="At least 6 characters" autocomplete="new-password">
</div>
<div class="field">
<label for="pw_confirm">Confirm new password</label>
<input type="password" id="pw_confirm" autocomplete="new-password">
<div class="error-inline" id="pw-error" role="alert"></div>
</div>
<button class="save" onclick="changePassword()">Update password</button>
</div>
</div>
<!-- Service API keys -->
{% for svc, label in [
('sonarr','Sonarr'), ('radarr','Radarr'), ('sabnzbd','SABnzbd'),
('tautulli','Tautulli'), ('prowlarr','Prowlarr'), ('ombi','Ombi')
] %}
<div class="card">
<div class="card-header"><h2>{{ label }}</h2></div>
<div class="card-body">
<div class="field">
<label for="{{ svc }}_api_key">API key</label>
<input type="password" id="{{ svc }}_api_key"
value="{{ {'sonarr': sonarr_api_key, 'radarr': radarr_api_key,
'sabnzbd': sabnzbd_api_key, 'tautulli': tautulli_api_key,
'prowlarr': prowlarr_api_key, 'ombi': ombi_api_key}[svc] }}"
autocomplete="off">
</div>
<button class="save" onclick="saveService('{{ svc }}')">Save</button>
</div>
</div>
{% endfor %}
</div>
</main>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="{{ url_for('static', filename='js/settings.js') }}"></script>
</body>
</html>