Conversation
…tion heading Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Collapsible RSVP field cards in Create/Edit dialog (only select/multi-select; non-option fields always expanded) - Locale switcher in RSVP toolbar; all localizable fields reflect selected locale; per-field edit dialog handles locale-mode saves (base + override in one API call); Localizations section removed from RSVP dialog - RSVP expanded options: replace numbered text list with read-only/editable TextFields (Value + Label) - Custom attr expanded values: same inline edit pattern as RSVP options (Value + Label TextFields, Edit/Save/Discard/Add/Remove) - displayAs: constrained to valid options per field type via getDisplayAsOptions(); column suppressed for non-select types; reset on incompatible type change - Badge fixes: informative → neutral for type/inputType labels; wrapped in flex div to prevent full-width stretch in table columns; locale code column uses plain Text - isRowExpandable predicate on DataTable/ResourceDashboardLayout: suppress expand chevron for RSVP fields with no options/rules/default/locale-overrides, and for custom attrs with no values - Custom attr dialog: size="L" - Fix Update button bug in custom attr dialog: normalize undefined label on openAttrEdit Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Renders scope-configured custom attributes (text, boolean, single-select, multi-select) in a new form card at the bottom of the Additional Content step. Multi-select uses an ordered repeater pattern to support user-defined downstream sequencing. Card always visible — shows progress indicator while loading and an empty-state message when no attributes are configured. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s to scope configs API
- Update scope-configs integration guide: options now use {value, label} format,
add localization merge patterns and option display logic notes
- Migrate RegistrationFieldsComponent from fetching external JSON configs to
cachedApi.getConfigsForScope, using RsvpFormField labels directly
- Update RegistrationConfigComponent prop name cloudType → isExperienceCloud
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ields When a locale is selected in the table toolbar, the Edit RSVP Config dialog now shows and edits locale-specific labels, placeholders, and option labels instead of base values. Structural controls (add/remove field, add/remove option, option values) are hidden in locale mode. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…l width Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ed indicator Remove isRequired from agenda end time fields (TimeField and DatePicker). Add a publish guard that validates all required fields across form steps before allowing publish, including custom attributes with isRequired. Shows a user-friendly dialog listing missing fields grouped by step. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- README/PROJECT_OVERVIEW: port 3000, real npm scripts, structure - EVENT_FORM/DEVELOPMENT_WORKFLOW/DEV_TOKEN: URLs and eventType route - FRONTEND: S2, App routes table, TopNav-based new-route steps - TESTING: Jest layout, test:unit, CI as lint+type-check, no e2e script - TOP_NAV_LAYOUT/USER_PANEL: paths, nav items, remove SideBar confusion - MODULAR_COMPONENT_PATTERN/EVENT_FORM: pages/EventForm paths Made-with: Cursor
EventInfoComponent previously called cachedApi.getLocales(), which hits the ESP GET /v1/locales endpoint. That route is deprecated in events-service-platform in favor of scope-level configs with type "locales" (same LocalesScopeConfig shape as Cloud Management: localeNames + localeUrlCodes). The picker now resolves the active ExC group scope via useGroup().activeGroup.scopeId and loads configs with cachedApi.getConfigsForScope(scopeId, 'locales'). When a locales config exists and localeNames is non-empty, options are built from those entries. If there is no scope id, the request fails, or no locales config is present, we fall back to SUPPORTED_SPEAKER_LOCALES + SPEAKER_LOCALE_LABELS so behavior matches ConfigManagement’s RSVP "available locales" fallback. If the event’s current defaultLocale is not listed in the resolved set (e.g. legacy data), we inject a synthetic picker row so the selected key remains valid until the user changes language. Made-with: Cursor
Align ConfigType, scope config models, and create bodies with ESP develop (customAttributes instead of custom-attributes). Update Event Form and Config Management fetch/filter/create paths so ?type= and config type match ESP’s strict filter.
- Prefer scope RSVP config via getConfigsForScope; fall back to legacy cloud
JSON (configService + mapLegacyRsvpConfigToFormFields) when scope has no fields
- Add RsvpFieldOptionSelectionState on EventFormData for select/multi-select
option order and include toggles (client-only until ESP exposes a contract)
- S2 Disclosure for option lists; HTML5 DnD reorder; auto-remove field when all
options disabled; reset option state when field hidden
- RegistrationConfigComponent wires cloudType and rsvpOptionSelections patch handler
- Hydrate rsvpOptionSelections as {} from API; TODO(PIM) on save path for future
granular serialization
Co-authored-by: Cursor <cursoragent@cursor.com>
- Document pim context/report usage and pod binding in CLAUDE.md - Add Claude Code sync command for PIM context pull - Gitignore .pim/ directory for local PIM state Co-authored-by: Cursor <cursoragent@cursor.com>
- Options list now renders inside the field card border rather than below it - Replaced Disclosure/DisclosureTitle trigger with an inline ListBulleted icon in the field row (5th grid column) - Icon is only shown for fields that have selectable options; absent otherwise - Icon highlights in selection-ring color when panel is expanded - Starting a field drag collapses all open option panels (mutually exclusive) - Removed redundant borders from option rows; drag-over ring retained Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Blocking fixes: - Replace div[role=button] with ActionButton isQuiet + onPress to fix drag-start interference and missing Spectrum focus ring - Add e.stopPropagation() to handleOptionDragOver/handleOptionDrop so option drags don't bubble to the outer field-card drop target - Clear optionDrag/optionDragOver in handleDragStart to avoid stale state - Prune expandedOptions when a field is hidden so the panel doesn't auto-reopen on re-show Code quality: - Extract toggleExpanded local fn to deduplicate setExpandedOptions logic - Replace <div /> fallback with null for the empty list-icon column - Wrap mandatedFieldNames in useMemo; use stable ref in useEffect dep array - Make isSelectableField a proper TypeScript type predicate - Add aria-label/aria-hidden to Move drag handle divs - Remove dead font styles from empty header span elements Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat(rsvp): move options panel inside field card with inline toggle
…t-route # Conflicts: # web-src/src/pages/EventForm/EventForm.tsx
[MWPW-194949] : Update route with event id
Merge publishing-profile metadata with catalogue acknowledgments in one update when possible, backfill when the catalogue loads later, reset profile state on eventId change, and merge profileId from ESP association when the nested profile omits it (follow-up to explicit PPN selection). Co-authored-by: Cursor <cursoragent@cursor.com>
After saving a new image the table showed the stale photo because handleFormSubmit called apiService directly, bypassing cachedApi and its cache-invalidation logic. Removing an image also had no effect because no DELETE was ever sent to ESP. - Use cachedApi.updateSpeaker/createSpeaker so the series cache is invalidated before loadSpeakers re-fetches - Track removedImageId in SpeakerFormDialog and pass it to the parent; handleFormSubmit now calls deleteSpeakerImage when a saved image is removed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tion fix(event-form): stabilize page metadata (PPN) acknowledgment hydration
Merge dev into configs branch (resolves conflicts, preserves both feature sets)
When searching by group name, the expanded member list was always empty because the same query term was applied to filter users — who naturally don't match the group name. Now, if the group itself matches the query (name or description), all its members are shown; filtering is only applied when the group surfaced via a member match. Also adds a defensive empty-string guard to groupMetaMatchesQuery, matching the style of the parallel userMatchesQuery helper. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix(scope-group-mgmt): show all members when group matched by name
Three structural correctness fixes around rsvpFormFields:
- Add 'rsvpFormFields' to speciallyHandledFields so the generic
EVENT_DATA_FILTER loop does not double-process the field alongside
the explicit payload block.
- Guard rsvpFormFields payload assembly with Array.isArray so empty
arrays and non-array form state values are not serialized as
{ fields: [] } (BE rejects non-object/empty values).
- Surface the actual BE error message on save failures by reading
result.error.message instead of result.message, which was always
undefined and caused all save errors to fall back to the generic
'Failed to update/create event' string.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds transitional dual-shape support for rsvpFormFields while ESP BE PR #903 (https://git.corp.adobe.com/wcms/events-service-platform/pull/962/files sibling: PR #903) is in flight. The BE is moving from the legacy { required: string[], visible: string[] } shape to the new { fields: [...] } shape — a breaking change. Until #903 ships to dev/stage/prod and stored events are normalized, EMC must work against both shapes. Save side (useEventFormSave.ts): - isRsvpFormFieldsRejection() detects 400 responses whose validation errors point at rsvpFormFields (Ajv errors don't include the field name in `message`, so we also walk `errors[].instancePath`). - toLegacyRsvpFormFieldsPayload() rewrites the new {fields} payload to the legacy {required, visible} shape. Per-field `options` overrides aren't representable in the legacy shape and are dropped with a console.warn so QA can see the loss. - Update and create branches send the new shape first and retry with the legacy payload on rsvpFormFields-flavored 400s. Read side (eventFormMappers.ts): - readRsvpFormFields() adapts either GET shape to the array form the form state expects. Without it, events stored under the legacy shape would open with an empty RSVP fields list. All temporary code is tagged `rsvp-shape-migration` so the cleanup after #903 ships is a clean grep-and-delete; the structural fixes from the prior `fix: rsvp form fields handling` commit are permanent and must stay (see header comment in useEventFormSave.ts for the checklist). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fix: config API bugs, ESP PR #962 custom attributes, scope mismatch fix
[MWPW-195009]:- Custom CaaS Taxonomy View per Series
…-migration chore: rsvpFormFields BE shape migration shim
…ds-be-shape-migration Revert "chore: rsvpFormFields BE shape migration shim"
Re-applies transitional dual-shape support for rsvpFormFields with save
order corrected: legacy {required, visible} shape is sent first; the new
{fields} shape is the fallback retry on rejection. Previous version was
reverted because it sent new shape first, which fails against the current
BE before ESP PR #903 ships.
Save side (useEventFormSave.ts):
- Primary call converts rsvpFormFields to legacy shape before sending.
- Retry with new {fields} shape only if BE rejects with a
rsvpFormFields-flavored 400 (post-#903 environments).
Read side (eventFormMappers.ts):
- readRsvpFormFields() adapts either GET shape to the array the form
expects, so events stored under the legacy shape open correctly on edit.
All temporary code tagged `rsvp-shape-migration` for clean grep-and-delete
once ESP PR #903 ships everywhere.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-migration-new chore: rsvpFormFields BE shape migration shim (legacy-first order)
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>
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>
Replace the object-shaped locales slice (`localeNames` + `localeUrlCodes`
keyed by locale code) with a single `locales: Locale[]` array on
ScopeConfig, where each entry carries `{ code, name, folder }`. Hard
cutover — old fields are no longer read or written anywhere on the FE.
Touches:
- types/configApi.ts: new `Locale` interface; `ScopeConfig.locales?`
replaces the two record fields; `LocalesScopeConfig` and
`hasLocalesSlice` updated.
- services/api.ts: `getConfigsForScope('locales')` filters by
`Array.isArray(c.locales)`.
- pages/ConfigManagement: read/write/delete paths use the array;
Locale Mapping table renders from `locales`; dialog state field
renamed `urlCode` -> `folder`; column header "URL Code" -> "Folder".
- pages/EventForm/EventInfoComponent: language picker reads
`localesConfig.locales` instead of `localeNames`.
Pending BE: this change cannot be verified against a live backend until
ESP migrates the locales slice; existing scopes will fall back to the
default picker / empty state until then.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fix(configs): PUT existing scope config when adding a new slice
ESP returns scopeId on GET but SERIES_DATA_FILTER stripped it on PUT, causing scope membership to be lost on series update/publish/unpublish/ archive. Add scopeId to the filter (updatable, not cloneable) and thread it from the loaded canonical response into SeriesForm's buildApiPayload. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fix(series): include scopeId in PUT payload
chore(configs): migrate locales slice to array shape
sirivuri
approved these changes
May 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release: T3-26.23 (stage)
Promotes
devintostagefor the T3-26.23 stage release.Release notes
Scope configs (new admin surface)
ScopeConfigmodel: one config per scope with optional slices (RSVP / locales / custom attributes); saves PUT to existing config instead of POSTing duplicate configs (fix(configs): PUT existing scope config when adding a new slice #167).?type=query param (client-side filter), includescopeIdin POST body, proper 409 error handling (MWPW-196046) (fix: config API bugs, ESP PR #962 custom attributes, scope mismatch fix #162).enabledAttributeIds(fix: config API bugs, ESP PR #962 custom attributes, scope mismatch fix #162).locales: Locale[]array shape (chore(configs): migrate locales slice to array shape #168); Event form language picker reads new structure.Event form
/events/edit/:eventIdafter first save/publish to prevent duplicate creation (MWPW-194949) ([MWPW-194949] : Update route with event id #152).cachedApifor cache invalidation (MWPW-195871) ([MWPW-195871] Fix: Speaker image update and delete not reflecting in table #158).enabledAttributeIds(MWPW-195821) (fix: config API bugs, ESP PR #962 custom attributes, scope mismatch fix #162).RSVP / registration
rsvpFormFieldsBE shape migration shim: legacy{required, visible}sent first, new{fields}shape as fallback retry pending ESP PR #903 (chore: rsvpFormFields BE shape migration shim (legacy-first order) #166).Series
scopeIdin series PUT payload so scope membership is preserved on update/publish/unpublish/archive (fix(series): include scopeId in PUT payload #169).Access (RBAC)
Included merges (high level)
Promotion path:
devis 62 commits ahead ofstageat PR open.Verification
scopeIdPost-merge: merge the companion T3-26.23 Production Release PR (
stage→main) after stage validation.Made with Cursor