Skip to content

feat(newsletters): admin UI for newsletter system (Wave 0)#75

Open
mpge wants to merge 14 commits into
mainfrom
feat/newsletter-frontend
Open

feat(newsletters): admin UI for newsletter system (Wave 0)#75
mpge wants to merge 14 commits into
mainfrom
feat/newsletter-frontend

Conversation

@mpge
Copy link
Copy Markdown
Member

@mpge mpge commented May 20, 2026

Summary

Implements the shared Vue/Inertia admin UI for the newsletter system per docs/superpowers/specs/2026-05-19-newsletter-system-design.md. Backend wiring follows in escalated-laravel (Wave 1).

  • New pages/Admin/Newsletters/** page tree (Index, Compose, Show, Edit, Settings, Lists, Templates)
  • New components/admin/newsletters/** building blocks (MarkdownEditor, MergeFieldDropdown, PreviewIframe, SummaryTiles, AnalyticsTiles, DeliveriesTable, ListMemberTable, DynamicFilterBuilder)
  • Sidebar nav gated on escalated.features.newsletters (added to EscalatedLayout)
  • English locale strings under locales/en.json (top-level newsletters key)
  • Storybook stories for every new component
  • Version bump to 0.9.0

Deviations from spec

  • Locale layout — plan assumed src/locales/en/<feature>.js modules; actual repo uses one JSON per language (en.json) with feature keys at the top level. Landed in en.json, not a new module.
  • Sidebar — plan referenced an AdminSidebar.vue standalone; actual repo has the admin nav inline in EscalatedLayout.vue via an adminLinks computed. Added the gated entry there, following the existing kbEnabled pattern.
  • Page paths — plan used lowercase pages/admin/newsletters/; actual convention is PascalCase pages/Admin/Newsletters/. Matched the existing convention.
  • Permission gating — plan called for newsletters.manage|send permission gating on the sidebar entry; no hasPermission helper exists in the frontend today (KB/CSAT/Macros are admin-implicit). Per-link permission gating is deferred — admin role gets both perms by default at install, so practical visibility is identical.
  • DynamicFilterBuilder — plan had a dynamic-import fallback that referenced a not-yet-existing ContactFilterBuilder.vue. Shipped the JSON-textarea fallback only; will swap in the real builder when the contacts saved-view filter component lands.

Test plan

  • Vitest: 558 tests passing (29 new test files, 36 new tests)
  • Lint: clean
  • Storybook stories ship alongside each component
  • (Post-merge) Tag release v0.9.0 so backend PRs can consume it

Reviewer: please do not auto-merge — review and merge at your discretion.

mpge added 14 commits May 20, 2026 09:22
Adds a Newsletters entry to the admin sidebar in EscalatedLayout, gated
on the backend-injected `escalated.features.newsletters === true` shared
prop. Follows the existing `kbEnabled` pattern.

Note: the spec calls for also gating on `newsletters.manage|send` permission,
but the shared frontend has no hasPermission helper today (KB/CSAT/Macros
nav are admin-implicit via the surrounding is_admin section gate). Per-link
permission gating can land alongside a generic hasPermission composable in a
later iteration; for v1 the admin role gets both perms by default at install
time, so the practical visibility is identical.
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.

1 participant