Add proper email notifications
This commit is contained in:
@@ -8,6 +8,7 @@ from __future__ import annotations
|
||||
|
||||
import uuid
|
||||
|
||||
import namesgenerator
|
||||
from django.conf import settings
|
||||
from django.core.validators import FileExtensionValidator
|
||||
from django.db import models
|
||||
@@ -178,6 +179,29 @@ class Submission(models.Model):
|
||||
# dashboard index so post-submit redirects always land somewhere real.
|
||||
return reverse("dashboard:index")
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""Auto-generate `slug` on first save so any creation path -- admin,
|
||||
`SubmitView`, fixtures, `objects.create()` -- gets a Docker-style
|
||||
codename without callers having to remember to set one."""
|
||||
if not self.slug:
|
||||
self.slug = self._generate_unique_slug()
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def _generate_unique_slug(cls, max_attempts: int = 16) -> str:
|
||||
"""`namesgenerator.get_random_name` + collision retries in Python
|
||||
(rather than a DB-side loop) so the rare collision path stays
|
||||
observable. If the surrounding transaction still loses a race with
|
||||
a concurrent insert, the DB's `unique=True` constraint fires an
|
||||
`IntegrityError` and the caller can retry."""
|
||||
for _ in range(max_attempts):
|
||||
candidate = namesgenerator.get_random_name()
|
||||
if not cls.objects.filter(slug=candidate).exists():
|
||||
return candidate
|
||||
# Fall through: extremely unlikely with the size of namesgenerator's
|
||||
# adjective/surname space.
|
||||
return namesgenerator.get_random_name()
|
||||
|
||||
# --- presentation helpers (consumed by dashboard templates) -------------
|
||||
|
||||
SOURCE_LABEL = {
|
||||
@@ -201,6 +225,20 @@ class Submission(models.Model):
|
||||
Status.FAILED: "bg-red-100 text-red-800",
|
||||
}
|
||||
|
||||
# Same palette as STATUS_BADGE_CLASS but expressed as hex pairs because
|
||||
# email clients strip <style> blocks and don't load external CSS, so the
|
||||
# HTML email templates use inline `background-color` / `color`.
|
||||
STATUS_EMAIL_COLORS = {
|
||||
Status.IDENTIFYING: {"bg": "#fef3c7", "fg": "#92400e"}, # amber
|
||||
Status.PROCESSING: {"bg": "#f1f5f9", "fg": "#334155"}, # slate
|
||||
Status.VERIFYING: {"bg": "#ede9fe", "fg": "#5b21b6"}, # violet
|
||||
Status.QUEUED: {"bg": "#dbeafe", "fg": "#1e40af"}, # blue
|
||||
Status.PRINTING: {"bg": "#ffedd5", "fg": "#9a3412"}, # orange
|
||||
Status.COMPLETED: {"bg": "#d1fae5", "fg": "#065f46"}, # emerald
|
||||
Status.REJECTED: {"bg": "#fee2e2", "fg": "#991b1b"}, # red
|
||||
Status.FAILED: {"bg": "#fee2e2", "fg": "#991b1b"}, # red
|
||||
}
|
||||
|
||||
@property
|
||||
def source_label(self) -> str:
|
||||
return self.SOURCE_LABEL.get(self.source_type, self.source_type)
|
||||
@@ -208,3 +246,9 @@ class Submission(models.Model):
|
||||
@property
|
||||
def status_badge_class(self) -> str:
|
||||
return self.STATUS_BADGE_CLASS.get(self.status, "bg-slate-100 text-slate-700")
|
||||
|
||||
@property
|
||||
def status_email_style(self) -> dict:
|
||||
return self.STATUS_EMAIL_COLORS.get(
|
||||
self.status, {"bg": "#f1f5f9", "fg": "#334155"}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user