Commit Graph

985 Commits

Author SHA1 Message Date
Paul Nothaft fad2de5abe fix(activity-log): smart feature_flags_updated rendering + 33 missing types
The Dashboard "Recent Activity" widget and the header notifications
dropdown both rendered raw activity-type strings (e.g. the literal
"feature_flags_updated") for any type missing from their lookup
maps — including everything emitted by the recently-added customer
portal (#354), webhooks (#327), API tokens (#322), event types,
event-publish flow, admin user management (#350), and the
feature-flags reorg itself.

Two coordinated changes:

1. Smart formatter for feature_flags_updated. The backend writes
   `metadata.changed = { [flagKey]: { from, to } }` on every save.
   New formatFeatureFlagsChanged() helper in admin.service.ts reads
   that diff and renders:
     - 1 change → "Customer Portal enabled"
     - N changes → "3 features updated: Customer Portal enabled,
       Calendar disabled, Quotes enabled"
   Per-flag display labels source from `settings.features.<key>.title`
   so they stay in sync with the Features tab. Unknown flag keys
   fall through to a humanised version of the key.

2. 33 missing activity types added to BOTH renderers and to the
   `admin.activities.*` + `admin.notificationMessages.*` i18n
   namespaces across all six locales. Coverage groups: customer
   portal (13 types), admin user management (6), webhooks (3),
   API tokens (2), event types (4), event publish/logo (3), bulk
   delete (1), and assorted post-merge surfaces (4).

   The notifications.service.ts switch + admin.service.ts fallback
   message map are still duplicated; consolidating them into a
   single source of truth is a follow-up worth doing before the
   next significant addition. For now both stay in sync via this PR.

en + de hand-translated. nl + pt + ru + fr machine-translated and
flagged for native review per project convention.
2026-05-11 22:06:10 +02:00
Paul Nothaft 4f3db923a6 Merge pull request #464 from Luca-Timo/feat/email-templates-reorg
Feat/email templates reorg
2026-05-11 21:44:17 +02:00
Luca 2343a162df fix(email-templates): backfill subcategory + customer password reset translations 2026-05-11 21:08:16 +02:00
Luca e3150e4213 feat(email-templates): seed missing locale translations + post-075 templates 2026-05-11 20:56:58 +02:00
Luca 53eecb6f83 feat(email-templates): group Templates UI by category with core sub-sections 2026-05-11 20:56:50 +02:00
Luca 2cae3fe47d feat(email-templates): categorise + sub-categorise + link to feature flags 2026-05-11 20:56:28 +02:00
Luca 358f7ee99e feat(email-templates): seed missing nl/pt/ru/fr translations 2026-05-11 20:42:28 +02:00
Luca 5ec26fc998 feat(email-templates): group Templates UI by category + Feature off chip 2026-05-11 20:42:16 +02:00
Luca 84c06affb7 feat(email-templates): categorise + link to feature flags 2026-05-11 20:41:50 +02:00
Paul Nothaft a125ea2ada Merge pull request #463 from the-luap/release-please--branches--beta
Build and Push Docker Images / build-backend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-frontend (push) Has been cancelled
Build and Push Docker Images / summary (push) Has been cancelled
chore(beta): release 3.46.3-beta.0
v3.46.3-beta.0
2026-05-11 20:19:43 +02:00
github-actions[bot] b31fc2140b chore(beta): release 3.46.3-beta.0 2026-05-11 18:18:34 +00:00
Paul Nothaft bd2288e6a0 Merge pull request #461 from the-luap/fix/branding-socials-not-loaded
fix(branding): socials + promo round-trip from DB to form (#460)
2026-05-11 20:18:09 +02:00
Paul Nothaft ae64a6acbc fix(branding): socials + promo round-trip from DB to form (#460)
formatBrandingSettings was updated when the BrandingSettings
interface added the footer-overhaul fields (#441 / #440), so the
admin BrandingPage initialised them as empty strings on every load.
Saving any other field then sent the form's empty socials /
promo_markdown / promo_position back to the backend and wiped the
saved values from the DB. The public gallery footer kept rendering
the old values until the next save, which is why the bug appeared
asymmetric (visible to galleries, gone from the admin form).

Add the missing read mappings for the seven branding_* keys so the
form round-trips them correctly.

Reported by @Rekoo-PS in #460 (split out of #447).
2026-05-11 20:11:19 +02:00
Paul Nothaft 4e0d26d3f8 Merge pull request #462 from the-luap/release-please--branches--beta
Build and Push Docker Images / build-backend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-frontend (push) Has been cancelled
Build and Push Docker Images / summary (push) Has been cancelled
chore(beta): release 3.46.2-beta.0
v3.46.2-beta.0
2026-05-11 20:09:57 +02:00
github-actions[bot] eddcdbf4d8 chore(beta): release 3.46.2-beta.0 2026-05-11 18:07:41 +00:00
Paul Nothaft 9776d8a6fc Merge pull request #458 from Luca-Timo/fix/customer-functions
fix(customer-portal): post-merge fixes for event save, theme fonts, and customer→gallery handoff
2026-05-11 20:07:11 +02:00
Luca c0c6b4c0e8 chore(customer-portal): align flag-gate comments with new dual-enforcement 2026-05-11 19:38:18 +02:00
Luca 2a7ae0702d fix(events): CustomerAccountPicker hooks order crashed /admin/events/new 2026-05-11 19:37:52 +02:00
Paul Nothaft 06733f841a Merge pull request #457 from the-luap/release-please--branches--beta
Build and Push Docker Images / build-backend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-frontend (push) Has been cancelled
Build and Push Docker Images / summary (push) Has been cancelled
chore(beta): release 3.46.1-beta.0
v3.46.1-beta.0
2026-05-11 19:08:13 +02:00
Luca 8d9d0bea83 fix(customer): customer sidebar active state matches admin pattern 2026-05-11 16:48:29 +02:00
Luca eb0c45e0f4 chore(i18n): drop dead navigation.customers keys 2026-05-11 16:39:30 +02:00
Luca 9091ed4012 feat(clients): scaffold top-level Clients section with sub-nav around Accounts 2026-05-11 16:17:14 +02:00
Luca 35f5b86d0f fix(theme): 'Same as body' heading font no longer inherits stale value 2026-05-11 11:50:09 +02:00
Luca 7ac1d14738 fix(customer): preserve slug-scoped gallery tokens on auth provider mount 2026-05-11 11:32:59 +02:00
Luca bf7ef14626 fix(settings): readable contrast on accent-tinted icon tiles + pills 2026-05-11 11:27:16 +02:00
Luca 2f00bbdd90 fix(settings): neutralize sidebar icons for a consistent palette 2026-05-11 11:11:23 +02:00
Luca 15d01f3756 fix(features-tab): icon tiles + preview pills follow CI accent 2026-05-11 11:07:55 +02:00
Luca 75e41eba03 feat(branding): toggle login-page logo frame + size 2026-05-11 11:02:33 +02:00
Luca dde72a1b1b fix(events): strip customer_account_ids from update spread 2026-05-11 10:53:12 +02:00
github-actions[bot] 3ea7eea4b7 chore(beta): release 3.46.1-beta.0 2026-05-11 08:07:45 +00:00
Paul Nothaft 5b148542e6 Merge pull request #455 from the-luap/fix/photo-dimensions-and-default-fit
fix(import): capture photo dimensions in fileWatcher + s3AutoImporter (#447)
2026-05-11 10:07:07 +02:00
Paul Nothaft 88a865c813 Merge pull request #456 from the-luap/release-please--branches--beta
Build and Push Docker Images / build-backend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-frontend (push) Has been cancelled
Build and Push Docker Images / summary (push) Has been cancelled
chore(beta): release 3.46.0-beta.0
v3.46.0-beta.0
2026-05-11 10:06:41 +02:00
Paul Nothaft 2f63188a34 fix(events): TDZ ReferenceError on /admin/events from #442 fix (#454)
The pagination-clamp useEffect added in #448 (commit 9c4a96f) was
inserted at the top of the component body, BEFORE the useQuery that
declares `data`. Because the useEffect's dependency array
`[data?.pagination, page]` is evaluated immediately when that line
executes, every render hit a temporal dead zone access on `data` and
threw `ReferenceError: Cannot access 'data' before initialization`
— minified to "Cannot access 'I' before initialization" in the
production bundle, crashing the entire page.

TypeScript caught this at the time
(`Block-scoped variable 'data' used before its declaration`) but the
project's build doesn't fail on TS errors so it shipped anyway.

Move the effect to immediately after the useQuery so `data` is in
scope. Behavior unchanged otherwise — same dep array, same setPage
clamp logic.

Reported by @derooijmnl on v3.45.1-beta.0.
2026-05-11 10:03:40 +02:00
Paul Nothaft 49b36a0352 chore(migrations): renumber 090 → 096 + small notes from #403 review
Post-merge cleanups after #403 (customer portal):

- Renumber 090_backfill_photo_dimensions_v2.js → 096 to follow #403's
  090_add_customer_accounts ... 095_add_customer_portal_flag chain.
- customerAccountsService.js: TODO note on must_change_password
  documenting that the column is decorative until an admin
  pre-loaded-password flow ships (mirrors what adminAuth does for
  must_change_password today).
- customerAuth.js: doc-comment on the /login route explaining why the
  customerPortal feature flag deliberately doesn't gate it (toggle off
  hides UI, doesn't revoke existing-customer access; deactivate
  individual accounts to lock out).
- 095_add_customer_portal_flag.js: header comment said "Migration 094"
  (copy-paste from 094) — now matches the filename.
2026-05-11 09:59:47 +02:00
Paul Nothaft 936a277eb8 fix(import): capture photo dimensions in fileWatcher + s3AutoImporter (#447)
The aspect-aware gallery layouts (masonry / mosaic / justified) read
photo.width and photo.height to size each card to the source's real
proportions. Two import paths were inserting rows without those
fields, which forced MasonryGalleryLayout to fall back to a hard-coded
800×600 default — every card came out the same shape, so users
reported masonry as "always cropped to 1:1ish" no matter which
thumbnail fit mode they chose.

- fileWatcher.js: extract dims with sharp.metadata() before insert.
- s3AutoImporter.js: same, materialising a tmp local copy via
  withLocalCopy so it works in S3 mode.
- migration 090: backfill any pre-existing rows with NULL dims
  (skips videos, skips S3 deployments — those need the writer fix
  alone since migrations cannot reach the storage backend).
- imageProcessor.js: change DEFAULT_THUMBNAIL_FIT from 'cover' to
  'inside' (only kicks in when the seed setting is missing — existing
  installs keep their saved value). Add UI tooltip recommending
  'inside' for masonry/mosaic/justified, 'cover' for uniform grids.

i18n covers all six locales.
2026-05-11 09:58:08 +02:00
github-actions[bot] 87dfae0074 chore(beta): release 3.46.0-beta.0 2026-05-11 07:57:50 +00:00
Paul Nothaft fe5295373b Merge pull request #403 from Luca-Timo/feat/user-accounts
feat: customer accounts (#354) — recurring logins, profile, password reset, branded customer surface
2026-05-11 09:57:15 +02:00
Luca 032a43ad01 i18n(customers): add nl / pt / ru / fr translations for customer portal
Previously these locales fell through to en for every customer.* /
customers.* / settings.customerSurface / settings.features.customerPortal
key. Machine-translated and flagged in the PR description as needing
native review.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 02:13:08 +02:00
Luca fd46c171ce chore(branding): move Customer dashboard card between Company Info and Gallery Theme
Keeps the customer-surface branding toggles adjacent to the other
brand-visibility controls instead of floating at the bottom of the
page, where they were easy to miss.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 01:59:30 +02:00
Luca b252cb67eb feat(branding): Customer dashboard header toggles in Branding page
Adds back the "Show logo" / "Show company name" toggles for the
customer dashboard, scoped to /customer/* surfaces only. Lives as a
dedicated card at the bottom of Settings → Branding, gated by the
customerPortal feature flag so admins who haven't enabled the portal
don't see it.

* Backend: restored GET/PUT /admin/settings/customer-surface
  endpoints, whitelisted only to the two branding keys
  (customer_show_logo, customer_show_company_name). The
  calendar/quotes/bills feature globals that used to live on this
  endpoint are now driven by the Features tab (feature_flags table).
* customerAccountsService.getCustomerSurfaceGlobals() reads from
  app_settings again so /api/customer/auth/session honours the
  toggles in its branding payload.
* New CustomerDashboardBrandingCard component with its own save
  flow — separate from the main BrandingPage payload so flipping a
  toggle doesn't replay the full branding mutation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 01:52:27 +02:00
Luca da08a5828a fix(customer): unwrap /customer/* from RequireFeature gate
RequireFeature calls useFeatureFlags(), which throws unless mounted
inside FeatureFlagsProvider — and that provider only wraps
AdminLayout. So unauthenticated visitors hitting /customer/login
crashed into the React error boundary with 'Oops! Something went
wrong'.

The customerPortal flag continues to hide every admin-side surface
(sidebar entry, /admin/customers routes, CustomerAccountPicker on
event forms), which is what the flag is actually for. The
customer-side tree stays reachable so existing customers can still
log in even if the admin flips the flag off temporarily.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 01:30:19 +02:00
Luca f048011324 fix(server): mount /api/admin/feature-flags route
The route was registered in upstream/beta's server.js but dropped
during the rebase squash — the Features tab GET/PUT both 404'd, so
the customerPortal flag (and every other flag) couldn't be toggled.
Restored the mount in its upstream/beta position.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 01:13:17 +02:00
Luca 4fa7225732 fix(server): drop missing requireCustomerPortal middleware import
server.js was still requiring ./src/middleware/requireCustomerPortal
— a file deleted during the AdvancedFeaturesTab cleanup — which
crashed the backend on boot in production (MODULE_NOT_FOUND).

The customerPortal feature flag is now enforced on the frontend via
<RequireFeature flag="customerPortal" /> route guards (App.tsx) and
AdminSidebar visibility. Defence in depth is provided by
customerAccountsService.isCustomerPortalEnabled() in adminEvents.
Routes themselves are still protected by adminAuth / customerAuth.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 00:48:13 +02:00
Luca adfa29e91e fix(auth): restore COOKIE_SECURE='auto' default for production
The customer-portal squash inadvertently reverted the upstream/beta
fix from PR #427: production NODE_ENV was flipping the cookie Secure
flag back to hard `true`, which broke admin login on
HTTPS-frontend → HTTP-backend reverse-proxy stacks (browser drops
the Secure cookie over HTTP, login loops indefinitely).

Restored upstream/beta's tokenUtils.js verbatim and re-layered only
the customer cookie helpers (CUSTOMER_COOKIE_NAME,
setCustomerAuthCookie, clearCustomerAuthCookie,
getCustomerTokenFromRequest) on top.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 00:29:04 +02:00
Luca 087ef45942 feat(customers): customer portal (#354) on top of feature-flags reorg
Implements the recurring-customer login surface from
the-luap/picpeak#354 plugged into the maintainer's
new feature-flag infrastructure (PR #443) instead of
a parallel toggle.

* New `customerPortal` feature flag (foundation flag for the
  not-yet-built calendar/quotes/bills/messaging customer
  surfaces). Defaults FALSE on fresh installs, TRUE on existing
  installs (events > 0) via migration 095 so live customer
  accounts don't disappear mid-deployment.
* Foundation schema: customer_accounts, customer_invitations,
  event_customer_assignments, customer_password_resets, plus
  RBAC permissions customers.view / .create / .delete granted
  to super_admin + admin system roles.
* Backend: /api/admin/customers (invite, list, search, assign,
  deactivate, reset password) + /api/customer/auth/* +
  /api/customer/* (login, dashboard, accept-invite, reset).
  Customer JWT bypass minted via
  /api/customer/events/:slug/access-token so existing gallery
  middleware stays untouched.
* Frontend: /customer/* route tree gated by RequireFeature flag
  customerPortal, with login / dashboard / accept-invite /
  reset pages and a customer-side sidebar layout.
  /admin/customers and /admin/customers/:id gated identically.
* Settings → Features grows a "Customers" section with a
  Customer portal card. The maintainer's Features tab stays the
  single source of truth — no parallel Advanced features tab.
* CustomerAccountPicker on event create/edit forms hides itself
  when the flag is off; backend ignores customer_account_ids in
  that case instead of erroring the whole event save.

Translations: en + de hand-translated. nl/pt/ru fall through to
en — flagged here as needing native review.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-11 00:05:20 +02:00
Paul Nothaft f2f48f31b0 Merge pull request #453 from the-luap/release-please--branches--beta
Build and Push Docker Images / build-backend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-frontend (push) Has been cancelled
Build and Push Docker Images / summary (push) Has been cancelled
chore(beta): release 3.45.1-beta.0
v3.45.1-beta.0
2026-05-10 22:09:48 +02:00
github-actions[bot] 55e6395e9e chore(beta): release 3.45.1-beta.0 2026-05-10 20:09:09 +00:00
Paul Nothaft 37d487db86 Merge pull request #452 from the-luap/fix/create-event-branding-default-race
fix(create-event): branding-default theme survives eventTypes refetch (#323-B)
2026-05-10 22:08:42 +02:00
Paul Nothaft d62c529b02 fix(create-event): branding-default theme survives eventTypes refetch
The "apply recommended preset on event-type change" effect was firing on
the initial mount AND every time the eventTypes API resolved (because
availableEventTypes is recomputed when that query settles). The first
fire matched the wedding default and clobbered the global Branding
theme that the previous effect had just applied.

Track the previous event_type in a ref and bail out when it hasn't
actually changed. The Branding-default effect now wins on first paint,
and the recommended-preset behaviour still kicks in when the user
manually picks a different event type.

Restores the green state of smoke spec 07 (#323-B regression).
2026-05-10 22:02:53 +02:00
Paul Nothaft 6ddb8e34d2 Merge pull request #451 from the-luap/release-please--branches--beta
Build and Push Docker Images / build-backend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-backend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-backend (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/amd64, ubuntu-latest) (push) Has been cancelled
Build and Push Docker Images / build-frontend (linux/arm64, ubuntu-24.04-arm) (push) Has been cancelled
Build and Push Docker Images / merge-frontend (push) Has been cancelled
Build and Push Docker Images / summary (push) Has been cancelled
chore(beta): release 3.45.0-beta.0
v3.45.0-beta.0
2026-05-10 21:58:21 +02:00