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
@@ -0,0 +1,67 @@
{% extends "portal_base.html" %}
{% block title %}Dashboard · Portal{% endblock %}
{% block topbar_title %}Dashboard{% endblock %}
{% block portal_content %}
<div class="stat-row">
<div class="stat-card">
<div class="label">New leads</div>
<div class="value">{{ lead_count }}</div>
</div>
<div class="stat-card">
<div class="label">Open pipeline</div>
<div class="value">{{ open_pipeline }}</div>
</div>
<div class="stat-card">
<div class="label">Mailing list</div>
<div class="value">{{ contact_count }}</div>
</div>
<div class="stat-card">
<div class="label">Scheduled posts</div>
<div class="value">{{ scheduled_posts }}</div>
</div>
</div>
<div class="split">
<div class="panel">
<div class="panel-h">
<h2>Recent leads</h2>
<a class="btn btn-sm btn-ghost" href="{% url 'leads:list' %}">View all</a>
</div>
<div class="panel-b" style="padding:0">
<table class="table">
<thead>
<tr><th>Name</th><th>Source</th><th>Status</th></tr>
</thead>
<tbody>
{% for lead in recent_leads %}
<tr>
<td><a href="{% url 'leads:detail' lead.pk %}">{{ lead.contact }}</a></td>
<td>{% if lead.attribution %}{{ lead.attribution.utm_source|default:"direct" }}{% if lead.attribution.utm_campaign %} / {{ lead.attribution.utm_campaign }}{% endif %}{% else %}—{% endif %}</td>
<td><span class="badge badge-{{ lead.status }}">{{ lead.get_status_display }}</span></td>
</tr>
{% empty %}
<tr><td colspan="3" class="empty-state">No leads yet.</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="panel">
<div class="panel-h">
<h2>Upcoming outreach</h2>
<a class="btn btn-sm btn-ghost" href="{% url 'messaging:campaign_list' %}">Compose</a>
</div>
<div class="panel-b">
{% for campaign in upcoming_campaigns %}
<p style="margin:0 0 12px;font-size:14px">
<strong><a href="{% url 'messaging:campaign_detail' campaign.pk %}">{{ campaign.name }}</a></strong>
— {{ campaign.get_channel_display }} · {{ campaign.get_status_display }}
{% if campaign.scheduled_for %} · {{ campaign.scheduled_for }}{% endif %}
</p>
{% empty %}
<p class="empty-state" style="margin:0">No campaigns yet.</p>
{% endfor %}
</div>
</div>
</div>
{% endblock %}