Add proper email notifications

This commit is contained in:
2026-05-14 23:19:50 +03:00
parent fe62575790
commit 9e16b78793
34 changed files with 1313 additions and 83 deletions

View File

@@ -0,0 +1,44 @@
{% extends "base.html" %}
{% block title %}Close your hamprint account{% endblock %}
{% block content %}
<div class="max-w-md mx-auto py-8">
<div class="bg-white border border-red-200 rounded-lg p-8 shadow-sm">
<h1 class="text-2xl font-bold tracking-tight text-red-700">Close your account</h1>
<p class="text-slate-700 mt-2 text-sm">
Signed in as
<span class="font-medium">{{ user.email|default:user.get_username }}</span>.
This action permanently deletes your account.
</p>
<div class="mt-4 rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-900">
<p class="font-semibold">There is no undo.</p>
<ul class="mt-2 list-disc pl-5 space-y-1">
<li>Your user row is deleted from the database.</li>
<li>
{% if submission_count == 0 %}
You don't have any prints in the system right now -- nothing else to remove.
{% elif submission_count == 1 %}
Your <strong>1</strong> print is deleted along with your account, including any uploaded STL.
{% else %}
All <strong>{{ submission_count }}</strong> of your prints are deleted along with your account, including any uploaded STLs.
{% endif %}
</li>
<li>Any active queue items are cancelled. Operators won't be able to contact you afterwards.</li>
</ul>
</div>
<form method="post" class="mt-6">
{% csrf_token %}
<button type="submit" class="w-full px-4 py-3 rounded-md bg-red-600 text-white hover:bg-red-700 font-medium">
Yes, delete my account permanently
</button>
</form>
<div class="mt-4 text-center">
<a href="{% url 'dashboard:my_prints' %}" class="text-sm text-slate-600 hover:underline">← Cancel, take me back</a>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,27 @@
{% extends "base.html" %}
{% block title %}Sign out — hamprint{% endblock %}
{% block content %}
<div class="max-w-md mx-auto py-8">
<div class="bg-white border border-slate-200 rounded-lg p-8 shadow-sm">
<h1 class="text-2xl font-bold tracking-tight">Sign out?</h1>
<p class="text-slate-600 mt-2 text-sm">
You're signed in as
<span class="font-medium">{{ user.email|default:user.get_username }}</span>.
Your prints stay on the dashboard either way -- you can come back any time.
</p>
<form method="post" action="{% url 'account_logout' %}" class="mt-6">
{% csrf_token %}
<button type="submit" class="w-full px-4 py-3 rounded-md bg-amber-500 text-white hover:bg-amber-600 font-medium">
Sign me out
</button>
</form>
<div class="mt-4 text-center">
<a href="{% url 'dashboard:my_prints' %}" class="text-sm text-slate-600 hover:underline">← Back to my prints</a>
</div>
</div>
</div>
{% endblock %}

View File

@@ -44,6 +44,26 @@
</nav>
<main class="mx-auto max-w-6xl px-4 py-8">
{% if messages %}
{% comment %}
One styled card per Django messages.add_message() call. The text is
rendered via {{ message|safe }} so that callers that built their
string with django.utils.html.format_html() can include <a>/<strong>
markup (variables are auto-escaped by format_html).
{% endcomment %}
<div class="mb-6 space-y-2">
{% for message in messages %}
<div class="px-4 py-3 rounded-md border text-sm
{% if 'success' in message.tags %}border-emerald-200 bg-emerald-50 text-emerald-900
{% elif 'error' in message.tags %}border-red-200 bg-red-50 text-red-900
{% elif 'warning' in message.tags %}border-amber-200 bg-amber-50 text-amber-900
{% else %}border-slate-200 bg-slate-50 text-slate-700{% endif %}">
{{ message|safe }}
</div>
{% endfor %}
</div>
{% endif %}
{% block content %}{% endblock %}
</main>

View File

@@ -80,6 +80,11 @@
<div class="mt-6 flex items-center justify-between text-sm">
<a href="{% url 'submissions:create' %}" class="text-amber-700 hover:underline font-medium">+ Submit another print</a>
<a href="{% url 'account_logout' %}" class="text-slate-500 hover:underline">Sign out</a>
<div class="flex items-center gap-4">
{% if not user.is_staff %}
<a href="{% url 'accounts:close' %}" class="text-red-600 hover:underline">Close account</a>
{% endif %}
<a href="{% url 'account_logout' %}" class="text-slate-500 hover:underline">Sign out</a>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,70 @@
{# Base email shell. Child templates fill {% block body %}{% endblock %}. #}
{# Inline styles only -- most clients strip <style> tags or block CDNs. #}
{# Table-based layout -- Outlook/Windows Mail still rely on it for spacing. #}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="light">
<meta name="supported-color-schemes" content="light">
<title>hamprint</title>
</head>
<body style="margin:0; padding:0; background-color:#f8fafc; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,'Helvetica Neue',Arial,sans-serif; color:#0f172a; -webkit-font-smoothing:antialiased;">
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="background-color:#f8fafc;">
<tr>
<td align="center" style="padding:32px 16px;">
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="560" style="max-width:560px; width:100%; background-color:#ffffff; border:1px solid #e2e8f0; border-radius:8px; box-shadow:0 1px 2px rgba(15,23,42,0.04);">
<!-- Header -->
<tr>
<td style="padding:20px 28px; border-bottom:1px solid #e2e8f0;">
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
<tr>
<td style="padding-right:10px;">
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="32" height="32" style="background-color:#f59e0b; border-radius:6px;">
<tr>
<td align="center" valign="middle" height="32" style="color:#ffffff; font-weight:700; font-size:18px; line-height:1; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">h</td>
</tr>
</table>
</td>
<td style="vertical-align:middle;">
<span style="font-weight:700; font-size:18px; color:#0f172a; letter-spacing:-0.01em;">hamprint</span>
<span style="font-size:12px; color:#64748b; margin-left:4px;">· hamlab.lt</span>
</td>
</tr>
</table>
</td>
</tr>
<!-- Body -->
<tr>
<td style="padding:28px;">
{% block body %}{% endblock %}
</td>
</tr>
<!-- Footer -->
<tr>
<td style="padding:16px 28px; border-top:1px solid #e2e8f0; background-color:#f8fafc; border-bottom-left-radius:8px; border-bottom-right-radius:8px;">
<p style="margin:0; font-size:12px; color:#64748b; text-align:center;">
A community service of <a href="https://hamlab.lt" style="color:#475569; font-weight:500; text-decoration:none;">hamlab.lt</a>.
</p>
</td>
</tr>
</table>
<!-- Plain-text footnote that still degrades nicely in dark-mode clients -->
<p style="margin:16px 0 0 0; font-size:12px; color:#94a3b8; text-align:center; max-width:560px;">
You're receiving this because you submitted a print at hamprint.
</p>
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,39 @@
{% extends "emails/_base.html" %}
{% block body %}
<h1 style="margin:0 0 12px 0; font-size:22px; font-weight:700; color:#0f172a; letter-spacing:-0.01em;">Confirm your submission</h1>
<p style="margin:0 0 18px 0; color:#334155; font-size:15px; line-height:1.55;">
You submitted a 3D print to hamlab.lt. Your codename is:
</p>
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="margin:0 0 22px 0;">
<tr>
<td style="padding:12px 16px; background-color:#fef3c7; border-radius:6px; font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:18px; font-weight:700; color:#92400e;">
{{ submission.slug }}
</td>
</tr>
</table>
<p style="margin:0 0 24px 0; color:#334155; font-size:15px; line-height:1.55;">
To put it in the queue, click the button below within <strong style="color:#0f172a;">24 hours</strong>. Otherwise the submission (and any uploaded <span style="font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;">.stl</span>) is deleted automatically.
</p>
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:0 0 24px 0;">
<tr>
<td style="background-color:#f59e0b; border-radius:6px;">
<a href="{{ confirm_url }}" style="display:inline-block; padding:12px 24px; color:#ffffff; font-weight:600; font-size:15px; text-decoration:none; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
Confirm my submission
</a>
</td>
</tr>
</table>
<p style="margin:0 0 4px 0; font-size:13px; color:#64748b;">Or copy this link into your browser:</p>
<p style="margin:0 0 24px 0; font-size:13px; color:#475569; word-break:break-all; font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;">{{ confirm_url }}</p>
<hr style="margin:0 0 18px 0; border:none; border-top:1px solid #e2e8f0;">
<p style="margin:0; font-size:13px; color:#64748b; line-height:1.55;">
If you didn't submit this, you can safely ignore the email — nothing happens until you click the link.
</p>
{% endblock %}

View File

@@ -0,0 +1,16 @@
Hi,
You submitted a 3D print to hamlab.lt. Your codename is:
{{ submission.slug }}
To put it in the queue, click the link below within 24 hours. If you don't,
the submission (and any uploaded .stl) will be deleted automatically.
{{ confirm_url }}
If you didn't submit this, you can safely ignore this email -- nothing
happens until you click the link.
— hamprint
{{ site_url }}

View File

@@ -0,0 +1 @@
Confirm your hamprint submission: {{ submission.slug }}

View File

@@ -0,0 +1,55 @@
{% extends "emails/_base.html" %}
{% block body %}
<h1 style="margin:0 0 12px 0; font-size:22px; font-weight:700; color:#0f172a; letter-spacing:-0.01em;">Status update</h1>
<p style="margin:0 0 16px 0; color:#334155; font-size:15px; line-height:1.55;">
Your submission <strong style="font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; color:#92400e; font-weight:700;">{{ submission.slug }}</strong> has moved to:
</p>
{% comment %}
Status pill -- per-status hex colours from `Submission.STATUS_EMAIL_COLORS`.
Wrapped in a table so Outlook respects padding + border-radius.
{% endcomment %}
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:0 0 20px 0;">
<tr>
<td style="padding:6px 14px; background-color:{{ submission.status_email_style.bg }}; border-radius:9999px;">
<span style="color:{{ submission.status_email_style.fg }}; font-weight:600; font-size:14px; letter-spacing:0.01em;">
{{ submission.get_status_display }}
</span>
</td>
</tr>
</table>
{% if previous_status %}
<p style="margin:0 0 20px 0; font-size:13px; color:#64748b;">
Previously: <span style="color:#475569;">{{ previous_status }}</span>
</p>
{% endif %}
{% if submission.operator_notes %}
<table role="presentation" cellpadding="0" cellspacing="0" border="0" width="100%" style="margin:0 0 24px 0;">
<tr>
<td style="padding:16px; background-color:#f8fafc; border-left:3px solid #f59e0b; border-radius:0 4px 4px 0;">
<p style="margin:0 0 6px 0; font-size:11px; font-weight:600; color:#64748b; text-transform:uppercase; letter-spacing:0.06em;">
Note from the operator
</p>
<p style="margin:0; color:#334155; font-size:14px; line-height:1.55; white-space:pre-line;">{{ submission.operator_notes }}</p>
</td>
</tr>
</table>
{% endif %}
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
<tr>
<td style="background-color:#f59e0b; border-radius:6px;">
<a href="{{ detail_url }}" style="display:inline-block; padding:12px 24px; color:#ffffff; font-weight:600; font-size:15px; text-decoration:none; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
View submission
</a>
</td>
</tr>
</table>
<p style="margin:18px 0 0 0; font-size:13px; color:#64748b;">
Direct link: <span style="color:#475569; word-break:break-all; font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;">{{ detail_url }}</span>
</p>
{% endblock %}

View File

@@ -0,0 +1,16 @@
Hi,
Your hamprint submission "{{ submission.slug }}" has moved to:
{{ submission.get_status_display }}{% if previous_status %} (was: {{ previous_status }}){% endif %}
{% if submission.operator_notes %}A note from the operator:
{{ submission.operator_notes }}
{% endif %}You can see the latest state at:
{{ detail_url }}
— hamprint
{{ site_url }}

View File

@@ -0,0 +1 @@
hamprint update: {{ submission.slug }} is now {{ submission.get_status_display }}

View File

@@ -0,0 +1,37 @@
{% extends "emails/_base.html" %}
{% block body %}
<h1 style="margin:0 0 12px 0; font-size:22px; font-weight:700; color:#0f172a; letter-spacing:-0.01em;">Cleared auto-checks</h1>
<p style="margin:0 0 16px 0; color:#334155; font-size:15px; line-height:1.55;">
Your submission <strong style="font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; color:#92400e; font-weight:700;">{{ submission.slug }}</strong> passed our automated checks (size, format, host allow-list) and is now waiting for an operator to take a manual look.
</p>
{# Pill colours come from `Submission.STATUS_EMAIL_COLORS` -- same per-status palette as the website badge. #}
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin:0 0 20px 0;">
<tr>
<td style="padding:6px 14px; background-color:{{ submission.status_email_style.bg }}; border-radius:9999px;">
<span style="color:{{ submission.status_email_style.fg }}; font-weight:600; font-size:14px; letter-spacing:0.01em;">
{{ submission.get_status_display }}
</span>
</td>
</tr>
</table>
<p style="margin:0 0 24px 0; color:#334155; font-size:15px; line-height:1.55;">
If the operator is happy with the print job, it moves into the print queue shortly after &mdash; and we'll email you again once that happens. You don't need to do anything right now.
</p>
<table role="presentation" cellpadding="0" cellspacing="0" border="0">
<tr>
<td style="background-color:#f59e0b; border-radius:6px;">
<a href="{{ detail_url }}" style="display:inline-block; padding:12px 24px; color:#ffffff; font-weight:600; font-size:15px; text-decoration:none; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
View submission
</a>
</td>
</tr>
</table>
<p style="margin:18px 0 0 0; font-size:13px; color:#64748b;">
Direct link: <span style="color:#475569; word-break:break-all; font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;">{{ detail_url }}</span>
</p>
{% endblock %}

View File

@@ -0,0 +1,18 @@
Hi,
Good news -- your hamprint submission "{{ submission.slug }}" passed the
automated checks (size, format, host allow-list) and is now waiting for an
operator to take a manual look.
Codename : {{ submission.slug }}
Status : Verifying
If the operator is happy with the print job, it moves into the print queue
shortly after and we'll email you again. You don't need to do anything
right now.
You can also check on it here:
{{ detail_url }}
— hamprint
{{ site_url }}

View File

@@ -0,0 +1 @@
hamprint: {{ submission.slug }} cleared auto-checks, awaiting operator review