Files
Martinhal-Birthday-Mailing-App/templates/admin.html
T
2026-09-13 20:15:10 +01:00

166 lines
7.2 KiB
HTML

{% extends "base.html" %}
{% set active = 'admin' %}
{% block title %}Administration - Birthday Manager{% endblock %}
{% block content %}
<!-- ======================= Users ======================= -->
<section class="card">
<h2>Users</h2>
<form method="post" action="{{ url_for('add_user') }}" class="entry-form">
<label>Username<input type="text" name="username" required></label>
<label>Password<input type="password" name="password" required minlength="4"></label>
<button class="btn btn-primary" type="submit">Add user</button>
</form>
<div class="table-wrap">
<table>
<thead><tr><th>Username</th><th>MFA</th><th>Created</th><th></th></tr></thead>
<tbody>
{% for u in users %}
<tr>
<td>{{ u.username }}{% if u.id == user_id %} <span class="pill pill-ok">you</span>{% endif %}</td>
<td>{{ 'Enabled' if u.mfa_enabled else 'Off' }}</td>
<td>{{ u.created_at }}</td>
<td class="ta-right">
{% if u.id != user_id %}
<form method="post" action="{{ url_for('delete_user', uid=u.id) }}"
onsubmit="return confirm('Remove user {{ u.username }}?')">
<button class="btn btn-danger btn-sm" type="submit">Remove</button>
</form>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</section>
<!-- ======================= My account: password + MFA ======================= -->
<div class="two-col">
<section class="card">
<h2>Change my password</h2>
<form method="post" action="{{ url_for('change_password') }}" class="stack-form">
<label>Current password<input type="password" name="current" required autocomplete="current-password"></label>
<label>New password<input type="password" name="new" required minlength="4" autocomplete="new-password"></label>
<label>Confirm new password<input type="password" name="confirm" required minlength="4" autocomplete="new-password"></label>
<button class="btn btn-primary" type="submit">Change password</button>
</form>
</section>
<section class="card">
<h2>Two-factor authentication (MFA)</h2>
{% set me = users | selectattr('id', 'equalto', user_id) | first %}
{% if me and me.mfa_enabled %}
<p>MFA is <strong>enabled</strong> for your account. You'll be asked for a 6-digit code every time you sign in.</p>
<form method="post" action="{{ url_for('mfa_disable') }}"
onsubmit="return confirm('Disable two-factor authentication for your account?')">
<button class="btn btn-danger" type="submit">Disable MFA</button>
</form>
{% else %}
<p>Protect your account with a one-time code from an authenticator app (Google Authenticator, Authy, Microsoft Authenticator…).</p>
<a class="btn btn-primary" href="{{ url_for('mfa_setup') }}">Enable MFA</a>
{% endif %}
</section>
</div>
<!-- ======================= Automatic send time ======================= -->
<section class="card">
<h2>Automatic e-mail send time</h2>
<p class="muted">The birthday e-mails are sent automatically every day at this time.</p>
<form method="post" action="{{ url_for('save_send_time') }}" class="entry-form">
<label>Send time
<input type="time" name="send_time" value="{{ send_time }}" required>
</label>
<button class="btn btn-primary" type="submit">Save send time</button>
</form>
</section>
<!-- ======================= E-mail log ======================= -->
<section class="card">
<h2>E-mail log</h2>
{% if log %}
<div class="table-wrap log-wrap">
<table>
<thead><tr><th>Date &amp; time</th><th>Recipient</th><th>E-mail address</th><th>Subject</th><th>Status</th></tr></thead>
<tbody>
{% for l in log %}
<tr>
<td class="nowrap">{{ l.sent_at }}</td>
<td>{{ l.recipient_name }}</td>
<td>{{ l.recipient_email }}</td>
<td>{{ l.subject }}</td>
<td>
<span class="pill {{ 'pill-ok' if l.status == 'Sent' else 'pill-bad' }}"
{% if l.detail %}title="{{ l.detail }}"{% endif %}>{{ l.status }}</span>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p class="muted">No e-mails have been sent yet.</p>
{% endif %}
</section>
<!-- ======================= Images ======================= -->
<section class="card">
<h2>Images</h2>
<p class="muted">Upload one or more images (15 MB total per upload). Each image shows the ready-to-use
<code>&lt;img&gt;</code> command — copy it into a template and the image is embedded inline in the e-mail when it is sent.</p>
<form method="post" action="{{ url_for('upload_image') }}" enctype="multipart/form-data" class="entry-form">
<input type="file" name="images" accept=".png,.jpg,.jpeg,.gif,.webp" multiple required>
<button class="btn btn-primary" type="submit">Upload image(s)</button>
</form>
{% if images %}
<div class="image-grid">
{% for img in images %}
<div class="image-tile">
<img src="{{ url_for('serve_upload', fname=img) }}" alt="{{ img }}">
<div class="copy-row">
<input type="text" readonly class="copy-input" value='<img src="/uploads/{{ img }}">'
onclick="this.select()">
<button type="button" class="btn btn-ghost btn-sm"
onclick="navigator.clipboard.writeText(this.previousElementSibling.value);this.textContent='Copied!';setTimeout(()=>this.textContent='Copy',1500)">Copy</button>
</div>
<form method="post" action="{{ url_for('delete_image', fname=img) }}"
onsubmit="return confirm('Delete this image?')">
<button class="btn btn-danger btn-sm" type="submit">Delete</button>
</form>
</div>
{% endfor %}
</div>
{% endif %}
</section>
<!-- ======================= Template zones ======================= -->
<div class="two-col">
<section class="card tpl-zone">
<h2>E-mail Template Male</h2>
<form method="post" action="{{ url_for('save_template') }}" class="stack-form">
<input type="hidden" name="gender" value="Male">
<label>Subject<input type="text" name="subject" value="{{ tpl_male.subject }}"></label>
<label>Body (HTML)
<textarea name="body" rows="10">{{ tpl_male.body }}</textarea>
</label>
<p class="muted small">Placeholders: <code>{first_name}</code> <code>{last_name}</code> <code>{age}</code> — insert images with <code>&lt;img src="/uploads/…"&gt;</code></p>
<button class="btn btn-primary" type="submit">Save Male template</button>
</form>
</section>
<section class="card tpl-zone">
<h2>E-Mail Template Female</h2>
<form method="post" action="{{ url_for('save_template') }}" class="stack-form">
<input type="hidden" name="gender" value="Female">
<label>Subject<input type="text" name="subject" value="{{ tpl_female.subject }}"></label>
<label>Body (HTML)
<textarea name="body" rows="10">{{ tpl_female.body }}</textarea>
</label>
<p class="muted small">Placeholders: <code>{first_name}</code> <code>{last_name}</code> <code>{age}</code> — insert images with <code>&lt;img src="/uploads/…"&gt;</code></p>
<button class="btn btn-primary" type="submit">Save Female template</button>
</form>
</section>
</div>
{% endblock %}