Add Django site, Docker packaging, and beta/prod Gitea deploys.
Deploy Beta / unit-tests (push) Successful in 9s
Deploy Beta / docker (push) Successful in 17s
Deploy Beta / deploy-beta (push) Successful in 2m31s

Unignore site/ (was blocked by mkdocs /site rule), add compose/Docker/uv tooling, and split deploys so push to main goes to beta while prod stays manual.
This commit is contained in:
2026-08-08 07:32:55 -05:00
parent 7dca98bbf6
commit 1f7d78de64
204 changed files with 21662 additions and 70 deletions
+74
View File
@@ -0,0 +1,74 @@
from datetime import timedelta
from django.contrib.auth.decorators import login_required
from django.db.models import Count
from django.shortcuts import render
from django.utils import timezone
from analytics.models import Attribution, UTMVisit
def _bar_pct(rows, key="count"):
max_count = max((row[key] for row in rows), default=1) or 1
for row in rows:
row["bar_pct"] = max(12, int(100 * row[key] / max_count))
return rows
@login_required
def report(request):
since_30d = timezone.now() - timedelta(days=30)
visits_last_30_days = UTMVisit.objects.filter(created_at__gte=since_30d).count()
visits_by_source = _bar_pct(
list(
UTMVisit.objects.values("utm_source")
.annotate(count=Count("id"))
.order_by("-count")[:20]
)
)
visits_by_combo = list(
UTMVisit.objects.values("utm_source", "utm_medium", "utm_campaign")
.annotate(count=Count("id"))
.order_by("-count")[:50]
)
top_visit = visits_by_source[0] if visits_by_source else None
top_visit_campaign = (
UTMVisit.objects.exclude(utm_campaign="")
.values("utm_campaign")
.annotate(count=Count("id"))
.order_by("-count")
.first()
)
leads_by_source = _bar_pct(
list(
Attribution.objects.values("utm_source")
.annotate(count=Count("id"))
.order_by("-count")[:20]
)
)
leads_by_combo = list(
Attribution.objects.values("utm_source", "utm_medium", "utm_campaign")
.annotate(count=Count("id"))
.order_by("-count")[:50]
)
recent_visits = UTMVisit.objects.all()[:25]
return render(
request,
"analytics/report.html",
{
"visits_last_30_days": visits_last_30_days,
"total_visits": UTMVisit.objects.count(),
"total_attributed": Attribution.objects.count(),
"top_source": (top_visit or {}).get("utm_source") or "(direct)",
"top_campaign": (top_visit_campaign or {}).get("utm_campaign") or "",
"visits_by_source": visits_by_source,
"visits_by_combo": visits_by_combo,
"leads_by_source": leads_by_source,
"leads_by_combo": leads_by_combo,
"recent_visits": recent_visits,
},
)