Skip to content

Tenant improvements on addition and ability to delete#997

Open
rchlfryn wants to merge 9 commits intomainfrom
tenant-improvements
Open

Tenant improvements on addition and ability to delete#997
rchlfryn wants to merge 9 commits intomainfrom
tenant-improvements

Conversation

@rchlfryn
Copy link
Collaborator

@rchlfryn rchlfryn commented Mar 22, 2026

Description

While working on onboarding tickets, I though of some improvements we can make for the tenant (avalanche center) creation and deletion (which was broken) experience in the admin UI.

Related Issues

Fixes #976

Key Changes

Slug field: only show unused slugs on creation

  • The slug field uses a custom TenantSlugField component that fetches existing tenants and filters out already-used slugs when creating a new tenant. We can't use Payload's built-in filterOptions here because it only works on relationship fields, not select fields — the slug is a select with a static list of valid avalanche center identifiers, so filtering must happen client-side.
  • When editing an existing tenant, all options are shown (the field is read-only on update anyway).

Auto-fill name from slug

  • An invisible AutoFillNameFromSlug component syncs the name field to the full avalanche center name when a slug is selected during creation.

Delete confirmation with type-to-confirm

  • Deleting a tenant is extremely destructive — it cascades across 17 tenant-scoped collections (pages, posts, media, settings, navigation, etc.). Payload's built-in delete confirmation is a simple "Are you sure?" which is not sufficient for an operation this invasive.
  • A DeleteTenantModal component intercepts Payload's default delete modal and replaces it with a custom one that requires typing the tenant name to confirm. This uses Payload's Modal directly rather than ConfirmationModal because the latter doesn't support controlling button state based on user input.

Deprovision hook

  • A beforeDelete hook (deprovisionBeforeDelete) deletes all tenant-scoped data before the tenant record itself is removed, preventing orphaned data and SQLite foreign key constraint errors. This runs regardless of how deletion is triggered (admin UI, API, etc.).

How to test

Create a new tenant:

  • Go to Admin > Avalanche Centers > Create New
  1. Slug field
    - Above name field now
    - The slug dropdown should only show slugs not already in use.
    - Edit an existing tenant — all slugs should be visible (field is read-only).
  2. Name field
    • On the create form, select a slug — the name field should auto-populate with the full center name.
    • You should be able to edit this if you want
  3. Delete confirmation
    • Open an existing tenant, click the actions menu > Delete.
    • The custom modal should appear requiring you to type the tenant name.
    • Typing the wrong name and clicking Delete should show an error toast.
    • Typing the correct name should proceed with deletion.
  4. Deprovision cleanup
    • After deletion, verify no orphaned data remains for that tenant across collections (pages, settings, media, etc.).

Screenshots / Demo video

https://www.loom.com/share/af64206841684c02ae1c75c44e546ae9

Migration Explanation

No migration needed — no schema changes.

Future enhancements / Questions

How do we feel about the custom slug field?

@github-actions
Copy link
Contributor

Preview deployment: https://tenant-improvements.preview.avy-fx.org

@@ -0,0 +1,51 @@
import type { CollectionBeforeDeleteHook } from 'payload'

export const TENANT_SCOPED_COLLECTIONS = [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[17:30:01] ERROR (payload): Failed query: delete from "tenants" where "tenants"."id" = ?
params: 2
err: {
"type": "DrizzleQueryError",
"message": "Failed query: delete from "tenants" where "tenants"."id" = ?\nparams: 2: SQLITE_CONSTRAINT_NOTNULL: NOT NULL constraint failed: forms.tenant_id: NOT NULL constraint failed: forms.tenant_id",

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how did you get this error?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh jeez I thought I'd included context here - that's terrible haha.

What I thought I'd written was:

I believe you need to add the forms collection to this list because you get this NOT NULL constraint failed on the form that gets created in our seed data. https://www.loom.com/share/5b53172aed9048ec83b367fcd4412266

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just pushed that change since it was super quick. 0027fa7

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you!

@rchlfryn rchlfryn added this pull request to the merge queue Mar 25, 2026
github-merge-queue bot pushed a commit that referenced this pull request Mar 25, 2026
Tenant improvements on addition and ability to delete
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Mar 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support deleting an avalanche center

2 participants