Downloads official instruction PDFs from LEGO, located via the Brickset API, one set per interval (10 minutes by default) so neither API gets hammered. Official sets only; MOCs are excluded throughout. - New admin page at /admin/instruction-fetch: queue builder, pacing controls, live countdown and per-set job history - Database-backed queue (instruction_fetch_jobs) and last-run timestamp, so pacing survives restarts - Background worker thread, plus 'flask instructions queue/run/status' for Task Scheduler or cron - SHA-256 dedupe (instructions.sha256), PDF header check, size cap and streaming downloads via temp files - brickset_api: getInstructions2 by set number and getInstructions by setID (the old code sent a set number to the setID method); getSets params now proper JSON; getKeyUsageStats added - Schema top-ups applied automatically at boot: new table plus instructions.sha256/source - Docker: fetcher env vars passed through compose, no worker thread in the entrypoint bootstrap
183 lines
8.7 KiB
HTML
183 lines
8.7 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Site Settings - Admin{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="row mb-4">
|
|
<div class="col">
|
|
<h1><i class="bi bi-sliders"></i> Site Settings</h1>
|
|
</div>
|
|
<div class="col-auto">
|
|
<a href="{{ url_for('instruction_fetch.index') }}" class="btn btn-outline-warning me-2">
|
|
<i class="bi bi-cloud-arrow-down"></i> Instruction Fetcher
|
|
</a>
|
|
<a href="{{ url_for('backup.index') }}" class="btn btn-outline-danger me-2">
|
|
<i class="bi bi-archive"></i> Backup & Restore
|
|
</a>
|
|
<a href="{{ url_for('admin.dashboard') }}" class="btn btn-outline-secondary">
|
|
<i class="bi bi-arrow-left"></i> Back
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-lg-7">
|
|
<form method="POST">
|
|
<input type="hidden" name="action" value="save">
|
|
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0"><i class="bi bi-person-plus"></i> Accounts</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" role="switch"
|
|
id="allow_registration" name="allow_registration"
|
|
{% if settings.allow_registration in ['true', '1', 'yes', 'on'] %}checked{% endif %}>
|
|
<label class="form-check-label" for="allow_registration">
|
|
<strong>Allow self-registration</strong>
|
|
</label>
|
|
</div>
|
|
<div class="form-text">
|
|
When off, the Register page is hidden and blocked, and you create
|
|
accounts yourself from
|
|
<a href="{{ url_for('admin.users') }}">User Management</a>.
|
|
The very first account on a fresh install is always allowed,
|
|
so this can't lock you out.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0"><i class="bi bi-eye"></i> Set visibility</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<label class="form-label"><strong>Default for newly added sets</strong></label>
|
|
|
|
<div class="form-check mb-2">
|
|
<input class="form-check-input" type="radio" name="default_visibility"
|
|
id="vis_private" value="private"
|
|
{% if settings.default_visibility == 'private' %}checked{% endif %}>
|
|
<label class="form-check-label" for="vis_private">
|
|
<i class="bi bi-lock-fill"></i> <strong>Private</strong>
|
|
— only the owner and administrators.
|
|
</label>
|
|
</div>
|
|
<div class="form-check mb-2">
|
|
<input class="form-check-input" type="radio" name="default_visibility"
|
|
id="vis_shared" value="shared"
|
|
{% if settings.default_visibility == 'shared' %}checked{% endif %}>
|
|
<label class="form-check-label" for="vis_shared">
|
|
<i class="bi bi-people-fill"></i> <strong>Shared</strong>
|
|
— the owner picks which users can see each set.
|
|
</label>
|
|
</div>
|
|
<div class="form-check mb-3">
|
|
<input class="form-check-input" type="radio" name="default_visibility"
|
|
id="vis_public" value="public"
|
|
{% if settings.default_visibility == 'public' %}checked{% endif %}>
|
|
<label class="form-check-label" for="vis_public">
|
|
<i class="bi bi-globe"></i> <strong>Public</strong>
|
|
— every logged-in user.
|
|
</label>
|
|
</div>
|
|
|
|
<div class="alert alert-light border small mb-0">
|
|
Visibility only controls who can <em>see</em> a set and its files.
|
|
Only the owner and administrators can ever change one.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0"><i class="bi bi-signpost-split"></i> Navigation</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" role="switch"
|
|
id="home_redirect_dashboard" name="home_redirect_dashboard"
|
|
{% if settings.home_redirect_dashboard in ['true', '1', 'yes', 'on'] %}checked{% endif %}>
|
|
<label class="form-check-label" for="home_redirect_dashboard">
|
|
<strong>Send logged-in users straight to their dashboard</strong>
|
|
</label>
|
|
</div>
|
|
<div class="form-text">
|
|
Skips the welcome page for anyone already signed in. Logged-out
|
|
visitors still see it.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-danger">
|
|
<i class="bi bi-check-lg"></i> Save settings
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="col-lg-5">
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0">System Information</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<table class="table table-sm mb-0">
|
|
<tr><td>Total Users:</td><td><strong>{{ stats.total_users }}</strong></td></tr>
|
|
<tr><td>Total Sets:</td><td><strong>{{ stats.total_sets }}</strong></td></tr>
|
|
<tr><td>Total Instructions:</td><td><strong>{{ stats.total_instructions }}</strong></td></tr>
|
|
<tr><td>Storage Used:</td>
|
|
<td><strong>{{ (stats.total_storage / 1024 / 1024) | round(2) }} MB</strong></td></tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card mb-4">
|
|
<div class="card-header">
|
|
<h5 class="mb-0"><i class="bi bi-collection"></i> Existing sets</h5>
|
|
</div>
|
|
<div class="card-body">
|
|
<table class="table table-sm">
|
|
<tr>
|
|
<td><i class="bi bi-lock-fill"></i> Private</td>
|
|
<td class="text-end"><strong>{{ visibility_counts.get('private', 0) }}</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td><i class="bi bi-people-fill"></i> Shared</td>
|
|
<td class="text-end"><strong>{{ visibility_counts.get('shared', 0) }}</strong></td>
|
|
</tr>
|
|
<tr>
|
|
<td><i class="bi bi-globe"></i> Public</td>
|
|
<td class="text-end"><strong>{{ visibility_counts.get('public', 0) }}</strong></td>
|
|
</tr>
|
|
</table>
|
|
|
|
<p class="small text-muted">
|
|
Sets that existed before visibility was added were made
|
|
<strong>public</strong>, so nothing disappeared from anyone's library.
|
|
Change them all at once here, then adjust individual sets from their
|
|
own pages.
|
|
</p>
|
|
|
|
<form method="POST"
|
|
onsubmit="return confirm('Change the visibility of EVERY set? This cannot be undone.');">
|
|
<input type="hidden" name="action" value="apply_visibility">
|
|
<div class="input-group">
|
|
<select name="bulk_visibility" class="form-select">
|
|
{% for v in visibilities %}
|
|
<option value="{{ v }}">{{ v|capitalize }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
<button type="submit" class="btn btn-outline-danger">
|
|
Apply to all
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<p class="text-center text-muted small">Created by: Jess Rogerson (yelling commands at Claude.AI)</p>
|
|
{% endblock %}
|