Ship College Craft public site and point CI deploys at college_craft.
Deploy Beta / unit-tests (push) Successful in 21s
Deploy Beta / docker (push) Successful in 26s
Deploy Beta / deploy-beta (push) Successful in 6m25s

Replaces template branding with College Craft pages, assets, and copy, and
matches Gitea deploy workflows to the server-infra catalog name and master
branch so beta deploys actually run.

Closes #1
This commit is contained in:
2026-09-02 09:42:43 -05:00
parent b62357c8be
commit b46e192138
191 changed files with 2404 additions and 2041 deletions
+125 -51
View File
@@ -17,8 +17,9 @@ from contacts.consent import (
set_channel_preferences,
unsubscribe_all,
)
from public.forms import ContactForm, NotifyForm
from public.forms import CareersForm, ContactForm, NotifyForm
from public.notifications import notify_admins_of_contact_form
from public.testimonials_data import FEATURED_TESTIMONIALS, TESTIMONIALS
def _public_site_base(request) -> str:
@@ -28,14 +29,89 @@ def _public_site_base(request) -> str:
return request.build_absolute_uri("/").rstrip("/")
def _postal_from_form(data: dict) -> dict:
return Contact.make_postal_address(
line1=data.get("address_line1") or "",
line2=data.get("address_line2") or "",
city=data.get("address_city") or "",
state=data.get("address_state") or "",
zip_code=data.get("address_zip") or "",
)
def _create_lead(
request,
*,
data: dict,
source: str,
body: str,
consent_reason: str,
):
postal = _postal_from_form(data)
submitted_email = data["email"].lower()
contact_obj, _created, match_reason = upsert_contact(
email=submitted_email,
first_name=data["first_name"],
last_name=data.get("last_name") or "",
phone=data.get("phone") or "",
postal_address=postal if Contact.postal_address_has_content(postal) else None,
source=source,
)
ConsentRecord.objects.update_or_create(
contact=contact_obj,
channel=Channel.EMAIL,
defaults={"opted_in": True, "reason": consent_reason},
)
if (data.get("phone") or "").strip():
ConsentRecord.objects.update_or_create(
contact=contact_obj,
channel=Channel.SMS,
defaults={"opted_in": True, "reason": consent_reason},
)
if Contact.postal_address_has_content(postal):
ConsentRecord.objects.get_or_create(
contact=contact_obj,
channel=Channel.POSTCARD,
defaults={"opted_in": True, "reason": consent_reason},
)
if (
match_reason in {"phone", "address"}
and (contact_obj.email or "").lower() != submitted_email
):
body = (
f"Submitted email: {submitted_email} "
f"(merged by {match_reason} with "
f"{contact_obj.email or 'existing contact'})\n\n{body}"
).strip()
lead = Lead.objects.create(
contact=contact_obj,
message=body,
status=Lead.Status.NEW,
)
attribute_lead_from_request(request, lead)
return lead
def home(request):
return render(request, "public/home.html")
return render(
request,
"public/home.html",
{"featured_testimonials": FEATURED_TESTIMONIALS},
)
def about(request):
return render(request, "public/about.html")
def services(request):
return render(request, "public/services.html")
def testimonials(request):
return render(request, "public/testimonials.html", {"testimonials": TESTIMONIALS})
def terms(request):
return render(request, "public/terms.html")
@@ -64,7 +140,10 @@ def sitemap_xml(request):
paths = [
("public:home", "1.0", "weekly"),
("public:about", "0.8", "monthly"),
("public:services", "0.8", "monthly"),
("public:testimonials", "0.7", "monthly"),
("public:contact", "0.9", "monthly"),
("public:careers", "0.6", "monthly"),
("public:terms", "0.5", "yearly"),
]
from django.apps import apps as django_apps
@@ -95,61 +174,18 @@ def contact(request):
form = ContactForm(request.POST)
if form.is_valid():
data = form.cleaned_data
postal = Contact.make_postal_address(
line1=data.get("address_line1") or "",
line2=data.get("address_line2") or "",
city=data.get("address_city") or "",
state=data.get("address_state") or "",
zip_code=data.get("address_zip") or "",
)
submitted_email = data["email"].lower()
contact_obj, _created, match_reason = upsert_contact(
email=submitted_email,
first_name=data["first_name"],
last_name=data.get("last_name") or "",
phone=data.get("phone") or "",
postal_address=postal
if Contact.postal_address_has_content(postal)
else None,
source=Contact.Source.CONTACT_FORM,
)
ConsentRecord.objects.update_or_create(
contact=contact_obj,
channel=Channel.EMAIL,
defaults={"opted_in": True, "reason": "contact_form"},
)
if (data.get("phone") or "").strip():
ConsentRecord.objects.update_or_create(
contact=contact_obj,
channel=Channel.SMS,
defaults={"opted_in": True, "reason": "contact_form"},
)
if Contact.postal_address_has_content(postal):
ConsentRecord.objects.get_or_create(
contact=contact_obj,
channel=Channel.POSTCARD,
defaults={"opted_in": True, "reason": "contact_form"},
)
interest = data.get("interest") or ""
interest_label = dict(ContactForm.INTEREST_CHOICES).get(interest, interest)
body = data.get("message") or ""
if interest_label:
body = f"Interest: {interest_label}\n\n{body}".strip()
if (
match_reason in {"phone", "address"}
and (contact_obj.email or "").lower() != submitted_email
):
body = (
f"Submitted email: {submitted_email} "
f"(merged by {match_reason} with "
f"{contact_obj.email or 'existing contact'})\n\n{body}"
).strip()
lead = Lead.objects.create(
contact=contact_obj,
message=body,
status=Lead.Status.NEW,
lead = _create_lead(
request,
data=data,
source=Contact.Source.CONTACT_FORM,
body=body,
consent_reason="contact_form",
)
attribute_lead_from_request(request, lead)
notify_admins_of_contact_form(lead)
messages.success(request, "Thanks — we will be in touch soon.")
return redirect(f"{reverse('public:contact')}?sent=1")
@@ -158,6 +194,44 @@ def contact(request):
return render(request, "public/contact.html", {"form": form})
@require_http_methods(["GET", "POST"])
def careers(request):
if request.method == "POST":
form = CareersForm(request.POST)
if form.is_valid():
data = form.cleaned_data
position_labels = [
dict(CareersForm.POSITION_CHOICES).get(value, value)
for value in data.get("positions") or []
]
body_parts = [
"Interest: Employment application",
f"Positions: {', '.join(position_labels) or '(none)'}",
f"Start: {data.get('start_date') or '(not specified)'}",
f"Driver's license: {data.get('drivers_license') or '(not specified)'}",
f"Transportation: {data.get('has_vehicle') or '(not specified)'}",
"",
data.get("qualifications") or "",
]
lead = _create_lead(
request,
data=data,
source=Contact.Source.CAREERS,
body="\n".join(body_parts).strip(),
consent_reason="careers_form",
)
notify_admins_of_contact_form(
lead, subject_prefix="New employment application"
)
messages.success(
request, "Thanks — we received your application and will follow up."
)
return redirect(f"{reverse('public:careers')}?sent=1")
else:
form = CareersForm()
return render(request, "public/careers.html", {"form": form})
@require_http_methods(["GET", "POST"])
def under_construction(request):
"""Direct route (also used by middleware). Accepts notify-me emails."""