Skip to content

Changelog

CmsBlockLibrary

Every released version of CmsBlockLibrary, newest first.

CMS 7 releases latest 1.3.4RepositoryDocumentation

Changed

  • sw-cms-stage-add-section now extends the inner sw_cms_add_section_button block instead of the outer sw_cms_add_section, so the saved-section picker sits inside .sw-cms-stage-add-section rather than turning the component root into a fragment (fragment children take their anchors from the stage's children list, which reintroduced the same patch mismatch).

  • Removed the $nextTick / close-before-mutate workarounds in sw-cms-block-config.dmfOnSaveVisibility() and dmf-section-settings-modal.onClose(). They worked around the symptom above and their comments blamed a Vue <teleport> that was never involved — visibility now mutates customFields, persists, then closes in the normal order.

  • All eight modal components accept a hostSelector prop (default 'body'), forwarded to sw-modal's selector. New shared stylesheet src/app/dmf-cms-modal-host.scss hides an idle host (.dmf-cms-modal-host:empty) so it contributes no layout.

Fixed

  • Configuring block/section visibility twice threw insertBefore errors and the modal stopped opening. Setting up visibility worked once; changing it afterwards logged NotFoundError: Failed to execute 'insertBefore' on 'Node' followed by TypeError: Cannot read properties of null (reading 'insertBefore'), and from then on the modal never reappeared. Cause: core sw-modal relocates its own root node in mountedComponent() (document.querySelector(this.selector).appendChild(this.$el), selector defaults to body) and defers $el.remove() by 400 ms. Vue's patchBlockChildren derives the patch container for a component child from hostParentNode(oldVnode.el) — after the relocation that is body — while the sibling anchors still belong to the plugin's own subtree. On open, Vue wrote its v-if placeholders into body anchored to body text nodes; on close, sw-modal's deferred removal orphaned that anchor, insertBefore threw, the host lost its placeholder, and every later open mounted into a null container. Every v-if'd modal in the plugin now renders into its own host div whose per-instance id (${this.$.uid}) is passed to sw-modal as selector, so the node is re-appended where Vue already put it and container and DOM parent stay in sync. Applied to all 12 mount sites: block settings sidebar (save / linked editor / visibility), Section settings modal (nested save + linked editor), section actions, stage add section picker, category layout form, and both library list pages (preview / edit / usage). The modal keeps rendering as a full-viewport overlay — .sw-modal stays position: fixed, no ancestor in these subtrees creates a containing block.

Fixed

  • Dropping a media library item failed with HTTP 400 ("This field was not expected"). Captured configs carried the admin's runtime schema hints (media.entity, media.required, …) which DAL's SlotConfigField rejects (allowExtraFields: false). The raw-SQL block sync tolerated them, so they polluted stored configs; the drop writes via the DAL cascade and was rejected. Configs are now sanitized to the persistable { source, value } shape on capture, on apply (repairs already-polluted masters at drop time), and in the section-sync reconcile (so a linked section containing media no longer 400s on save).

Added

  • Multi-language library snapshots (import/export per language). Saving a block/section to the library now captures every language, not just the one active in the editor, and stores it in the snapshot as configByLocale keyed by locale ISO code (de-DE, en-GB) — portable across shops. Dropping/pasting a library item writes those languages back into the new slots' cms_slot_translation rows (locales absent from the target shop are skipped; the active language keeps rendering immediately via slot.config). Export/import inherit this automatically since they round-trip the snapshot JSON. Older single-language snapshots load unchanged. New shared helper service/dmf-cms-i18n.helper.js; capture wired into block + section save, apply wired into all block/section insert paths.

Changed

  • Unlinking a section now fully detaches it. Previously unlink only dropped dmfLinked but kept dmfSavedSectionId (and the child blocks' dmfLinkedSectionId), so the detached section still counted under the library entry's In use list. Unlink now strips all library-origin markers — from the section and every child block — so it becomes a plain, independent section that no longer appears as a usage and is no longer synced. (Sections unlinked under the old behaviour keep their stale markers until re-processed.)

Fixed

  • Dropping a library item while viewing a non-default language. The apply step left the new slot's slot.config (the context-language row + what the editor renders immediately) at the snapshot's base language, only writing the other languages as explicit translations. Dropping while the admin was in a non-base language therefore showed — and, when base ≠ current, persisted — the base language's text for the current language. applySlotConfigByLocale now sets slot.config to the current language's configByLocale entry, so a drop made in German writes and shows German.

  • Linked sections — multi-language content loss. Editing a linked section in one language could overwrite the other languages, so a section maintained in German and English suddenly showed the English text in both. Cause: the section-propagation reconciler (SavedSectionController::reconcileBlocks) matched a target's existing blocks/slots to the source config by array index. Any added, removed or reordered block/slot shifted every following child onto a freshly-minted id — and a fresh cms_slot carries a cms_slot_translation row for the edited language only, so all other languages fell back to the system-default content. Blocks are now reconciled by stable identity (sectionPosition + position) and slots by their slot name, so existing ids — and with them every language's translation row — are preserved. Only genuinely new slots start single-language, exactly like any new CMS slot. Mirrors the linked-block language scoping shipped in 1.3.0.

  • Section library "Sektion bearbeiten" modal — stray "Als verknüpften Block speichern" toggle. The section-library edit modal reuses dmf-save-block-modal but did not pass hide-linked-toggle, so it showed the block-worded linked toggle even for already-linked sections. The toggle was also inert here (the edit only persists name + tags). It is now hidden, matching the block-library edit modal.

  • Linked sync wiped the library master's other languages. While a block/section was linked, every CMS page/category save fired the sync endpoint, which serializes in the edited language only and overwrote the library master snapshot — stripping the multi-language configByLocale. Dropping the (later unlinked) library entry onto a new page then rendered every language in the edited one. SavedSectionController::sync and SavedBlockController::sync now merge the single-language payload into the stored master: structure follows the payload, but each slot keeps the locales it already had and refreshes only the edited locale. The library master stays multi-language across linked edits.

Added

  • Linked sections — save a section as linked (Save as linked section in the Section settings modal). Editing any linked instance propagates its full block/slot structure (add / remove / reorder blocks + all slot configs) to every other linked instance across all pages and categories. Backed by a new is_linked column on dmf_cms_saved_section (migration 1746700000) and a new sync endpoint POST /api/_action/dmf-cms-section-library/{id}/sync.

  • Section library Type column — the Section library list now shows a Linked / Static badge, matching the Block library.

  • Category "Layout" linked marking + usage modal — the category layout form shows a hint banner above the inheritance banner when the layout hosts linked elements, plus a clickable blue Linked section / Linked block badge on each linked element. Clicking a badge opens a usage modal listing every CMS layout that hosts the element and the categories / landing pages assigned to it (current category highlighted, per-layout instance count).

  • CMS-builder stage badges — linked blocks and linked sections now show a blue Linked block / Linked section badge on the stage; the section badge sits at the top-left of sw-cms-section__wrapper.

  • Delete cleanup — deleting a linked block/section from the library now unlinks its live instances (markers stripped → they become plain static copies, content preserved) via a delete-event subscriber.

Changed

  • Cross-category propagation — linked-element edits made in the category Layout tab now propagate. Core sw-category-detail.onSave() persists only the category, so the plugin fires the sync endpoints on save (last-edit-wins across categories).

  • Per-category slot overrides no longer shadow linked content — on every sync, category_translation.slot_config entries for linked slots are stripped, so a linked element always renders the shared, propagated content. Rule: linked = always shared; unlink an element first to give it a per-category variant. Non-linked overrides are preserved.

  • Section sync reuses ids — the section propagation reconciles blocks/slots by reusing existing ids (minting new only for added children, deleting only the surplus) instead of regenerating them, so a versioned page draft never orphans its references.

  • Propagation is admin-triggered — the always-on in-page live mirroring and debounced live library sync were removed. Linked changes now propagate on CMS page save, on category save, and via the Edit linked block / section editor modals.

Fixed

  • Multi-language — linked-block config propagation is now scoped to the edited language (sw-language-id header + cms_slot_translation.language_id filter). Editing a linked block in one language no longer overwrites the other languages.

  • Duplicate instances — when the same linked block/section appears more than once on a page, the edited instance is now identified by comparing against the library baseline, so editing the second (or any) copy no longer loses the edit.

  • Section save 400 — saving a page containing a linked section no longer fails with type/position should not be blank (id-reuse) and sizing_mode never writes NULL.

  • Category save 400 — removed a redundant full cms_page save from the category write-through.

  • Missing styling for the linked panel in the Section settings modal.

Added

  • Section-level visibility controls in the Section settings modal (gear icon → new Sichtbarkeit / Visibility tab):

    • Display rule — pick a Shopware Rule Builder rule; section is hidden when the rule does not match (silent hide).
    • Schedule — from / until datetime range; section is hidden outside the window.
  • Visibility state stored under cms_section.custom_fields.dmfSectionVisibility. Persisted on modal close via PATCH /cms-section/{id} (no DAL migration).

  • Twig override on @Storefront/storefront/page/content/detail.html.twig gates section rendering server-side around the page_content_section block.

Added

  • New Sichtbarkeit / Visibility section in the CMS block settings sidebar with an Edit visibility rules button that opens a modal:

    • Display rule — pick a Shopware Rule Builder rule; block is hidden when the rule does not match the current sales-channel context (silent hide).
    • Schedule — from / until datetime range; block is hidden outside the window.
  • Visibility state stored under cms_block.custom_fields.dmfBlockVisibility — no DAL migration.

  • Twig override on @Storefront/storefront/section/cms-section-block-container.html.twig gates block rendering server-side.

Changed

  • DmfCmsBlockLibrary::getTemplatePriority() returns 100 so the visibility wrapper composes after lower-priority CMS section overrides (e.g. DmfCmsDynamicGrid).

Added

  • Saved Blocks library with admin overview under Inhalte → Erlebniswelten Block-Übersicht.

  • "Save as block" quickaction in the CMS block settings sidebar.

  • "Saved blocks" picker category with drag-drop to stage.

  • JSON import / export endpoints (/api/_action/dmf-cms-block-library/{import,export}).

  • Block copy / paste-before / paste-after quickactions (sessionStorage clipboard).

  • Section copy / paste-before / paste-after context-menu items.

  • DAL entity dmf_cms_saved_block (auto-CRUD via REST + search routes).

  • German and English snippets.