Stand up Print Forge as a 3D-printed toy shop with color variants and printer photography.

Replaces the client_site template branding, adds shop/shipping, and points beta CI at master for easy deploy.

Closes #1
This commit is contained in:
2026-09-06 08:28:04 -05:00
parent 8a97e3fbe2
commit b2029b6c0f
336 changed files with 9241 additions and 2537 deletions
+3 -1
View File
@@ -10,7 +10,9 @@
<div style="display:flex;gap:8px;flex-wrap:wrap">
<a class="btn btn-ghost btn-sm" href="{% url 'contacts:import' %}">Import CSV / Excel</a>
<a class="btn btn-ghost btn-sm" href="{% url 'contacts:create' %}">New contact</a>
<a class="btn btn-primary btn-sm" href="{% url 'messaging:campaign_list' %}">New campaign</a>
{% if 'email_sms' in enabled_features %}
<a class="btn btn-primary btn-sm" href="{% url 'email_sms:campaign_list' %}">New campaign</a>
{% endif %}
</div>
</div>
+16
View File
@@ -219,3 +219,19 @@ class PortalCreateMatchPromptTests(TestCase):
self.existing.refresh_from_db()
self.assertEqual(self.existing.first_name, "Alexander")
self.assertIn("alt@example.com", self.existing.notes)
class ContactListTests(TestCase):
def setUp(self):
User = get_user_model()
self.user = User.objects.create_user(
username="lister", password="test-pass-123"
)
self.client = Client()
self.client.login(username="lister", password="test-pass-123")
def test_list_renders_and_links_campaigns(self):
response = self.client.get(reverse("contacts:list"))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "Mailing list")
self.assertContains(response, reverse("email_sms:campaign_list"))