From 0a9130829591ec074ff85f5fd0af40feb050619d Mon Sep 17 00:00:00 2001 From: Ryan Westfall Date: Tue, 1 Sep 2026 13:21:41 -0500 Subject: [PATCH] Show campaign QR codes for email as well as postcard. Closes #13. --- .../templates/messaging/_utm_link_panel.html | 6 +++++- site/messaging/tests.py | 5 +++++ site/monica_site/static/css/portal.css | 3 +++ site/monica_site/static/js/campaign-utm.js | 11 +++++++++-- 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/site/messaging/templates/messaging/_utm_link_panel.html b/site/messaging/templates/messaging/_utm_link_panel.html index e952737..43f70cb 100644 --- a/site/messaging/templates/messaging/_utm_link_panel.html +++ b/site/messaging/templates/messaging/_utm_link_panel.html @@ -13,6 +13,7 @@ Auto-added to the email as a styled link. Updates as you type the campaign name. utm_medium=email · utm_campaign matches the name. Recipients tap a short piha.li link that redirects to this URL. + QR below encodes the same short link.

-

+

+ diff --git a/site/messaging/tests.py b/site/messaging/tests.py index 538c38e..ec00f8f 100644 --- a/site/messaging/tests.py +++ b/site/messaging/tests.py @@ -1554,6 +1554,8 @@ class CampaignUtmLinkTests(TestCase): self.assertEqual(response.status_code, 200) self.assertContains(response, "Tracked site link") self.assertContains(response, "campaign-utm.js") + self.assertContains(response, "qrcode.min.js") + self.assertContains(response, "data-utm-qr") self.assertContains(response, "utm_campaign") self.assertContains(response, reverse("messaging:campaign_short_link")) @@ -1573,6 +1575,9 @@ class CampaignUtmLinkTests(TestCase): self.assertEqual(response.status_code, 200) self.assertContains(response, "utm_campaign=spring-seller-tips") self.assertContains(response, "utm_medium=email") + self.assertContains(response, "qrcode.min.js") + self.assertContains(response, "data-utm-qr") + self.assertContains(response, "QR below encodes the same short link") def test_sms_replaces_existing_short_url(self): from messaging.services import ensure_campaign_utm_in_text diff --git a/site/monica_site/static/css/portal.css b/site/monica_site/static/css/portal.css index d33f1db..67705e4 100644 --- a/site/monica_site/static/css/portal.css +++ b/site/monica_site/static/css/portal.css @@ -718,6 +718,9 @@ body.portal { flex-wrap: wrap; margin-top: 12px; } +.utm-qr[hidden] { + display: none !important; +} .utm-qr canvas { display: block; border: 1px solid var(--monica-border); diff --git a/site/monica_site/static/js/campaign-utm.js b/site/monica_site/static/js/campaign-utm.js index 2576c3a..78aa29f 100644 --- a/site/monica_site/static/js/campaign-utm.js +++ b/site/monica_site/static/js/campaign-utm.js @@ -181,12 +181,19 @@ function paint(url, inject) { var ch = medium(); + var showQr = ch === "email" || ch === "postcard"; if (urlEl) urlEl.textContent = url; - if (qrWrap) qrWrap.hidden = ch !== "postcard"; + if (qrWrap) qrWrap.hidden = !showQr; if (smsHint) smsHint.hidden = ch !== "sms"; if (emailHint) emailHint.hidden = ch !== "email"; if (postcardHint) postcardHint.hidden = ch !== "postcard"; - if (ch === "postcard" && canvas) { + panel.querySelectorAll("[data-utm-qr-email-hint]").forEach(function (el) { + el.hidden = ch !== "email"; + }); + panel.querySelectorAll("[data-utm-qr-postcard-hint]").forEach(function (el) { + el.hidden = ch !== "postcard"; + }); + if (showQr && canvas) { renderQr(canvas, url).catch(function () {}); } if (inject && typeof opts.onUrlChange === "function") { -- 2.54.0