Skip to content

fix(configs): PUT existing scope config when adding a new slice#167

Merged
qiyundai merged 2 commits into
devfrom
chore/configs-changes
May 28, 2026
Merged

fix(configs): PUT existing scope config when adding a new slice#167
qiyundai merged 2 commits into
devfrom
chore/configs-changes

Conversation

@sharmeebuilds
Copy link
Copy Markdown
Collaborator

@sharmeebuilds sharmeebuilds commented May 28, 2026

ESP enforces one config per scope (any combination of rsvp / locales / customAttributes slices), but the UI treated each tab as its own config keyed on a legacy type discriminator. When a scope already had a config (e.g. customAttributes), saving from the Locales tab POSTed and returned 409 because the "no locales-typed config found" check missed the existing customAttributes-typed one.

This change unifies the model: a scope has a single ScopeConfig with optional slice fields. Slices are detected by field presence, and saves PUT to the existing config (merging slices, dropping legacy type) or POST a fresh one only when the scope owns none.

What is a "slice"?

A slice is one tab's chunk of fields inside the single scope config:

Tab Slice fields
RSVP Fields rsvpFormFields, localizations
Locale Mapping localeNames, localeUrlCodes
Custom Attributes attributes

deleteSlice is triggered from the Delete button in each tab — the ButtonGroup next to Edit on the RSVP/Locales tabs (ConfigManagement.tsx:1482 for RSVP, :1557 for Locales). It flows: button → confirmation AlertDialogdeleteSlice(config, 'rsvp' | 'locales', label).

Why not just call DELETE /configs/{configId}? Because the config now possibly carries other tabs' data. If a scope has both locales and custom attributes on the same config, hitting Delete on the Locales tab used to wipe attributes too. Now it strips only that tab's fields and PUTs the rest back. The full DELETE only fires when removing this slice empties the config entirely.

For Custom Attributes there's no separate "delete the whole attributes section" button — the equivalent slice-clearing path is inside handleDeleteAttr (:855): when you delete the last attribute row, it removes the attributes field. Same PUT-vs-DELETE branch lives there.

Changes deployed here: https://14257-emc-sharmeeb.adobeio-static.net/

Summary

  • New unified ScopeConfig with optional slice fields + hasRsvpSlice / hasLocalesSlice / hasAttributesSlice guards
  • getConfigsForScope(scopeId, type) filters by slice-field presence so reads still work on configs written by newer PUTs that omit type
  • ConfigManagement save handlers (RSVP / Locales / Attributes) PUT into scopeConfig.configId when the scope owns a config; POST otherwise
  • New buildPutBody() strips legacy type while preserving sibling slices on every PUT path
  • Slice-level deletes (deleteSlice, handleDeleteAttr) clear only the removed slice via PUT when other slices remain; full DELETE only when the slice was the last one
  • EventForm consumers (EventInfo, CustomAttributes, RegistrationFields) switched from c.type === ... to slice-presence helpers
  • RSVP Fields and Custom Attributes tabs disabled in ConfigManagement — only Locale Mapping is in scope; default landing tab switched to locales so the page doesn't open onto a disabled tab

Test plan

  • On a scope that already has a customAttributes config, go to the Locale Mapping tab, click Create Locales Config, fill in en-US, and save — expect a PUT 200 (not POST 409), and after refresh both the locales table and the existing custom attributes are visible
  • On a fresh scope (no config), Create Locales Config — expect a POST 201 with no type field in the body
  • On a scope with locales + attributes, delete the locales config — expect a PUT 200 that drops localeNames/localeUrlCodes; attributes remain on refresh
  • On the same scope, delete the last custom attribute — expect a PUT 200 that drops attributes; locales remain
  • On a scope with only locales, delete locales — expect a DELETE 204
  • Repeat the same scenarios for the RSVP slice (Create/Edit field, Edit options, Delete field, Delete RSVP Config)
  • Open EventForm on a scope whose config was PUT without type — locale picker, custom attributes, and RSVP fields all populate
  • Open the Configs page with a scope selected — RSVP Fields and Custom Attributes tabs render greyed-out and are not clickable; Locale Mapping is selected by default

ESP enforces one config per scope (any combination of rsvp / locales /
customAttributes slices), but the UI treated each tab as its own config
keyed on a legacy `type` discriminator. When a scope already had a
config (e.g. customAttributes), saving from the Locales tab POSTed and
returned 409 because the "no locales-typed config found" check missed
the existing customAttributes-typed one.

This change unifies the model: a scope has a single ScopeConfig with
optional slice fields. Slices are detected by field presence, and saves
PUT to the existing config (merging slices, dropping legacy `type`) or
POST a fresh one only when the scope owns none.

## Summary
- New unified `ScopeConfig` with optional slice fields + `hasRsvpSlice`
  / `hasLocalesSlice` / `hasAttributesSlice` guards
- `getConfigsForScope(scopeId, type)` filters by slice-field presence
  so reads still work on configs written by newer PUTs that omit `type`
- ConfigManagement save handlers (RSVP / Locales / Attributes) PUT into
  `scopeConfig.configId` when the scope owns a config; POST otherwise
- New `buildPutBody()` strips legacy `type` while preserving sibling
  slices on every PUT path
- Slice-level deletes (`deleteSlice`, `handleDeleteAttr`) clear only the
  removed slice via PUT when other slices remain; full DELETE only when
  the slice was the last one
- EventForm consumers (EventInfo, CustomAttributes, RegistrationFields)
  switched from `c.type === ...` to slice-presence helpers

## Test plan
- [ ] On a scope that already has a customAttributes config, go to the
      Locale Mapping tab, click Create Locales Config, fill in en-US,
      and save — expect a PUT 200 (not POST 409), and after refresh both
      the locales table and the existing custom attributes are visible
- [ ] On a fresh scope (no config), Create Locales Config — expect a
      POST 201 with no `type` field in the body
- [ ] On a scope with locales + attributes, delete the locales config —
      expect a PUT 200 that drops localeNames/localeUrlCodes; attributes
      remain on refresh
- [ ] On the same scope, delete the last custom attribute — expect a
      PUT 200 that drops `attributes`; locales remain
- [ ] On a scope with only locales, delete locales — expect a DELETE 204
- [ ] Repeat the same scenarios for the RSVP slice (Create/Edit field,
      Edit options, Delete field, Delete RSVP Config)
- [ ] Open EventForm on a scope whose config was PUT without `type` —
      locale picker, custom attributes, and RSVP fields all populate

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@sharmeebuilds sharmeebuilds requested a review from qiyundai May 28, 2026 14:04
Only Locale Mapping is in scope; the other two tabs are disabled and
the default landing tab switches to `locales` so the page doesn't open
onto a disabled tab.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@sharmeebuilds
Copy link
Copy Markdown
Collaborator Author

Note: The locales structure might get updated in the next PR based on latest BE changes getting discussed

@qiyundai qiyundai merged commit a40d132 into dev May 28, 2026
3 checks passed
@qiyundai qiyundai mentioned this pull request May 29, 2026
5 tasks
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.

2 participants