Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
9c2e7ba
Wrap current_plan in a list for now
dnass Jun 26, 2026
8ae47f8
Update heading buttons on org plan card
dnass Jun 26, 2026
7f9cf20
Redesign plan card
dnass Jun 26, 2026
be6ef2d
Set up new subscription management page structure
dnass Jun 26, 2026
9b26665
Pass all plans to plan card
dnass Jun 29, 2026
edc225f
Rename UpdateSubscription to UpdateSubscriptions
dnass Jun 29, 2026
12e87f3
Include subscription data, dates and costs in payment page context
dnass Jun 29, 2026
4df9a6a
Add tag icon
dnass Jun 29, 2026
3c88e70
Add subscription management cards to payment page
dnass Jun 29, 2026
42552ae
Just use base price for plan cost
dnass Jun 30, 2026
efdf312
Pass payment card and receipt emails to subscriptions page
dnass Jun 30, 2026
9dbae64
Reorganize CSS
dnass Jun 30, 2026
3349551
Show payment card and receipt emails on subscription page
dnass Jun 30, 2026
8274f61
Plan card fixes
dnass Jun 30, 2026
9e50d99
Pass recent payment data to subscription page
dnass Jun 30, 2026
fe5aac6
Use blocktrans
dnass Jun 30, 2026
272c68e
Revert UpdateSubscription view and payment template
dnass Jul 2, 2026
006c0d6
Set up new ManageSubscriptions view
dnass Jul 2, 2026
dceea83
Add update card form helper and view class
dnass Jul 2, 2026
ace882d
Redirect to subscriptions page
dnass Jul 2, 2026
aba9589
Add update card template and Stripe form JS
dnass Jul 2, 2026
7b8a390
Update links on plan card and org detail page
dnass Jul 2, 2026
3726c45
Add org name to update card template
dnass Jul 2, 2026
0bea174
Create modal layout template
dnass Jul 3, 2026
b0e967a
Use modal layout for update card template
dnass Jul 3, 2026
bac4e7a
More modal layout styles
dnass Jul 3, 2026
7cc6068
Make get_subscription_next_date a standalone function
dnass Jul 3, 2026
1e9eaa5
More modal layout helper classes
dnass Jul 3, 2026
2d1a61a
Add cancel subscription template and stub view
dnass Jul 3, 2026
b9a6942
Modal layout footer block
dnass Jul 3, 2026
9799563
Add customer service CTA
dnass Jul 3, 2026
1481d13
Add subscription frequency template and stub view
dnass Jul 3, 2026
2cddfa6
Add receipt email form
dnass Jul 3, 2026
c3734a6
Add receipts card template
dnass Jul 5, 2026
bb5a66c
Add payments list view
dnass Jul 5, 2026
2de5a2f
Add receipts card and update links to payments page
dnass Jul 5, 2026
af4bbab
Update modal layout headers
dnass Jul 5, 2026
a756184
Remove dummy data
dnass Jul 5, 2026
da98cee
Fix receipt pagination styles and charge links
dnass Jul 5, 2026
7161723
Add receipts card empty message
dnass Jul 6, 2026
ee84ccc
Filter charges to just the current org
dnass Jul 6, 2026
39da263
Show placeholder card for no subscriptions
dnass Jul 6, 2026
9ab011a
Pass through payment URL for upgrade button
dnass Jul 6, 2026
7fb59f8
Format and fix lint errors
dnass Jul 6, 2026
04a6d5f
Include org slug in subscription management views
dnass Jul 6, 2026
f3c782a
Query by subscription, not plan
dnass Jul 6, 2026
d9722d8
Rework cancel subscription view
dnass Jul 6, 2026
0c2e564
Show badge for cancelled subscriptions
dnass Jul 6, 2026
9942d23
Use organization.remove_subscription to cancel
dnass Jul 6, 2026
ec59582
Use subscription ID for subscription frequency link
dnass Jul 7, 2026
3e6c9d5
Add permissions check for PaymentsList view
dnass Jul 7, 2026
53dfacf
Pass all subscriptions to user detail view
dnass Jul 7, 2026
8682609
Update plan card layout and copy
dnass Jul 7, 2026
f2af46c
Query organization in UpdateSubscriptionFrequency view
dnass Jul 7, 2026
f464b80
Move subscription forms, views and templates to separate files
dnass Jul 7, 2026
a0256a1
Add URLs and views for user subscription pages
dnass Jul 7, 2026
5170e05
Fix import
dnass Jul 7, 2026
b989d0f
Build URLs in plan card
dnass Jul 7, 2026
ef9f2a2
Update user page subscription links and headings
dnass Jul 7, 2026
251d5f6
Use subject namespace in subscription template URLs
dnass Jul 7, 2026
bf04452
Fixes
dnass Jul 7, 2026
c0d193b
Namespace redirect urls
dnass Jul 7, 2026
c7028c3
Vary template copy by subject
dnass Jul 7, 2026
cf3aad4
Rename TS and CSS files to match templates
dnass Jul 7, 2026
b89d763
Remove unused imports
dnass Jul 7, 2026
597660e
Mobile styles and fixes
dnass Jul 7, 2026
0729935
Lint and format
dnass Jul 7, 2026
70c85c2
Use consistent color scheme for plan names
dnass Jul 7, 2026
8d33cb5
Remove unnecessary checks
dnass Jul 7, 2026
0cd7e70
Fixes for individual payment pages
allanlasser Jul 10, 2026
acbef2c
Fix card mocking in Stripe tests
allanlasser Jul 10, 2026
9da5b27
Updated method for getting card payment brand
dnass Jul 20, 2026
20e3bdc
Template fix
dnass Jul 22, 2026
154a5ed
Use new payment brand and last4 fields
dnass Jul 22, 2026
95de17a
Consolidate subscriptions module into payments
dnass Jul 22, 2026
58a646d
Throw an error if OrganizationPermissionMixin is used with a non-orga…
dnass Jul 22, 2026
be4b6ab
Adds a view to show payments summary across all organizations
allanlasser Jul 22, 2026
b339af8
Update organization URLs
allanlasser Jul 22, 2026
5e9625e
Update templates
allanlasser Jul 23, 2026
e5c99e5
Adds handling for removing a payment method
allanlasser Jul 23, 2026
d0d375b
Show navigation to view payment details for all orgs
allanlasser Jul 24, 2026
539b16d
Adds activity stream logging for staff management actions
allanlasser Jul 24, 2026
29e3738
Fix card access in templates
allanlasser Jul 24, 2026
416c704
Fix e2e tests
allanlasser Jul 24, 2026
e375777
Remove billing frequency change logic
allanlasser Jul 27, 2026
ed59dad
Fix upgrade button link
allanlasser Jul 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion config/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
OrganizationViewSet as FEOrganizationViewSet,
)
from squarelet.organizations.viewsets import ChargeViewSet, OrganizationViewSet
from squarelet.payments.views import PlanDetailView, PlanRedirectView
from squarelet.payments.views import PaymentsHubView, PlanDetailView, PlanRedirectView
from squarelet.users.fe_api.viewsets import UserViewSet as FEUserViewSet
from squarelet.users.views import (
LoginView,
Expand Down Expand Up @@ -66,6 +66,7 @@ def redirect_erh(request, path=""):
path("plans/<int:pk>/", PlanRedirectView.as_view(), name="plan_detail_id"),
path("plans/<slug:slug>/", PlanRedirectView.as_view(), name="plan_detail_slug"),
path("selectplan/", SelectPlanView.as_view(), name="select_plan"),
path("payments/", PaymentsHubView.as_view(), name="payments"),
# Django Admin, use {% url 'admin:index' %}
path(settings.ADMIN_URL, admin.site.urls),
# User management
Expand Down
18 changes: 9 additions & 9 deletions e2e/organizations.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ test.describe("Organization Viewing", () => {

test("does NOT see plan section", async ({ page }) => {
await page.goto("/organizations/e2e-public-org/");
await expect(page.locator("section#plan")).toHaveCount(0);
await expect(page.locator("section#billing")).toHaveCount(0);
});
});

Expand All @@ -112,7 +112,7 @@ test.describe("Organization Viewing", () => {

test("does NOT see plan section", async ({ page }) => {
await page.goto("/organizations/e2e-public-org/");
await expect(page.locator("section#plan")).toHaveCount(0);
await expect(page.locator("section#billing")).toHaveCount(0);
});

test("sees only admins in member list", async ({ page }) => {
Expand Down Expand Up @@ -141,7 +141,7 @@ test.describe("Organization Viewing", () => {

test("sees plan section", async ({ page }) => {
await page.goto("/organizations/e2e-public-org/");
await expect(page.locator("section#plan")).toBeVisible();
await expect(page.locator("section#billing")).toBeVisible();
});

test("sees all members in user list (not just admins)", async ({
Expand Down Expand Up @@ -204,13 +204,13 @@ test.describe("Organization Viewing", () => {

test("sees plan section", async ({ page }) => {
await page.goto("/organizations/e2e-public-org/");
await expect(page.locator("section#plan")).toBeVisible();
await expect(page.locator("section#billing")).toBeVisible();
});

test("sees button to change plans", async ({ page }) => {
test("sees button to upgrade plan", async ({ page }) => {
await page.goto("/organizations/e2e-public-org/");
await expect(
page.locator('a[href$="/organizations/e2e-public-org/payment/"]'),
page.locator('a.btn.premium[href*="/plans/"][href$="-organization/"]'),
).toBeVisible();
});
});
Expand Down Expand Up @@ -253,13 +253,13 @@ test.describe("Organization Viewing", () => {

test("sees plan section", async ({ page }) => {
await page.goto("/organizations/e2e-public-org/");
await expect(page.locator("section#plan")).toBeVisible();
await expect(page.locator("section#billing")).toBeVisible();
});

test("sees button to change plans", async ({ page }) => {
test("sees button to upgrade plan", async ({ page }) => {
await page.goto("/organizations/e2e-public-org/");
await expect(
page.locator('a[href$="/organizations/e2e-public-org/payment/"]'),
page.locator('a.btn.premium[href*="/plans/"][href$="-organization/"]'),
).toBeVisible();
});

Expand Down
96 changes: 96 additions & 0 deletions frontend/css/manage_subscriptions.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
.subscription-card {
width: 100%;
display: flex;
flex-direction: column;
gap: 0.5rem 1rem;
padding: 1rem;
}

.subscription-card h3 {
font-family: var(--font-sans, "Source Sans Pro");
font-size: var(--font-md, 1rem);
font-style: normal;
font-weight: 600;
line-height: var(--font-xl, 1.5rem);
margin: 0 0 auto;
}

.subscription-card .professional {
color: var(--blue-4);
}

.subscription-card .organization {
color: var(--purple-4);
}

.subscription-frequency {
display: flex;
flex-direction: row;
align-items: center;
gap: 0.25rem;
}

.subscription-row {
display: flex;
flex-wrap: wrap;
gap: 0.25rem 0;
justify-content: space-between;
align-items: center;
}

.subscription-group {
display: flex;
gap: 1rem;
}

@media (max-width: 28rem) {
.subscription-group {
flex: 1 0 100%;
}
}

.subscription-detail {
flex: 0 1 auto;
display: flex;
align-items: center;
gap: 0.5rem;
color: var(--gray-5);
fill: var(--gray-4);
}

.subscription-detail .icon {
display: inline-flex;
align-items: center;
width: var(--font-md, 0.75em);
height: var(--font-md, 0.75em);
}

.subscription-detail .emails :not(:last-child):after {
content: ",";
}

.account-row {
display: flex;
justify-content: space-between;
align-items: center;
gap: 1rem;
}

.remove-card-form {
margin: 0;
}

.account-card {
display: flex;
align-items: center;
gap: 0.5rem;
}

.account-card .icon {
display: flex;
align-items: center;
}

.account-card-brand {
text-transform: capitalize;
}
108 changes: 108 additions & 0 deletions frontend/css/modal_layout.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
.modal-layout {
box-sizing: border-box;
}

.modal-layout header {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: flex-start;
gap: 0.25rem 1rem;
margin: 0.5rem 0 2rem;
}

.modal-layout header .arrow {
fill: var(--gray-4, #5c717c);
width: var(--font-md, 1rem);
height: var(--font-md, 1rem);
align-self: center;
}

.modal-layout main {
box-sizing: border-box;
width: 100%;
border-radius: 0.5rem;
border: 1px solid var(--gray-2, #d8dee2);
background: var(--white, #fff);
box-shadow: var(--shadow-1);
display: flex;
flex-direction: column;
gap: 0.5rem 1rem;
padding: 1rem;
}

.modal-layout :is(h1, h2, h3) {
margin: 0;
}

.modal-layout h1 {
font-size: var(--font-xl, 24px);
font-weight: 400;
}

.modal-layout h2 {
font-size: var(--font-xl, 24px);
}

.modal-layout h3 {
font-size: var(--font-md, 16px);
}

.modal-layout .info {
flex: 0 1 auto;
font-size: var(--font-sm);
opacity: 0.7;
display: flex;
align-items: center;
gap: 0.25rem;
color: var(--gray-5);
}

.modal-layout .info .icon {
display: inline-flex;
align-items: center;
width: var(--font-md, 0.75em);
height: var(--font-md, 0.75em);
}

.modal-layout .help {
font-weight: var(--font-regular, 400);
font-size: var(--font-sm, 0.875em);
}

.modal-layout .plan.professional {
color: var(--blue-4);
}

.modal-layout .plan.organization {
color: var(--purple-4);
}

.modal-layout p {
margin: 0;
}

.modal-layout form {
display: flex;
flex-direction: column;
gap: 0.5rem;
}

.modal-layout .buttons {
display: flex;
gap: 1rem;
align-items: center;
margin-top: 0.5rem;
}

.modal-layout .footer {
margin-top: 2rem;
font-weight: 600;
font-family: var(--font-sans, "Source Sans Pro");
font-size: var(--font-md, 16px);
}

.modal-layout .footer a {
color: var(--gray-5, #233944);
text-decoration-color: var(--gray-5, #233944);
}
5 changes: 5 additions & 0 deletions frontend/css/payments_hub.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
header .title {
display: flex;
align-items: center;
gap: 0.5rem;
}
Loading
Loading