From 6829ced4bfeb32710477c570fe1f7dcfee56fdde Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 3 Aug 2022 13:57:16 +0200 Subject: [PATCH 01/18] IBX-3523: Introduced tabs to left sidebar in Content Edit interface --- .../Resources/encore/ibexa.js.config.js | 1 + .../js/scripts/admin.anchor.navigation.js | 4 + .../admin.anchor.sections.navigation.js | 156 ++++++++++++++++++ .../public/js/scripts/admin.content.edit.js | 18 -- .../Resources/public/scss/_content-edit.scss | 8 + .../public/scss/_main-container.scss | 4 +- .../public/scss/_navigation-menu.scss | 96 +++++++++++ src/bundle/Resources/public/scss/ibexa.scss | 1 + .../admin/ui/anchor_navigation_menu.html.twig | 35 ++-- .../ui/anchor_navigation_section.html.twig | 4 +- 10 files changed, 288 insertions(+), 39 deletions(-) create mode 100644 src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js create mode 100644 src/bundle/Resources/public/scss/_navigation-menu.scss diff --git a/src/bundle/Resources/encore/ibexa.js.config.js b/src/bundle/Resources/encore/ibexa.js.config.js index 003477ff53..50c3ad943c 100644 --- a/src/bundle/Resources/encore/ibexa.js.config.js +++ b/src/bundle/Resources/encore/ibexa.js.config.js @@ -55,6 +55,7 @@ const layout = [ path.resolve(__dirname, '../public/js/scripts/autogenerate.identifier.js'), path.resolve(__dirname, '../public/js/scripts/admin.back.to.top.js'), path.resolve(__dirname, '../public/js/scripts/admin.middle.ellipsis.js'), + path.resolve(__dirname, '../public/js/scripts/admin.anchor.sections.navigation'), ]; const fieldTypes = []; diff --git a/src/bundle/Resources/public/js/scripts/admin.anchor.navigation.js b/src/bundle/Resources/public/js/scripts/admin.anchor.navigation.js index ad9c9da6ed..81d5a2eaec 100644 --- a/src/bundle/Resources/public/js/scripts/admin.anchor.navigation.js +++ b/src/bundle/Resources/public/js/scripts/admin.anchor.navigation.js @@ -1,4 +1,8 @@ (function (global, doc) { + if (doc.querySelector('.ibexa-navigation-menu')) { + return; + } + const EDIT_CONTENT_TOP_PADDING = 42; const formContainerNode = doc.querySelector('.ibexa-edit-content'); const allSections = [...doc.querySelectorAll('.ibexa-anchor-navigation-sections__section')]; diff --git a/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js b/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js new file mode 100644 index 0000000000..fe6e3b499e --- /dev/null +++ b/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js @@ -0,0 +1,156 @@ +(function (global, doc) { + if (!doc.querySelector('.ibexa-navigation-menu')) { + return; + } + + const SECTION_ADJUST_MARGIN_TOP = 20; + const formContainerNode = doc.querySelector('.ibexa-edit-content'); + const getSecondarySectionActiveItems = () => { + const secondarySectionItems = formContainerNode.querySelectorAll( + '.ibexa-edit-content__primary-section--active .ibexa-edit-content__secondary-section', + ); + + return [...secondarySectionItems]; + }; + let currentlyVisibleSections = getSecondarySectionActiveItems(); + const fitSecondarySections = () => { + const primarySection = doc.querySelector('.ibexa-edit-content__primary-section--active'); + const contentColumn = doc.querySelector('.ibexa-main-container__content-column'); + const firstSection = primarySection.querySelector('.ibexa-edit-content__secondary-section:first-child'); + const lastSection = primarySection.querySelector('.ibexa-edit-content__secondary-section:last-child'); + const contentContainer = contentColumn.querySelector('.ibexa-edit-content__container'); + + contentContainer.style.paddingBottom = '0px'; + + if (!firstSection.isSameNode(lastSection) && lastSection && lastSection.offsetHeight) { + const headerContainer = doc.querySelector('.ibexa-edit-header .ibexa-edit-header__container'); + const heightFromLastSection = contentContainer.offsetHeight - lastSection.offsetTop; + const contentColumnBodyHeight = contentColumn.offsetHeight - headerContainer.offsetHeight; + const heightDiff = contentColumnBodyHeight - heightFromLastSection; + + if (heightDiff > 0) { + contentContainer.style.paddingBottom = `${heightDiff}px`; + } + } + }; + const navigateTo = (targetId) => { + const secondarySectionNode = formContainerNode.querySelector(`.ibexa-edit-content__secondary-section[data-id="${targetId}"]`); + + formContainerNode.scrollTo({ + top: secondarySectionNode.offsetTop, + behavior: 'smooth', + }); + }; + const setActiveSecondaryMenu = (node) => { + const secondaryMenuItems = doc.querySelectorAll( + '.ibexa-navigation-menu__secondary--active .ibexa-navigation-menu__secondary-item-btn', + ); + + secondaryMenuItems.forEach((item) => { + item.classList.toggle('ibexa-navigation-menu__secondary-item-btn--active', item.isSameNode(node)); + }); + }; + const showPrimarySection = (id) => { + const primarySectionItems = formContainerNode.querySelectorAll('.ibexa-edit-content__primary-section'); + + primarySectionItems.forEach((item) => { + item.classList.toggle('ibexa-edit-content__primary-section--active', item.dataset.id === id); + }); + + currentlyVisibleSections = getSecondarySectionActiveItems(); + + fitSecondarySections(); + }; + const showSecondaryMenu = (node) => { + const items = doc.querySelectorAll('.ibexa-navigation-menu__secondary'); + + items.forEach((item) => item.classList.toggle('ibexa-navigation-menu__secondary--active', item.isSameNode(node))); + }; + const onSelectPrimaryMenuList = (event) => { + const { targetId } = event.target.dataset; + const secondaryMenuNode = doc.querySelector(`.ibexa-navigation-menu__secondary[data-id="${targetId}"]`); + const primaryMenuItems = doc.querySelectorAll('.ibexa-navigation-menu__primary--list .ibexa-navigation-menu__primary-item'); + + primaryMenuItems.forEach((item) => { + item.classList.toggle('ibexa-navigation-menu__primary-item--active', item.isSameNode(event.target)); + }); + showPrimarySection(targetId); + + if (secondaryMenuNode) { + showSecondaryMenu(secondaryMenuNode); + } + }; + const onSelectPrimaryMenuDropdown = (event) => { + const targetId = event.target.value; + const secondaryMenuNode = doc.querySelector(`.ibexa-navigation-menu__secondary[data-id="${targetId}"]`); + + showPrimarySection(targetId); + + if (secondaryMenuNode) { + showSecondaryMenu(secondaryMenuNode); + } + }; + const onSelectSecondaryMenu = (event) => { + const { targetId } = event.currentTarget.dataset; + + navigateTo(targetId); + }; + const bindPrimaryMenuListEvents = () => { + const items = doc.querySelectorAll('.ibexa-navigation-menu__primary--list .ibexa-navigation-menu__primary-item'); + + items.forEach((item) => item.addEventListener('click', onSelectPrimaryMenuList, false)); + }; + const bindPrimaryMenuDropdownEvents = () => { + const sourceSelect = doc.querySelector('.ibexa-navigation-menu__primary--dropdown .ibexa-dropdown__source .ibexa-input'); + + if (!sourceSelect) { + return; + } + + sourceSelect.addEventListener('change', onSelectPrimaryMenuDropdown, false); + }; + const bindSecondaryMenuEvents = () => { + const items = doc.querySelectorAll('.ibexa-navigation-menu .ibexa-navigation-menu__secondary-item-btn'); + + items.forEach((item) => item.addEventListener('click', onSelectSecondaryMenu, false)); + }; + const bindScrollContainerEvents = () => { + const allSections = [...doc.querySelectorAll('.ibexa-edit-content__secondary-section')]; + const headerContainer = doc.querySelector('.ibexa-edit-header .ibexa-edit-header__container'); + let previousFirstVisibleSection = null; + + if (formContainerNode && allSections.length) { + formContainerNode.addEventListener('scroll', () => { + let firstVisibleSection = currentlyVisibleSections.find((section) => { + const { top, height } = section.getBoundingClientRect(); + + return top + height >= headerContainer.offsetHeight + SECTION_ADJUST_MARGIN_TOP; + }); + + if (!firstVisibleSection) { + firstVisibleSection = currentlyVisibleSections.at(-1); + } + + if (previousFirstVisibleSection === firstVisibleSection) { + return; + } + + previousFirstVisibleSection = firstVisibleSection; + + const targetId = firstVisibleSection.dataset.id; + + const secondaryMenuNode = doc.querySelector( + `.ibexa-navigation-menu__secondary--active .ibexa-navigation-menu__secondary-item-btn[data-target-id="${targetId}"]`, + ); + + setActiveSecondaryMenu(secondaryMenuNode); + }); + } + }; + + bindPrimaryMenuListEvents(); + bindPrimaryMenuDropdownEvents(); + bindSecondaryMenuEvents(); + bindScrollContainerEvents(); + fitSecondarySections(); +})(window, window.document); diff --git a/src/bundle/Resources/public/js/scripts/admin.content.edit.js b/src/bundle/Resources/public/js/scripts/admin.content.edit.js index e9a8b6562f..db6d4cfc99 100644 --- a/src/bundle/Resources/public/js/scripts/admin.content.edit.js +++ b/src/bundle/Resources/public/js/scripts/admin.content.edit.js @@ -130,22 +130,6 @@ const isAutosaveEnabled = () => { return ibexa.adminUiConfig.autosave.enabled && form.querySelector('[name="ezplatform_content_forms_content_edit[autosave]"]'); }; - const fitSections = () => { - const lastSection = doc.querySelector('.ibexa-anchor-navigation-sections .ibexa-anchor-navigation-sections__section:last-child'); - - if (lastSection && lastSection.offsetHeight) { - const contentColumn = doc.querySelector('.ibexa-main-container__content-column'); - const contentContainer = contentColumn.querySelector('.ibexa-edit-content__container'); - const headerContainer = doc.querySelector('.ibexa-edit-header .ibexa-edit-header__container'); - const heightFromLastSection = contentContainer.offsetHeight - lastSection.offsetTop; - const contentColumnBodyHeight = contentColumn.offsetHeight - headerContainer.offsetHeight; - const heightDiff = contentColumnBodyHeight - heightFromLastSection; - - if (heightDiff > 0) { - contentContainer.style.paddingBottom = `${heightDiff}px`; - } - } - }; if (isAutosaveEnabled()) { const AUTOSAVE_SUBMIT_BUTTON_NAME = 'ezplatform_content_forms_content_edit[autosave]'; @@ -232,8 +216,6 @@ btn.addEventListener('click', clickHandler, false); }); - fitSections(); - menuButtonsToValidate.forEach((btn) => { btn.addEventListener('click', validateHandler, false); }); diff --git a/src/bundle/Resources/public/scss/_content-edit.scss b/src/bundle/Resources/public/scss/_content-edit.scss index 210616d651..f05c3da525 100644 --- a/src/bundle/Resources/public/scss/_content-edit.scss +++ b/src/bundle/Resources/public/scss/_content-edit.scss @@ -8,4 +8,12 @@ max-width: calculateRem(1600px); } } + + &__primary-section { + display: none; + + &--active { + display: block; + } + } } diff --git a/src/bundle/Resources/public/scss/_main-container.scss b/src/bundle/Resources/public/scss/_main-container.scss index 570930d300..74b1d6b120 100644 --- a/src/bundle/Resources/public/scss/_main-container.scss +++ b/src/bundle/Resources/public/scss/_main-container.scss @@ -16,8 +16,8 @@ &--without-anchor-menu-items { .ibexa-main-container { &__side-column { - width: 15%; - max-width: calculateRem(200px); + min-width: calculateRem(240px); + max-width: calculateRem(240px); } &__content-column { diff --git a/src/bundle/Resources/public/scss/_navigation-menu.scss b/src/bundle/Resources/public/scss/_navigation-menu.scss new file mode 100644 index 0000000000..084d992ef7 --- /dev/null +++ b/src/bundle/Resources/public/scss/_navigation-menu.scss @@ -0,0 +1,96 @@ +.ibexa-navigation-menu { + padding: calculateRem(25px); + font-size: $ibexa-text-font-size-medium; + + &__primary { + height: calculateRem(48px); + padding: calculateRem(4px); + border-radius: $ibexa-border-radius; + background-color: $ibexa-color-light-300; + display: flex; + } + + &__primary-item { + height: calculateRem(40px); + padding: calculateRem(10px); + border-radius: $ibexa-border-radius; + border: 0; + flex-basis: 100%; + text-align: center; + + &--active { + background-color: $ibexa-color-white; + font-weight: 600; + } + } + + &__secondary { + margin: calculateRem(24px) 0 0; + padding: calculateRem(24px) 0 0; + list-style: none; + display: none; + border-top: calculateRem(1px) solid $ibexa-color-light; + + &--active { + display: block; + } + } + + &__secondary-item-btn { + display: inline-flex; + width: 100%; + padding: calculateRem(11px) calculateRem(15px); + border: calculateRem(1px) solid transparent; + border-radius: $ibexa-border-radius; + text-align: left; + + &::before { + content: ''; + display: block; + width: calculateRem(8px); + height: calculateRem(8px); + margin: calculateRem(8px) calculateRem(16px) 0 0; + border-radius: 50%; + background-color: $ibexa-color-light; + } + + &::after { + content: '*'; + width: calculateRem(16px); + display: inline-block; + opacity: 0; + margin: calculateRem(4px) 0 0 calculateRem(4px); + color: $ibexa-color-danger; + font-size: $ibexa-text-font-size-small; + } + + &:hover { + color: $ibexa-color-info; + font-weight: 600; + + &:before { + background-color: $ibexa-color-info; + } + } + + &--active { + color: $ibexa-color-info; + background: $ibexa-color-info-100; + font-weight: 600; + + &:before { + background-color: $ibexa-color-info; + } + } + + &--invalid { + &:after { + opacity: 1; + } + } + } + + &__secondary-item-label { + max-width: calc(100% - #{calculateRem(45px)}); + } +} diff --git a/src/bundle/Resources/public/scss/ibexa.scss b/src/bundle/Resources/public/scss/ibexa.scss index f1c14b25a3..ee0fa08d7b 100644 --- a/src/bundle/Resources/public/scss/ibexa.scss +++ b/src/bundle/Resources/public/scss/ibexa.scss @@ -118,3 +118,4 @@ @import 'user-group-invitation'; @import 'user-invitation-modal'; @import 'default-location'; +@import 'navigation-menu'; diff --git a/src/bundle/Resources/views/themes/admin/ui/anchor_navigation_menu.html.twig b/src/bundle/Resources/views/themes/admin/ui/anchor_navigation_menu.html.twig index 386d3f0807..a220a8a39a 100644 --- a/src/bundle/Resources/views/themes/admin/ui/anchor_navigation_menu.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/anchor_navigation_menu.html.twig @@ -16,22 +16,23 @@
- {% if items|default([])|length > 1 %} - - {% endif %} + {% block navigation_menu_body %} + {% if items|default([])|length > 1 %} + + {% endif %} + {% endblock %}
diff --git a/src/bundle/Resources/views/themes/admin/ui/anchor_navigation_section.html.twig b/src/bundle/Resources/views/themes/admin/ui/anchor_navigation_section.html.twig index e81aadf5e0..4d8bc446fe 100644 --- a/src/bundle/Resources/views/themes/admin/ui/anchor_navigation_section.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/anchor_navigation_section.html.twig @@ -1,6 +1,6 @@
{% block anchor_section_content %} {% block anchor_section_header %}{% endblock %} From 10bc6838edc7c51b9aebd50f4416d8634a6a8a35 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 3 Aug 2022 13:58:32 +0200 Subject: [PATCH 02/18] IBX-3523: Created new menu `content_edit_anchor_menu` --- .../Resources/config/services/menu.yaml | 5 + .../Resources/translations/menu.en.xliff | 10 + .../themes/admin/content/edit_base.html.twig | 63 ++++--- .../admin/ui/menu/anchor_menu.html.twig | 178 ++++++++++++++++++ src/lib/Menu/ContentEditAnchorMenuBuilder.php | 169 +++++++++++++++++ src/lib/Menu/Event/ConfigureMenuEvent.php | 1 + 6 files changed, 402 insertions(+), 24 deletions(-) create mode 100644 src/bundle/Resources/views/themes/admin/ui/menu/anchor_menu.html.twig create mode 100644 src/lib/Menu/ContentEditAnchorMenuBuilder.php diff --git a/src/bundle/Resources/config/services/menu.yaml b/src/bundle/Resources/config/services/menu.yaml index eb93d2bf80..fe6e12856c 100644 --- a/src/bundle/Resources/config/services/menu.yaml +++ b/src/bundle/Resources/config/services/menu.yaml @@ -45,6 +45,11 @@ services: tags: - { name: knp_menu.menu_builder, method: build, alias: ezplatform_admin_ui.menu.content_edit.sidebar_right } + Ibexa\AdminUi\Menu\ContentEditAnchorMenuBuilder: + public: true + tags: + - { name: knp_menu.menu_builder, method: build, alias: ibexa.admin_ui.menu.content_edit.anchor_menu } + Ibexa\AdminUi\Menu\ContentCreateRightSidebarBuilder: public: true tags: diff --git a/src/bundle/Resources/translations/menu.en.xliff b/src/bundle/Resources/translations/menu.en.xliff index 8e79427846..6463073288 100644 --- a/src/bundle/Resources/translations/menu.en.xliff +++ b/src/bundle/Resources/translations/menu.en.xliff @@ -76,6 +76,16 @@ Save key: content_create__sidebar_right__save_draft + + Content + Content + key: content_edit__anchor_menu__content + + + Meta + Meta + key: content_edit__anchor_menu__meta + Delete draft Delete draft diff --git a/src/bundle/Resources/views/themes/admin/content/edit_base.html.twig b/src/bundle/Resources/views/themes/admin/content/edit_base.html.twig index 552554b327..6b6c070e20 100644 --- a/src/bundle/Resources/views/themes/admin/content/edit_base.html.twig +++ b/src/bundle/Resources/views/themes/admin/content/edit_base.html.twig @@ -20,7 +20,20 @@ }) %} {% endif %} - {% include '@ibexadesign/ui/anchor_navigation_menu.html.twig' with anchor_params %} + {% set content_edit_anchor_menu = knp_menu_get('ibexa.admin_ui.menu.content_edit.anchor_menu', [], { + 'content': content, + 'content_type': content_type, + 'location': location, + 'parent_location': parent_location, + 'language': language, + 'grouped_fields': grouped_fields, + }) %} + + {% embed '@ibexadesign/ui/anchor_navigation_menu.html.twig' with anchor_params %} + {% block navigation_menu_body %} + {{ knp_menu_render(content_edit_anchor_menu, { 'template': '@ibexadesign/ui/menu/anchor_menu.html.twig' }) }} + {% endblock %} + {% endembed %} {% endblock %} {% macro renderFormField(formField) -%} @@ -53,29 +66,31 @@ {% block form %} {{ form_start(form, {'attr': {'class': 'ibexa-form-validate ibexa-form'}}) }} - {% block form_fields %} - {% if grouped_fields|length > 1 %} -
- {% for key, group in grouped_fields %} - {% embed '@ibexadesign/ui/anchor_navigation_section.html.twig' with { - anchor_section_key: key, - parent_self: _self, - } %} - {% trans_default_domain 'content_edit' %} - {% import parent_self as parent_self %} - - {% block anchor_section_body %} - {{ parent_self.renderFieldGroup(group, form) }} - {% endblock %} - {% endembed %} - {% endfor %} -
- {% else %} - {% for formField in form.fieldsData %} - {{ _self.renderFormField(formField) }} - {%- endfor %} - {% endif %} - {% endblock %} +
+
+ {% block form_fields %} +
+ {% for key, group in grouped_fields %} + {% embed '@ibexadesign/ui/anchor_navigation_section.html.twig' with { + anchor_section_key: 'ibexa-edit-content-sections-content-fields-' ~ key|lower, + parent_self: _self, + } %} + {% trans_default_domain 'content_edit' %} + {% import parent_self as parent_self %} + + {% block anchor_section_body %} + {{ parent_self.renderFieldGroup(group, form) }} + {% endblock %} + {% endembed %} + {% endfor %} +
+ {% endblock %} +
+ {% block content_sections %}{% endblock %} +
{{ form_end(form) }} {% endblock %} diff --git a/src/bundle/Resources/views/themes/admin/ui/menu/anchor_menu.html.twig b/src/bundle/Resources/views/themes/admin/ui/menu/anchor_menu.html.twig new file mode 100644 index 0000000000..9ae16fddcf --- /dev/null +++ b/src/bundle/Resources/views/themes/admin/ui/menu/anchor_menu.html.twig @@ -0,0 +1,178 @@ +{% extends '@KnpMenu/menu.html.twig' %} + +{% block anchor_menu_list %} + {% if item.hasChildren and options.depth is not same as(0) and item.displayChildren %} + {% import _self as knp_menu %} + <{{ tagElement }}{{ knp_menu.attributes(listAttributes) }}> + {{ block('anchor_menu_children') }} + + {% endif %} +{% endblock %} + +{% block anchor_menu_children %} + {# save current variables #} + {% set currentOptions = options %} + {% set currentItem = item %} + {# update the depth for children #} + {% if options.depth is not none %} + {% set options = options|merge({'depth': currentOptions.depth - 1}) %} + {% endif %} + {# update the matchingDepth for children #} + {% if options.matchingDepth is not none and options.matchingDepth > 0 %} + {% set options = options|merge({'matchingDepth': currentOptions.matchingDepth - 1}) %} + {% endif %} + + {{ block(innerChildrenBlock|default('children')) }} + + {# restore current variables #} + {% set item = currentItem %} + {% set options = currentOptions %} +{% endblock %} + +{% block children_1st_level %} + {% for item in currentItem.children %} + {%- set itemClass = 'ibexa-navigation-menu__primary-item' %} + {%- if loop.first %} + {%- set itemClass = itemClass ~ ' ibexa-navigation-menu__primary-item--active' %} + {%- endif %} + {%- do item.setAttribute('class', (item.getAttribute('class') ~ ' ' ~ itemClass)|trim) -%} + {%- do item.setAttribute('type', 'button') -%} + {{ block('anchor_menu_item') }} + {% endfor %} +{% endblock %} + +{% block children_1st_level_dropdown %} + {% for item in currentItem.children %} + {%- set itemClass = 'ibexa-navigation-menu__primary-item' %} + {%- if loop.first %} + {%- set itemClass = itemClass ~ ' ibexa-navigation-menu__primary-item--active' %} + {%- endif %} + {%- do item.setAttribute('class', (item.getAttribute('class') ~ ' ' ~ itemClass)|trim) -%} + {%- do item.setAttribute('type', 'button') -%} + {% endfor %} + + {% set value = '' %} + {% set choices = [] %} + {% for item in currentItem.children %} + {% if loop.first %} + {% set value = item.getAttribute('data-target-id') %} + {% endif %} + {% set choices = choices|merge([{ + value: item.getAttribute('data-target-id'), + label: block('label'), + }]) %} + {% endfor %} + + {% set source %} + + {% endset %} + + {% include '@ibexadesign/ui/component/dropdown/dropdown.html.twig' with { + source: source, + choices: choices, + value: value, + } %} +{% endblock %} + +{% block children_2nd_level %} + {% for item in currentItem.children %} + {%- set itemClass = 'ibexa-navigation-menu__secondary-item-btn' %} + {%- if loop.first %} + {%- set itemClass = itemClass ~ ' ibexa-navigation-menu__secondary-item-btn--active' %} + {%- endif %} + {%- do item.setAttribute('class', (item.getAttribute('class') ~ ' ' ~ itemClass)|trim) -%} + {%- do item.setAttribute('type', 'button') -%} + {%- do item.setLabelAttribute('class', 'ibexa-navigation-menu__secondary-item-btn-label') -%} + {{ block('anchor_menu_item') }} + {% endfor %} +{% endblock %} + +{% block anchor_menu_item %} + {% if item.displayed %} + {# building the class of the item #} + {%- set classes = item.attribute('class') is not empty ? [item.attribute('class')] : [] %} + {%- if matcher.isCurrent(item) %} + {%- set classes = classes|merge([options.currentClass]) %} + {%- elseif matcher.isAncestor(item, options.matchingDepth) %} + {%- set classes = classes|merge([options.ancestorClass]) %} + {%- endif %} + {%- if item.actsLikeFirst %} + {%- set classes = classes|merge([options.firstClass]) %} + {%- endif %} + {%- if item.actsLikeLast %} + {%- set classes = classes|merge([options.lastClass]) %} + {%- endif %} + + {# Mark item as "leaf" (no children) or as "branch" (has children that are displayed) #} + {% if item.hasChildren and options.depth is not same as(0) %} + {% if options.branch_class is not empty and item.displayChildren %} + {%- set classes = classes|merge([options.branch_class]) %} + {% endif %} + {% elseif options.leaf_class is not empty %} + {%- set classes = classes|merge([options.leaf_class]) %} + {%- endif %} + + {%- set attributes = item.attributes %} + {%- if classes is not empty %} + {%- set attributes = attributes|merge({'class': classes|join(' ')}) %} + {%- endif %} + + {{ block(innerItemBlock|default('item')) }} + {% endif %} +{% endblock %} + +{% block item_1st_level %} + {% import _self as knp_menu %} + + {%- set itemTagElement = itemTagElement|default('button') %} + + <{{ itemTagElement }}{{ knp_menu.attributes(attributes) }}> + {{ block('label') }} + +{% endblock %} + +{% block item_2nd_level %} + {% import _self as knp_menu %} + + {%- set itemTagElement = itemTagElement|default('button') %} + +
  • + <{{ itemTagElement }}{{ knp_menu.attributes(attributes) }}> + {{ block('label') }} + +
  • +{% endblock %} + +{% block root %} +
    + {% if item.count() < 4 %} + {% set listAttributes = item.childrenAttributes|merge({'class': (listAttributes.class|default('') ~ ' ibexa-navigation-menu__primary ibexa-navigation-menu__primary--list')|trim}) %} + {% set innerChildrenBlock = 'children_1st_level' %} + {% set innerItemBlock = 'item_1st_level' %} + {% set tagElement = 'div' %} + {% set itemTagElement = 'button' %} + {% else %} + {% set listAttributes = item.childrenAttributes|merge({'class': (listAttributes.class|default('') ~ ' ibexa-navigation-menu__dropdown-wrapper ibexa-navigation-menu__primary--dropdown')|trim}) %} + {% set innerChildrenBlock = 'children_1st_level_dropdown' %} + {% set tagElement = 'div' %} + {% endif %} + {{ block('anchor_menu_list') -}} + +
    + {% for item in item.children %} + {% set listAttributes = {'class': 'ibexa-navigation-menu__secondary' ~ (loop.first ? ' ibexa-navigation-menu__secondary--active' : ''), 'data-id': item.getAttribute('data-target-id')} %} + {% set innerChildrenBlock = 'children_2nd_level' %} + {% set innerItemBlock = 'item_2nd_level' %} + {% set tagElement = 'ul' %} + {% set itemTagElement = 'button' %} + {{ block('anchor_menu_list') -}} + {% endfor %} +
    +
    +{% endblock %} diff --git a/src/lib/Menu/ContentEditAnchorMenuBuilder.php b/src/lib/Menu/ContentEditAnchorMenuBuilder.php new file mode 100644 index 0000000000..b6b82a84a3 --- /dev/null +++ b/src/lib/Menu/ContentEditAnchorMenuBuilder.php @@ -0,0 +1,169 @@ +configResolver = $configResolver; + } + + /** + * @return string + */ + protected function getConfigureEventName(): string + { + return ConfigureMenuEvent::CONTENT_EDIT_ANCHOR_MENU; + } + + /** + * @param array $options + */ + public function createStructure(array $options): ItemInterface + { + /** @var \Knp\Menu\ItemInterface|\Knp\Menu\ItemInterface[] $menu */ + $menu = $this->factory->createItem('root'); + + /** @var \Ibexa\Core\Repository\Values\ContentType\ContentType $contentType */ + $contentType = $options['content_type']; + + /** @var array> $groupedFields */ + $groupedFields = $options['grouped_fields']; + + $items = [ + self::ITEM__CONTENT => $this->createMenuItem( + self::ITEM__CONTENT, + [ + 'attributes' => ['data-target-id' => 'ibexa-edit-content-sections-content-fields'], + 'extras' => [ + 'orderNumber' => 10, + ], + ] + ), + ]; + + $items[self::ITEM__CONTENT]->setChildren( + $this->getContentFieldGroupItems($groupedFields) + ); + + $metaFields = $this->getMetaFieldItems($contentType); + + if (!empty($metaFields)) { + $items[self::ITEM__META] = $this->createMenuItem( + self::ITEM__META, + [ + 'attributes' => ['data-target-id' => 'ibexa-edit-content-sections-meta'], + 'extras' => [ + 'orderNumber' => 50, + ], + ] + ); + + $items[self::ITEM__META]->setChildren($metaFields); + } + + $menu->setChildren($items); + + return $menu; + } + + /** + * @param array> $groupedFields + * + * @return array<\Knp\Menu\ItemInterface> + */ + private function getContentFieldGroupItems(array $groupedFields): array + { + $items = []; + $order = 0; + foreach ($groupedFields as $group => $fields) { + $order = $order + 10; + $items[$group] = $this->createMenuItem($group, [ + 'attributes' => [ + 'data-target-id' => sprintf('ibexa-edit-content-sections-content-fields-%s', mb_strtolower($group)), + ], + 'extras' => [ + 'orderNumber' => $order, + ], + ]); + } + + return $items; + } + + /** + * @param array> $groupedFields + * + * @return array<\Knp\Menu\ItemInterface> + */ + private function getMetaFieldItems(ContentType $contentType): array + { + $fieldTypeSettings = $this->configResolver->getParameter('admin_ui_forms.content_edit.fieldtypes'); + $metaFieldTypeIdentifiers = array_keys(array_filter( + $fieldTypeSettings, + static fn (array $config) => true === $config['meta'] + )); + + $order = 0; + foreach ($metaFieldTypeIdentifiers as $metaFieldTypeIdentifier) { + if (false === $contentType->hasFieldDefinitionOfType($metaFieldTypeIdentifier)) { + continue; + } + + $fieldDefinitions = $contentType->getFieldDefinitionsOfType($metaFieldTypeIdentifier); + foreach ($fieldDefinitions as $fieldDefinition) { + $fieldDefIdentifier = $fieldDefinition->identifier; + $order = $order + 10; + $items[$fieldDefIdentifier] = $this->createMenuItem( + $fieldDefIdentifier, + [ + 'label' => $fieldDefinition->getName(), + 'attributes' => [ + 'data-target-id' => sprintf('ibexa-edit-content-sections-meta-%s', $fieldDefIdentifier), + ], + 'extras' => [ + 'orderNumber' => $order, + ], + ] + ); + } + } + + return $items; + } + + /** + * @return array<\JMS\TranslationBundle\Model\Message> + */ + public static function getTranslationMessages(): array + { + return [ + (new Message(self::ITEM__CONTENT, 'menu'))->setDesc('Content'), + (new Message(self::ITEM__META, 'menu'))->setDesc('Meta'), + ]; + } +} diff --git a/src/lib/Menu/Event/ConfigureMenuEvent.php b/src/lib/Menu/Event/ConfigureMenuEvent.php index 695b067809..994814011f 100644 --- a/src/lib/Menu/Event/ConfigureMenuEvent.php +++ b/src/lib/Menu/Event/ConfigureMenuEvent.php @@ -21,6 +21,7 @@ class ConfigureMenuEvent extends Event public const USER_MENU = 'ezplatform_admin_ui.menu_configure.user_menu'; public const CONTENT_SIDEBAR_RIGHT = 'ezplatform_admin_ui.menu_configure.content_sidebar_right'; public const CONTENT_EDIT_SIDEBAR_RIGHT = 'ezplatform_admin_ui.menu_configure.content_edit_sidebar_right'; + public const CONTENT_EDIT_ANCHOR_MENU = 'ibexa.admin_ui.menu_configure.content_edit_anchor_menu'; public const CONTENT_CREATE_SIDEBAR_RIGHT = 'ezplatform_admin_ui.menu_configure.content_create_sidebar_right'; public const CONTENT_SIDEBAR_LEFT = 'ezplatform_admin_ui.menu_configure.content_sidebar_left'; public const TRASH_SIDEBAR_RIGHT = 'ezplatform_admin_ui.menu_configure.trash_sidebar_right'; From 2a018dbbc32d21be287e8fdb878663f3bd3dfb33 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 3 Aug 2022 13:59:17 +0200 Subject: [PATCH 03/18] IBX-3523: Created new component displaying meta fieldtypes form --- .../services/components/content/edit.yaml | 4 ++ .../content/components/meta_fields.html.twig | 15 ++++ .../themes/admin/content/edit/edit.html.twig | 11 +++ .../primary_section.html.twig | 8 +++ .../secondary_section.html.twig | 6 ++ .../ContentEditMetaFieldsComponent.php | 68 +++++++++++++++++++ 6 files changed, 112 insertions(+) create mode 100644 src/bundle/Resources/views/themes/admin/content/components/meta_fields.html.twig create mode 100644 src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/primary_section.html.twig create mode 100644 src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/secondary_section.html.twig create mode 100644 src/lib/Component/Content/ContentEditMetaFieldsComponent.php diff --git a/src/bundle/Resources/config/services/components/content/edit.yaml b/src/bundle/Resources/config/services/components/content/edit.yaml index 274ea2ff2a..52099e02a2 100644 --- a/src/bundle/Resources/config/services/components/content/edit.yaml +++ b/src/bundle/Resources/config/services/components/content/edit.yaml @@ -7,3 +7,7 @@ services: Ibexa\AdminUi\Component\Content\PreviewUnavailableTwigComponent: tags: - { name: ibexa.admin_ui.component, group: 'content-edit-form-before' } + + Ibexa\AdminUi\Component\Content\ContentEditMetaFieldsComponent: + tags: + - { name: ibexa.admin_ui.component, group: 'content-edit-sections' } diff --git a/src/bundle/Resources/views/themes/admin/content/components/meta_fields.html.twig b/src/bundle/Resources/views/themes/admin/content/components/meta_fields.html.twig new file mode 100644 index 0000000000..83d5566b9c --- /dev/null +++ b/src/bundle/Resources/views/themes/admin/content/components/meta_fields.html.twig @@ -0,0 +1,15 @@ +{% extends '@ibexadesign/ui/component/anchor_navigation/primary_section.html.twig' %} + +{% set data_id = 'ibexa-edit-content-sections-meta' %} + +{% block sections %} + {% for identifier in meta_fields %} + {% embed '@ibexadesign/ui/component/anchor_navigation/secondary_section.html.twig' with {'form': form, 'identifier': identifier} %} + {% set data_id = 'ibexa-edit-content-sections-meta-' ~ identifier %} + {% block content %} + {% import '@ibexadesign/content/edit_base.html.twig' as edit_base %} + {{ edit_base.renderFormField(form.fieldsData[identifier]) }} + {% endblock %} + {% endembed %} + {% endfor %} +{% endblock %} diff --git a/src/bundle/Resources/views/themes/admin/content/edit/edit.html.twig b/src/bundle/Resources/views/themes/admin/content/edit/edit.html.twig index 748678d1e6..ea966cc7a5 100644 --- a/src/bundle/Resources/views/themes/admin/content/edit/edit.html.twig +++ b/src/bundle/Resources/views/themes/admin/content/edit/edit.html.twig @@ -51,6 +51,17 @@
    {% endblock %} +{% block content_sections %} + {{ ibexa_render_component_group('content-edit-sections', { + 'form': form, + 'content': content, + 'content_type': content_type, + 'location': location, + 'parent_location': parent_location, + 'language': language + }) }} +{% endblock %} + {% block form_after %} {{ ibexa_render_component_group('content-edit-form-after', { 'content': content, diff --git a/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/primary_section.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/primary_section.html.twig new file mode 100644 index 0000000000..d1ce150bea --- /dev/null +++ b/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/primary_section.html.twig @@ -0,0 +1,8 @@ +
    +
    + {% block sections %}{% endblock %} +
    +
    diff --git a/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/secondary_section.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/secondary_section.html.twig new file mode 100644 index 0000000000..335765ef51 --- /dev/null +++ b/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/secondary_section.html.twig @@ -0,0 +1,6 @@ +
    + {% block content %}{% endblock %} +
    diff --git a/src/lib/Component/Content/ContentEditMetaFieldsComponent.php b/src/lib/Component/Content/ContentEditMetaFieldsComponent.php new file mode 100644 index 0000000000..3ee9b01208 --- /dev/null +++ b/src/lib/Component/Content/ContentEditMetaFieldsComponent.php @@ -0,0 +1,68 @@ +twig = $twig; + $this->configResolver = $configResolver; + } + + /** + * @param array $parameters + * + * @return string + */ + public function render(array $parameters = []): string + { + /** @var \Ibexa\Contracts\Core\Repository\Values\ContentType\ContentType $contentType */ + $contentType = $parameters['content_type']; + + $metaFieldTypeIdentifiers = $this->getMetaFieldTypeIdentifiers(); + + if (empty($metaFieldTypeIdentifiers)) { + return self::NO_CONTENT; + } + + $parameters['meta_fields'] = []; + foreach ($metaFieldTypeIdentifiers as $identifier) { + $fields = $contentType->getFieldDefinitionsOfType($identifier); + $parameters['meta_fields'] = $parameters['meta_fields'] + array_column($fields->toArray(), 'identifier'); + } + + return $this->twig->render( + '@ibexadesign/content/components/meta_fields.html.twig', + $parameters + ); + } + + /** + * @return array + */ + private function getMetaFieldTypeIdentifiers(): array + { + $fieldTypeConfig = $this->configResolver->getParameter('admin_ui_forms.content_edit.fieldtypes'); + + return array_keys(array_filter($fieldTypeConfig, static fn (array $config) => true === $config['meta'])); + } +} From df7594bf452c0d1340e4eb9918ee90d0e32f1347 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 3 Aug 2022 13:59:37 +0200 Subject: [PATCH 04/18] IBX-3523: Refactored admin_ui_forms configuration --- .../Configuration/Parser/AdminUiForms.php | 64 ++++++++++++++--- .../Configuration/Parser/AdminUiFormsTest.php | 68 ++++++++++++++++--- 2 files changed, 114 insertions(+), 18 deletions(-) diff --git a/src/bundle/DependencyInjection/Configuration/Parser/AdminUiForms.php b/src/bundle/DependencyInjection/Configuration/Parser/AdminUiForms.php index cf40b164e7..8cad778d43 100644 --- a/src/bundle/DependencyInjection/Configuration/Parser/AdminUiForms.php +++ b/src/bundle/DependencyInjection/Configuration/Parser/AdminUiForms.php @@ -28,6 +28,7 @@ class AdminUiForms extends AbstractParser { public const FORM_TEMPLATES_PARAM = 'admin_ui_forms.content_edit_form_templates'; + public const FIELDTYPES_PARAM = 'admin_ui_forms.content_edit.fieldtypes'; /** * Adds semantic configuration definition. @@ -39,13 +40,47 @@ public function addSemanticConfig(NodeBuilder $nodeBuilder) $nodeBuilder ->arrayNode('admin_ui_forms') ->info('Admin UI forms configuration settings') + ->beforeNormalization() + ->always(static function (array $array): array { + // handle deprecated config + if (isset($array['content_edit_form_templates'])) { + $array['content_edit']['form_templates'] = $array['content_edit_form_templates']; + unset($array['content_edit_form_templates']); + } + + return $array; + }) + ->end() ->children() - ->arrayNode('content_edit_form_templates') - ->info('A list of Content Edit (and create) default Twig form templates') - ->arrayPrototype() - ->children() - ->scalarNode('template')->end() - ->integerNode('priority')->end() + ->arrayNode('content_edit') + ->info('Content Edit form configuration') + ->children() + ->arrayNode('form_templates') + ->info('A list of Content Edit (and create) default Twig form templates') + ->setDeprecated( + 'ibexa/admin-ui', + '4.2.0', + 'Setting "admin_ui.content_edit_form_templates" is deprecated. Use "admin_ui.content_edit.form_templates" instead.' + ) + ->arrayPrototype() + ->children() + ->scalarNode('template')->end() + ->integerNode('priority')->end() + ->end() + ->end() + ->end() + ->arrayNode('fieldtypes') + ->info('Configuration for specific FieldTypes') + ->useAttributeAsKey('identifier') + ->arrayPrototype() + ->children() + ->scalarNode('identifier')->end() + ->booleanNode('meta') + ->info('Make this fieldtype a part of Meta group') + ->defaultFalse() + ->end() + ->end() + ->end() ->end() ->end() ->end() @@ -61,11 +96,16 @@ public function mapConfig( $currentScope, ContextualizerInterface $contextualizer ): void { - if (!empty($scopeSettings['admin_ui_forms']['content_edit_form_templates'])) { + if (!empty($scopeSettings['admin_ui_forms']['content_edit']['form_templates'])) { $scopeSettings['admin_ui_forms.content_edit_form_templates'] = $this->processContentEditFormTemplates( - $scopeSettings['admin_ui_forms']['content_edit_form_templates'] + $scopeSettings['admin_ui_forms']['content_edit']['form_templates'] ); - unset($scopeSettings['admin_ui_forms']['content_edit_form_templates']); + unset($scopeSettings['admin_ui_forms']['content_edit']['form_templates']); + } + + if (!empty($scopeSettings['admin_ui_forms']['content_edit']['fieldtypes'])) { + $scopeSettings['admin_ui_forms.content_edit.fieldtypes'] = $scopeSettings['admin_ui_forms']['content_edit']['fieldtypes']; + unset($scopeSettings['admin_ui_forms']['content_edit']['fieldtypes']); } $contextualizer->setContextualParameter( @@ -73,6 +113,11 @@ public function mapConfig( $currentScope, $scopeSettings['admin_ui_forms.content_edit_form_templates'] ?? [] ); + $contextualizer->setContextualParameter( + static::FIELDTYPES_PARAM, + $currentScope, + $scopeSettings['admin_ui_forms.content_edit.fieldtypes'] ?? [] + ); } /** @@ -81,6 +126,7 @@ public function mapConfig( public function postMap(array $config, ContextualizerInterface $contextualizer) { $contextualizer->mapConfigArray('admin_ui_forms.content_edit_form_templates', $config); + $contextualizer->mapConfigArray('admin_ui_forms.content_edit.fieldtypes', $config); } /** diff --git a/tests/bundle/DependencyInjection/Configuration/Parser/AdminUiFormsTest.php b/tests/bundle/DependencyInjection/Configuration/Parser/AdminUiFormsTest.php index c701c19eea..0c0c389392 100644 --- a/tests/bundle/DependencyInjection/Configuration/Parser/AdminUiFormsTest.php +++ b/tests/bundle/DependencyInjection/Configuration/Parser/AdminUiFormsTest.php @@ -40,10 +40,12 @@ public function testContentEditFormTemplatesAreMapped() { $scopeSettings = [ 'admin_ui_forms' => [ - 'content_edit_form_templates' => [ - ['template' => 'my_template-01.html.twig', 'priority' => 1], - ['template' => 'my_template-02.html.twig', 'priority' => 0], - ['template' => 'my_template-03.html.twig', 'priority' => 2], + 'content_edit' => [ + 'form_templates' => [ + ['template' => 'my_template-01.html.twig', 'priority' => 1], + ['template' => 'my_template-02.html.twig', 'priority' => 0], + ['template' => 'my_template-03.html.twig', 'priority' => 2], + ], ], ], ]; @@ -56,12 +58,60 @@ public function testContentEditFormTemplatesAreMapped() ]; $this->contextualizer - ->expects($this->once()) + ->expects($this->atLeast(2)) ->method('setContextualParameter') - ->with( - AdminUiForms::FORM_TEMPLATES_PARAM, - $currentScope, - $expectedTemplatesList + ->withConsecutive( + [ + AdminUiForms::FORM_TEMPLATES_PARAM, + $currentScope, + $expectedTemplatesList, + ], + [ + AdminUiForms::FIELDTYPES_PARAM, + $currentScope, + [], + ], + ); + + $this->parser->mapConfig($scopeSettings, $currentScope, $this->contextualizer); + } + + /** + * Test given fieldtype settings are mapped. + */ + public function testContentEditFieldTypesAreMapped() + { + $scopeSettings = [ + 'admin_ui_forms' => [ + 'content_edit' => [ + 'fieldtypes' => [ + 'my_fieldtype' => ['meta' => true], + 'my_fieldtype_2' => ['meta' => false], + ], + ], + ], + ]; + $currentScope = 'admin_group'; + + $expectedFieldTypeSettings = [ + 'my_fieldtype' => ['meta' => true], + 'my_fieldtype_2' => ['meta' => false], + ]; + + $this->contextualizer + ->expects($this->atLeast(2)) + ->method('setContextualParameter') + ->withConsecutive( + [ + AdminUiForms::FORM_TEMPLATES_PARAM, + $currentScope, + [], + ], + [ + AdminUiForms::FIELDTYPES_PARAM, + $currentScope, + $expectedFieldTypeSettings, + ], ); $this->parser->mapConfig($scopeSettings, $currentScope, $this->contextualizer); From 8b0fd9f609879f403aad91e18a665e3c5b6143ce Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 3 Aug 2022 14:45:47 +0200 Subject: [PATCH 05/18] IBX-3523: Added GroupedNonMetaFormFieldsProvider to avoid displaying Meta fields in Content category --- .../Resources/config/services/events.yaml | 12 +++- .../Resources/config/services/forms.yaml | 4 ++ .../SetViewParametersListener.php | 38 +++++++++---- .../GroupedNonMetaFormFieldsProvider.php | 57 +++++++++++++++++++ 4 files changed, 96 insertions(+), 15 deletions(-) create mode 100644 src/lib/Form/Provider/GroupedNonMetaFormFieldsProvider.php diff --git a/src/bundle/Resources/config/services/events.yaml b/src/bundle/Resources/config/services/events.yaml index 01264b8d25..fbbdc8e25c 100644 --- a/src/bundle/Resources/config/services/events.yaml +++ b/src/bundle/Resources/config/services/events.yaml @@ -27,7 +27,7 @@ services: arguments: - '%ibexa.site_access.groups%' tags: - - {name: kernel.event_subscriber} + - { name: kernel.event_subscriber } Ibexa\AdminUi\EventListener\AdminExceptionListener: arguments: @@ -41,7 +41,7 @@ services: Ibexa\AdminUi\EventListener\MenuPermissionsListener: tags: - - {name: kernel.event_subscriber, priority: -250} + - { name: kernel.event_subscriber, priority: -250 } Ibexa\AdminUi\EventListener\ViewTemplatesListener: tags: @@ -51,4 +51,10 @@ services: arguments: $siteAccessGroups: '%ibexa.site_access.groups%' tags: - - {name: kernel.event_subscriber} + - { name: kernel.event_subscriber } + + Ibexa\AdminUi\EventListener\SetViewParametersListener: + arguments: + $groupedContentFormFieldsProvider: '@Ibexa\AdminUi\Form\Provider\GroupedNonMetaFormFieldsProvider' + tags: + - { name: kernel.event_subscriber } diff --git a/src/bundle/Resources/config/services/forms.yaml b/src/bundle/Resources/config/services/forms.yaml index ea9087cc3d..05c0e9a52f 100644 --- a/src/bundle/Resources/config/services/forms.yaml +++ b/src/bundle/Resources/config/services/forms.yaml @@ -401,3 +401,7 @@ services: Ibexa\AdminUi\Form\Type\ContentType\FieldDefinitionsCollectionType: tags: - { name: form.type } + + Ibexa\AdminUi\Form\Provider\GroupedNonMetaFormFieldsProvider: + arguments: + $innerGroupedContentFormFieldsProvider: '@Ibexa\Contracts\ContentForms\Content\Form\Provider\GroupedContentFormFieldsProviderInterface' diff --git a/src/lib/EventListener/SetViewParametersListener.php b/src/lib/EventListener/SetViewParametersListener.php index 68ee409f57..869996ef39 100644 --- a/src/lib/EventListener/SetViewParametersListener.php +++ b/src/lib/EventListener/SetViewParametersListener.php @@ -12,6 +12,7 @@ use Ibexa\ContentForms\Content\View\ContentCreateView; use Ibexa\ContentForms\Content\View\ContentEditView; use Ibexa\ContentForms\User\View\UserUpdateView; +use Ibexa\Contracts\ContentForms\Content\Form\Provider\GroupedContentFormFieldsProviderInterface; use Ibexa\Contracts\Core\Repository\Exceptions\NotFoundException; use Ibexa\Contracts\Core\Repository\LocationService; use Ibexa\Contracts\Core\Repository\Repository; @@ -23,6 +24,7 @@ use Ibexa\Core\MVC\Symfony\Event\PreContentViewEvent; use Ibexa\Core\MVC\Symfony\MVCEvents; use Ibexa\Core\MVC\Symfony\View\View; +use Ibexa\Core\MVC\Symfony\View\ViewEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** @@ -30,28 +32,24 @@ */ class SetViewParametersListener implements EventSubscriberInterface { - /** @var \Ibexa\Contracts\Core\Repository\LocationService */ - protected $locationService; + protected LocationService $locationService; - /** @var \Ibexa\Contracts\Core\Repository\UserService */ - protected $userService; + protected UserService $userService; - /** @var \Ibexa\Contracts\Core\Repository\Repository */ - private $repository; + private Repository $repository; + + private GroupedContentFormFieldsProviderInterface $groupedContentFormFieldsProvider; - /** - * @param \Ibexa\Contracts\Core\Repository\LocationService $locationService - * @param \Ibexa\Contracts\Core\Repository\UserService $userService - * @param \Ibexa\Contracts\Core\Repository\Repository $repository - */ public function __construct( LocationService $locationService, UserService $userService, - Repository $repository + Repository $repository, + GroupedContentFormFieldsProviderInterface $groupedContentFormFieldsProvider ) { $this->locationService = $locationService; $this->userService = $userService; $this->repository = $repository; + $this->groupedContentFormFieldsProvider = $groupedContentFormFieldsProvider; } /** @@ -67,6 +65,7 @@ public static function getSubscribedEvents(): array ['setUserUpdateViewTemplateParameters', 5], ['setContentTranslateViewTemplateParameters', 10], ['setContentCreateViewTemplateParameters', 10], + ['setGroupedFieldsParameter', 20], ], ]; } @@ -179,6 +178,21 @@ public function setContentCreateViewTemplateParameters(PreContentViewEvent $even ]); } + public function setGroupedFieldsParameter(PreContentViewEvent $event): void + { + $view = $event->getContentView(); + if (!$view instanceof ContentEditView) { + return; + } + + $parameters = $view->getParameters(); + $parameters['grouped_fields'] = $this->groupedContentFormFieldsProvider->getGroupedFields( + $view->getForm()->get('fieldsData')->all() + ); + + $view->setParameters($parameters); + } + /** * @param \Ibexa\Contracts\Core\Repository\Values\Content\ContentInfo $contentInfo * @param \Ibexa\Core\MVC\Symfony\View\View $contentView diff --git a/src/lib/Form/Provider/GroupedNonMetaFormFieldsProvider.php b/src/lib/Form/Provider/GroupedNonMetaFormFieldsProvider.php new file mode 100644 index 0000000000..41c8ada9bf --- /dev/null +++ b/src/lib/Form/Provider/GroupedNonMetaFormFieldsProvider.php @@ -0,0 +1,57 @@ +innerGroupedContentFormFieldsProvider = $innerGroupedContentFormFieldsProvider; + $this->configResolver = $configResolver; + } + + public function getGroupedFields(array $fieldsDataForm): array + { + $identifiers = $this->getMetaFields(); + + $groupedFields = $this->innerGroupedContentFormFieldsProvider->getGroupedFields($fieldsDataForm); + foreach ($groupedFields as $group => $fields) { + $groupedFields[$group] = array_filter( + $fields, + static function (string $fieldIdentifier) use ($fieldsDataForm, $identifiers): bool { + $fieldData = $fieldsDataForm[$fieldIdentifier]->getNormData(); + $fieldTypeIdentifier = $fieldData->fieldDefinition->fieldTypeIdentifier; + + return !in_array($fieldTypeIdentifier, $identifiers, true); + } + ); + } + + return array_filter($groupedFields); + } + + /** + * @return array + */ + private function getMetaFields(): array + { + $fieldTypesConfig = $this->configResolver->getParameter('admin_ui_forms.content_edit.fieldtypes'); + + return array_keys(array_filter($fieldTypesConfig, static fn (array $config) => true === $config['meta'])); + } +} From 603b4c2460173424223d21df0c9c648a5144735b Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 3 Aug 2022 15:21:48 +0200 Subject: [PATCH 06/18] IBX-3523: Fixed uninitialized $items variable --- src/lib/Menu/ContentEditAnchorMenuBuilder.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/Menu/ContentEditAnchorMenuBuilder.php b/src/lib/Menu/ContentEditAnchorMenuBuilder.php index b6b82a84a3..a9ba802285 100644 --- a/src/lib/Menu/ContentEditAnchorMenuBuilder.php +++ b/src/lib/Menu/ContentEditAnchorMenuBuilder.php @@ -128,6 +128,7 @@ private function getMetaFieldItems(ContentType $contentType): array static fn (array $config) => true === $config['meta'] )); + $items = []; $order = 0; foreach ($metaFieldTypeIdentifiers as $metaFieldTypeIdentifier) { if (false === $contentType->hasFieldDefinitionOfType($metaFieldTypeIdentifier)) { From bb364f60ec7d9cf3166554ac5ab08458e32ac99a Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 3 Aug 2022 15:33:16 +0200 Subject: [PATCH 07/18] IBX-3523: Refactored default config to use new admin_ui_forms.content_edit.form_templates notation --- src/bundle/Resources/config/admin_ui_forms.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/bundle/Resources/config/admin_ui_forms.yaml b/src/bundle/Resources/config/admin_ui_forms.yaml index ac2200c091..83e09af8c5 100644 --- a/src/bundle/Resources/config/admin_ui_forms.yaml +++ b/src/bundle/Resources/config/admin_ui_forms.yaml @@ -1,8 +1,9 @@ system: admin_group: admin_ui_forms: - content_edit_form_templates: - - { template: '@ibexadesign/content/form_fields.html.twig', priority: 0 } + content_edit: + form_templates: + - { template: '@ibexadesign/content/form_fields.html.twig', priority: 0 } field_templates: - { template: '@ibexadesign/ui/field_type/preview/content_fields.html.twig', priority: 20 } From 6f9fe196d55fcc0429a699633356573e1e470e8d Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Wed, 3 Aug 2022 15:41:10 +0200 Subject: [PATCH 08/18] IBX-3523: Removed unnecessary doc blocks --- src/lib/Menu/ContentEditAnchorMenuBuilder.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/lib/Menu/ContentEditAnchorMenuBuilder.php b/src/lib/Menu/ContentEditAnchorMenuBuilder.php index a9ba802285..78092aab0c 100644 --- a/src/lib/Menu/ContentEditAnchorMenuBuilder.php +++ b/src/lib/Menu/ContentEditAnchorMenuBuilder.php @@ -32,9 +32,6 @@ public function __construct( $this->configResolver = $configResolver; } - /** - * @return string - */ protected function getConfigureEventName(): string { return ConfigureMenuEvent::CONTENT_EDIT_ANCHOR_MENU; @@ -116,8 +113,6 @@ private function getContentFieldGroupItems(array $groupedFields): array } /** - * @param array> $groupedFields - * * @return array<\Knp\Menu\ItemInterface> */ private function getMetaFieldItems(ContentType $contentType): array From 65eb399eb157042bdc057759553aa807674f4ffc Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 4 Aug 2022 09:54:27 +0200 Subject: [PATCH 09/18] IBX-3523: Fixed SetViewParametersListenerTest --- .../SetViewParametersListenerTest.php | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/tests/lib/EventListener/SetViewParametersListenerTest.php b/tests/lib/EventListener/SetViewParametersListenerTest.php index 6197d715d7..fc07e32983 100644 --- a/tests/lib/EventListener/SetViewParametersListenerTest.php +++ b/tests/lib/EventListener/SetViewParametersListenerTest.php @@ -11,6 +11,7 @@ use Ibexa\AdminUi\EventListener\SetViewParametersListener; use Ibexa\ContentForms\Content\View\ContentEditView; use Ibexa\ContentForms\User\View\UserUpdateView; +use Ibexa\Contracts\ContentForms\Content\Form\Provider\GroupedContentFormFieldsProviderInterface; use Ibexa\Contracts\Core\Repository\LocationService; use Ibexa\Contracts\Core\Repository\Repository; use Ibexa\Contracts\Core\Repository\UserService; @@ -22,6 +23,7 @@ use Ibexa\Core\Repository\Values\Content as Core; use Ibexa\Core\Repository\Values\User\User as CoreUser; use PHPUnit\Framework\TestCase; +use Symfony\Component\Form\FormInterface; final class SetViewParametersListenerTest extends TestCase { @@ -44,6 +46,9 @@ final class SetViewParametersListenerTest extends TestCase /** @var \Ibexa\Contracts\Core\Repository\Repository|\PHPUnit\Framework\MockObject\MockObject */ private $repository; + /** @var \Ibexa\Contracts\ContentForms\Content\Form\Provider\GroupedContentFormFieldsProviderInterface|\PHPUnit\Framework\MockObject\MockObject */ + private $groupedContentFormFieldsProvider; + public function setUp(): void { $contentInfo = $this->generateContentInfo(); @@ -58,11 +63,13 @@ public function setUp(): void $this->locationService = $this->createMock(LocationService::class); $this->userService = $this->createMock(UserService::class); $this->repository = $this->createMock(Repository::class); + $this->groupedContentFormFieldsProvider = $this->createMock(GroupedContentFormFieldsProviderInterface::class); $this->viewParametersListener = new SetViewParametersListener( $this->locationService, $this->userService, - $this->repository + $this->repository, + $this->groupedContentFormFieldsProvider ); } @@ -195,6 +202,41 @@ public function testSetUserUpdateViewTemplateParameters() $this->assertSame($user, $userUpdateView->getParameter('creator')); } + public function testSetGroupedFieldsParameter() + { + $fieldsDataChildren = [ + 'name' => $this->createMock(FormInterface::class), + 'short_name' => $this->createMock(FormInterface::class), + 'description' => $this->createMock(FormInterface::class), + ]; + $fieldsDataForm = $this->createMock(FormInterface::class); + $fieldsDataForm + ->method('all') + ->willReturn($fieldsDataChildren); + + $form = $this->createMock(FormInterface::class); + $form + ->method('get') + ->with('fieldsData') + ->willReturn($fieldsDataForm); + + $contentEditView = new ContentEditView(); + $contentEditView->setForm($form); + + $groupedFields = [ + 'Content' => ['name', 'short_name', 'description'], + ]; + + $this->groupedContentFormFieldsProvider + ->method('getGroupedFields') + ->with($fieldsDataChildren) + ->willReturn($groupedFields); + + $this->viewParametersListener->setGroupedFieldsParameter(new PreContentViewEvent($contentEditView)); + + $this->assertSame($groupedFields, $contentEditView->getParameter('grouped_fields')); + } + public function testSubscribedEvents() { $this->locationService @@ -207,6 +249,7 @@ public function testSubscribedEvents() ['setUserUpdateViewTemplateParameters', 5], ['setContentTranslateViewTemplateParameters', 10], ['setContentCreateViewTemplateParameters', 10], + ['setGroupedFieldsParameter', 20], ], ]; From d80ea289ddc08766b9de5d962b49108b9dbc83df Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 4 Aug 2022 10:26:31 +0200 Subject: [PATCH 10/18] Addressed review comments --- .../DependencyInjection/Configuration/Parser/AdminUiForms.php | 4 ++-- src/lib/Component/Content/ContentEditMetaFieldsComponent.php | 2 +- .../Configuration/Parser/AdminUiFormsTest.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bundle/DependencyInjection/Configuration/Parser/AdminUiForms.php b/src/bundle/DependencyInjection/Configuration/Parser/AdminUiForms.php index 8cad778d43..bc390aefa2 100644 --- a/src/bundle/DependencyInjection/Configuration/Parser/AdminUiForms.php +++ b/src/bundle/DependencyInjection/Configuration/Parser/AdminUiForms.php @@ -28,7 +28,7 @@ class AdminUiForms extends AbstractParser { public const FORM_TEMPLATES_PARAM = 'admin_ui_forms.content_edit_form_templates'; - public const FIELDTYPES_PARAM = 'admin_ui_forms.content_edit.fieldtypes'; + public const FIELD_TYPES_PARAM = 'admin_ui_forms.content_edit.fieldtypes'; /** * Adds semantic configuration definition. @@ -114,7 +114,7 @@ public function mapConfig( $scopeSettings['admin_ui_forms.content_edit_form_templates'] ?? [] ); $contextualizer->setContextualParameter( - static::FIELDTYPES_PARAM, + static::FIELD_TYPES_PARAM, $currentScope, $scopeSettings['admin_ui_forms.content_edit.fieldtypes'] ?? [] ); diff --git a/src/lib/Component/Content/ContentEditMetaFieldsComponent.php b/src/lib/Component/Content/ContentEditMetaFieldsComponent.php index 3ee9b01208..17528e6a9c 100644 --- a/src/lib/Component/Content/ContentEditMetaFieldsComponent.php +++ b/src/lib/Component/Content/ContentEditMetaFieldsComponent.php @@ -47,7 +47,7 @@ public function render(array $parameters = []): string $parameters['meta_fields'] = []; foreach ($metaFieldTypeIdentifiers as $identifier) { $fields = $contentType->getFieldDefinitionsOfType($identifier); - $parameters['meta_fields'] = $parameters['meta_fields'] + array_column($fields->toArray(), 'identifier'); + $parameters['meta_fields'] += array_column($fields->toArray(), 'identifier'); } return $this->twig->render( diff --git a/tests/bundle/DependencyInjection/Configuration/Parser/AdminUiFormsTest.php b/tests/bundle/DependencyInjection/Configuration/Parser/AdminUiFormsTest.php index 0c0c389392..036c0cff34 100644 --- a/tests/bundle/DependencyInjection/Configuration/Parser/AdminUiFormsTest.php +++ b/tests/bundle/DependencyInjection/Configuration/Parser/AdminUiFormsTest.php @@ -67,7 +67,7 @@ public function testContentEditFormTemplatesAreMapped() $expectedTemplatesList, ], [ - AdminUiForms::FIELDTYPES_PARAM, + AdminUiForms::FIELD_TYPES_PARAM, $currentScope, [], ], @@ -108,7 +108,7 @@ public function testContentEditFieldTypesAreMapped() [], ], [ - AdminUiForms::FIELDTYPES_PARAM, + AdminUiForms::FIELD_TYPES_PARAM, $currentScope, $expectedFieldTypeSettings, ], From b5370b468376900b2f24a4dbc9fea75dd35b402f Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 4 Aug 2022 10:32:56 +0200 Subject: [PATCH 11/18] IBX-3523: Moved anchor menu rendering to edit.html.twig template --- .../themes/admin/content/edit/edit.html.twig | 17 +++++++++++++++++ .../themes/admin/content/edit_base.html.twig | 17 +++-------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/bundle/Resources/views/themes/admin/content/edit/edit.html.twig b/src/bundle/Resources/views/themes/admin/content/edit/edit.html.twig index ea966cc7a5..f50b41a028 100644 --- a/src/bundle/Resources/views/themes/admin/content/edit/edit.html.twig +++ b/src/bundle/Resources/views/themes/admin/content/edit/edit.html.twig @@ -51,6 +51,23 @@ {% endblock %} +{% block anchor_menu %} + {% set content_edit_anchor_menu = knp_menu_get('ibexa.admin_ui.menu.content_edit.anchor_menu', [], { + 'content': content, + 'content_type': content_type, + 'location': location, + 'parent_location': parent_location, + 'language': language, + 'grouped_fields': grouped_fields, + }) %} + + {% embed '@ibexadesign/ui/anchor_navigation_menu.html.twig' with anchor_params %} + {% block navigation_menu_body %} + {{ knp_menu_render(content_edit_anchor_menu, { 'template': '@ibexadesign/ui/menu/anchor_menu.html.twig' }) }} + {% endblock %} + {% endembed %} +{% endblock %} + {% block content_sections %} {{ ibexa_render_component_group('content-edit-sections', { 'form': form, diff --git a/src/bundle/Resources/views/themes/admin/content/edit_base.html.twig b/src/bundle/Resources/views/themes/admin/content/edit_base.html.twig index 6b6c070e20..c8175a86e6 100644 --- a/src/bundle/Resources/views/themes/admin/content/edit_base.html.twig +++ b/src/bundle/Resources/views/themes/admin/content/edit_base.html.twig @@ -20,20 +20,9 @@ }) %} {% endif %} - {% set content_edit_anchor_menu = knp_menu_get('ibexa.admin_ui.menu.content_edit.anchor_menu', [], { - 'content': content, - 'content_type': content_type, - 'location': location, - 'parent_location': parent_location, - 'language': language, - 'grouped_fields': grouped_fields, - }) %} - - {% embed '@ibexadesign/ui/anchor_navigation_menu.html.twig' with anchor_params %} - {% block navigation_menu_body %} - {{ knp_menu_render(content_edit_anchor_menu, { 'template': '@ibexadesign/ui/menu/anchor_menu.html.twig' }) }} - {% endblock %} - {% endembed %} + {% block anchor_menu %} + {% include '@ibexadesign/ui/anchor_navigation_menu.html.twig' with anchor_params %} + {% endblock %} {% endblock %} {% macro renderFormField(formField) -%} From 9f6499bfc83e546d221579c67a43907bd1c91c4d Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 4 Aug 2022 13:21:54 +0200 Subject: [PATCH 12/18] Addresses review comments --- .../ContentEditMetaFieldsComponent.php | 7 ++- .../GroupedNonMetaFormFieldsProvider.php | 7 ++- src/lib/Menu/ContentEditAnchorMenuBuilder.php | 43 ++++++++++++------- .../Configuration/Parser/AdminUiFormsTest.php | 2 +- 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/lib/Component/Content/ContentEditMetaFieldsComponent.php b/src/lib/Component/Content/ContentEditMetaFieldsComponent.php index 17528e6a9c..b872a78d30 100644 --- a/src/lib/Component/Content/ContentEditMetaFieldsComponent.php +++ b/src/lib/Component/Content/ContentEditMetaFieldsComponent.php @@ -63,6 +63,11 @@ private function getMetaFieldTypeIdentifiers(): array { $fieldTypeConfig = $this->configResolver->getParameter('admin_ui_forms.content_edit.fieldtypes'); - return array_keys(array_filter($fieldTypeConfig, static fn (array $config) => true === $config['meta'])); + return array_keys( + array_filter( + $fieldTypeConfig, + static fn (array $config): bool => true === $config['meta'] + ) + ); } } diff --git a/src/lib/Form/Provider/GroupedNonMetaFormFieldsProvider.php b/src/lib/Form/Provider/GroupedNonMetaFormFieldsProvider.php index 41c8ada9bf..90f90b73df 100644 --- a/src/lib/Form/Provider/GroupedNonMetaFormFieldsProvider.php +++ b/src/lib/Form/Provider/GroupedNonMetaFormFieldsProvider.php @@ -52,6 +52,11 @@ private function getMetaFields(): array { $fieldTypesConfig = $this->configResolver->getParameter('admin_ui_forms.content_edit.fieldtypes'); - return array_keys(array_filter($fieldTypesConfig, static fn (array $config) => true === $config['meta'])); + return array_keys( + array_filter( + $fieldTypesConfig, + static fn (array $config): bool => true === $config['meta'] + ) + ); } } diff --git a/src/lib/Menu/ContentEditAnchorMenuBuilder.php b/src/lib/Menu/ContentEditAnchorMenuBuilder.php index 78092aab0c..12e08082da 100644 --- a/src/lib/Menu/ContentEditAnchorMenuBuilder.php +++ b/src/lib/Menu/ContentEditAnchorMenuBuilder.php @@ -10,6 +10,7 @@ use Ibexa\Contracts\AdminUi\Menu\AbstractBuilder; use Ibexa\Contracts\Core\SiteAccess\ConfigResolverInterface; use Ibexa\Core\Repository\Values\ContentType\ContentType; +use Ibexa\Core\Repository\Values\ContentType\FieldDefinition; use JMS\TranslationBundle\Model\Message; use JMS\TranslationBundle\Translation\TranslationContainerInterface; use Knp\Menu\ItemInterface; @@ -20,6 +21,8 @@ class ContentEditAnchorMenuBuilder extends AbstractBuilder implements Translatio public const ITEM__CONTENT = 'content_edit__anchor_menu__content'; public const ITEM__META = 'content_edit__anchor_menu__meta'; + private const ITEM_ORDER_SPAN = 10; + private ConfigResolverInterface $configResolver; public function __construct( @@ -75,7 +78,7 @@ public function createStructure(array $options): ItemInterface [ 'attributes' => ['data-target-id' => 'ibexa-edit-content-sections-meta'], 'extras' => [ - 'orderNumber' => 50, + 'orderNumber' => 20, ], ] ); @@ -98,7 +101,7 @@ private function getContentFieldGroupItems(array $groupedFields): array $items = []; $order = 0; foreach ($groupedFields as $group => $fields) { - $order = $order + 10; + $order += self::ITEM_ORDER_SPAN; $items[$group] = $this->createMenuItem($group, [ 'attributes' => [ 'data-target-id' => sprintf('ibexa-edit-content-sections-content-fields-%s', mb_strtolower($group)), @@ -120,7 +123,7 @@ private function getMetaFieldItems(ContentType $contentType): array $fieldTypeSettings = $this->configResolver->getParameter('admin_ui_forms.content_edit.fieldtypes'); $metaFieldTypeIdentifiers = array_keys(array_filter( $fieldTypeSettings, - static fn (array $config) => true === $config['meta'] + static fn (array $config): bool => true === $config['meta'] )); $items = []; @@ -133,25 +136,33 @@ private function getMetaFieldItems(ContentType $contentType): array $fieldDefinitions = $contentType->getFieldDefinitionsOfType($metaFieldTypeIdentifier); foreach ($fieldDefinitions as $fieldDefinition) { $fieldDefIdentifier = $fieldDefinition->identifier; - $order = $order + 10; - $items[$fieldDefIdentifier] = $this->createMenuItem( - $fieldDefIdentifier, - [ - 'label' => $fieldDefinition->getName(), - 'attributes' => [ - 'data-target-id' => sprintf('ibexa-edit-content-sections-meta-%s', $fieldDefIdentifier), - ], - 'extras' => [ - 'orderNumber' => $order, - ], - ] - ); + $order += self::ITEM_ORDER_SPAN; + $items[$fieldDefIdentifier] = $this->createSecondLevelItem($fieldDefIdentifier, $fieldDefinition, $order); } } return $items; } + private function createSecondLevelItem( + string $fieldDefIdentifier, + FieldDefinition $fieldDefinition, + int $order + ): ItemInterface { + return $this->createMenuItem( + $fieldDefIdentifier, + [ + 'label' => $fieldDefinition->getName(), + 'attributes' => [ + 'data-target-id' => sprintf('ibexa-edit-content-sections-meta-%s', $fieldDefIdentifier), + ], + 'extras' => [ + 'orderNumber' => $order, + ], + ] + ); + } + /** * @return array<\JMS\TranslationBundle\Model\Message> */ diff --git a/tests/bundle/DependencyInjection/Configuration/Parser/AdminUiFormsTest.php b/tests/bundle/DependencyInjection/Configuration/Parser/AdminUiFormsTest.php index 036c0cff34..0aa1755b1f 100644 --- a/tests/bundle/DependencyInjection/Configuration/Parser/AdminUiFormsTest.php +++ b/tests/bundle/DependencyInjection/Configuration/Parser/AdminUiFormsTest.php @@ -79,7 +79,7 @@ public function testContentEditFormTemplatesAreMapped() /** * Test given fieldtype settings are mapped. */ - public function testContentEditFieldTypesAreMapped() + public function testContentEditFieldTypesAreMapped(): void { $scopeSettings = [ 'admin_ui_forms' => [ From 0f38e93693d100059970ee436e4b73e52c4aaa79 Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Thu, 4 Aug 2022 13:39:03 +0200 Subject: [PATCH 13/18] Added missing return types in SetViewParametersListenerTest --- .../SetViewParametersListenerTest.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/lib/EventListener/SetViewParametersListenerTest.php b/tests/lib/EventListener/SetViewParametersListenerTest.php index fc07e32983..c2c6418ea2 100644 --- a/tests/lib/EventListener/SetViewParametersListenerTest.php +++ b/tests/lib/EventListener/SetViewParametersListenerTest.php @@ -73,7 +73,7 @@ public function setUp(): void ); } - public function testSetViewTemplateParameters() + public function testSetViewTemplateParameters(): void { $locationA = new Core\Location(['id' => self::EXAMPLE_LOCATION_A_ID]); $locationB = new Core\Location(['id' => self::EXAMPLE_LOCATION_B_ID]); @@ -115,7 +115,7 @@ private function generateLocation(int $parentLocationId = null): API\Location return new Core\Location(['id' => 3, 'parentLocationId' => $parentLocationId]); } - public function testSetViewTemplateParametersWithMainLocationId() + public function testSetViewTemplateParametersWithMainLocationId(): void { $mainLocationId = 123; $parentLocationId = 456; @@ -153,7 +153,7 @@ public function testSetViewTemplateParametersWithMainLocationId() $this->assertSame(reset($parentLocations), $contentView->getParameter('parent_location')); } - public function testSetViewTemplateParametersWithoutContentEditViewInstance() + public function testSetViewTemplateParametersWithoutContentEditViewInstance(): void { $contentView = $this->createMock(View::class); @@ -167,7 +167,7 @@ public function testSetViewTemplateParametersWithoutContentEditViewInstance() ); } - public function testSetUserUpdateViewTemplateParametersWithoutUserUpdateViewInstance() + public function testSetUserUpdateViewTemplateParametersWithoutUserUpdateViewInstance(): void { $view = $this->createMock(View::class); @@ -181,7 +181,7 @@ public function testSetUserUpdateViewTemplateParametersWithoutUserUpdateViewInst ); } - public function testSetUserUpdateViewTemplateParameters() + public function testSetUserUpdateViewTemplateParameters(): void { $ownerId = 42; @@ -202,7 +202,7 @@ public function testSetUserUpdateViewTemplateParameters() $this->assertSame($user, $userUpdateView->getParameter('creator')); } - public function testSetGroupedFieldsParameter() + public function testSetGroupedFieldsParameter(): void { $fieldsDataChildren = [ 'name' => $this->createMock(FormInterface::class), @@ -237,7 +237,7 @@ public function testSetGroupedFieldsParameter() $this->assertSame($groupedFields, $contentEditView->getParameter('grouped_fields')); } - public function testSubscribedEvents() + public function testSubscribedEvents(): void { $this->locationService ->expects(self::never()) From f08c3d43cecb9d7049b775d5f0723bd972597369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grabowski?= Date: Fri, 5 Aug 2022 10:40:43 +0200 Subject: [PATCH 14/18] fixes after cr --- .../admin.anchor.sections.navigation.js | 8 ++--- .../themes/admin/content/edit_base.html.twig | 30 +++++++++---------- .../admin/ui/anchor_navigation_menu.html.twig | 6 ++-- .../primary_section.html.twig | 4 +-- .../secondary_section.html.twig | 4 +-- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js b/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js index fe6e3b499e..605b61d787 100644 --- a/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js +++ b/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js @@ -23,7 +23,7 @@ contentContainer.style.paddingBottom = '0px'; if (!firstSection.isSameNode(lastSection) && lastSection && lastSection.offsetHeight) { - const headerContainer = doc.querySelector('.ibexa-edit-header .ibexa-edit-header__container'); + const headerContainer = doc.querySelector('.ibexa-edit-header__container'); const heightFromLastSection = contentContainer.offsetHeight - lastSection.offsetTop; const contentColumnBodyHeight = contentColumn.offsetHeight - headerContainer.offsetHeight; const heightDiff = contentColumnBodyHeight - heightFromLastSection; @@ -67,7 +67,7 @@ items.forEach((item) => item.classList.toggle('ibexa-navigation-menu__secondary--active', item.isSameNode(node))); }; const onSelectPrimaryMenuList = (event) => { - const { targetId } = event.target.dataset; + const { targetId } = event.currentTarget.dataset; const secondaryMenuNode = doc.querySelector(`.ibexa-navigation-menu__secondary[data-id="${targetId}"]`); const primaryMenuItems = doc.querySelectorAll('.ibexa-navigation-menu__primary--list .ibexa-navigation-menu__primary-item'); @@ -81,7 +81,7 @@ } }; const onSelectPrimaryMenuDropdown = (event) => { - const targetId = event.target.value; + const targetId = event.currentTarget.value; const secondaryMenuNode = doc.querySelector(`.ibexa-navigation-menu__secondary[data-id="${targetId}"]`); showPrimarySection(targetId); @@ -116,7 +116,7 @@ }; const bindScrollContainerEvents = () => { const allSections = [...doc.querySelectorAll('.ibexa-edit-content__secondary-section')]; - const headerContainer = doc.querySelector('.ibexa-edit-header .ibexa-edit-header__container'); + const headerContainer = doc.querySelector('.ibexa-edit-header__container'); let previousFirstVisibleSection = null; if (formContainerNode && allSections.length) { diff --git a/src/bundle/Resources/views/themes/admin/content/edit_base.html.twig b/src/bundle/Resources/views/themes/admin/content/edit_base.html.twig index c8175a86e6..aeb513b2fe 100644 --- a/src/bundle/Resources/views/themes/admin/content/edit_base.html.twig +++ b/src/bundle/Resources/views/themes/admin/content/edit_base.html.twig @@ -61,21 +61,21 @@ data-id="ibexa-edit-content-sections-content-fields" > {% block form_fields %} -
    - {% for key, group in grouped_fields %} - {% embed '@ibexadesign/ui/anchor_navigation_section.html.twig' with { - anchor_section_key: 'ibexa-edit-content-sections-content-fields-' ~ key|lower, - parent_self: _self, - } %} - {% trans_default_domain 'content_edit' %} - {% import parent_self as parent_self %} - - {% block anchor_section_body %} - {{ parent_self.renderFieldGroup(group, form) }} - {% endblock %} - {% endembed %} - {% endfor %} -
    +
    + {% for key, group in grouped_fields %} + {% embed '@ibexadesign/ui/anchor_navigation_section.html.twig' with { + anchor_section_key: 'ibexa-edit-content-sections-content-fields-' ~ key|lower, + parent_self: _self, + } %} + {% trans_default_domain 'content_edit' %} + {% import parent_self as parent_self %} + + {% block anchor_section_body %} + {{ parent_self.renderFieldGroup(group, form) }} + {% endblock %} + {% endembed %} + {% endfor %} +
    {% endblock %} {% block content_sections %}{% endblock %} diff --git a/src/bundle/Resources/views/themes/admin/ui/anchor_navigation_menu.html.twig b/src/bundle/Resources/views/themes/admin/ui/anchor_navigation_menu.html.twig index a220a8a39a..4533a18b5b 100644 --- a/src/bundle/Resources/views/themes/admin/ui/anchor_navigation_menu.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/anchor_navigation_menu.html.twig @@ -23,9 +23,9 @@ {% set sanitized_item = item|slug %}
  • diff --git a/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/primary_section.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/primary_section.html.twig index d1ce150bea..019eba797e 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/primary_section.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/primary_section.html.twig @@ -1,6 +1,6 @@
    {% block sections %}{% endblock %} diff --git a/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/secondary_section.html.twig b/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/secondary_section.html.twig index 335765ef51..51b867d564 100644 --- a/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/secondary_section.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/component/anchor_navigation/secondary_section.html.twig @@ -1,6 +1,6 @@
    {% block content %}{% endblock %}
    From 7e3e188c5c80ce7c674f6ff2b47a4929d789859e Mon Sep 17 00:00:00 2001 From: Maciej Kobus Date: Fri, 5 Aug 2022 14:59:35 +0200 Subject: [PATCH 15/18] IBX-3523: Fixed issue where fields overwrote previous elements in the array --- src/lib/Component/Content/ContentEditMetaFieldsComponent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/Component/Content/ContentEditMetaFieldsComponent.php b/src/lib/Component/Content/ContentEditMetaFieldsComponent.php index b872a78d30..b72a34ddb0 100644 --- a/src/lib/Component/Content/ContentEditMetaFieldsComponent.php +++ b/src/lib/Component/Content/ContentEditMetaFieldsComponent.php @@ -47,7 +47,7 @@ public function render(array $parameters = []): string $parameters['meta_fields'] = []; foreach ($metaFieldTypeIdentifiers as $identifier) { $fields = $contentType->getFieldDefinitionsOfType($identifier); - $parameters['meta_fields'] += array_column($fields->toArray(), 'identifier'); + $parameters['meta_fields'] = array_merge($parameters['meta_fields'], array_column($fields->toArray(), 'identifier')); } return $this->twig->render( From a0d2bda19c10151cddba74698c62c2653d992697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grabowski?= Date: Fri, 5 Aug 2022 15:47:54 +0200 Subject: [PATCH 16/18] fix menu elements width --- .../js/scripts/admin.anchor.sections.navigation.js | 9 ++++++--- src/bundle/Resources/public/scss/_main-container.scss | 3 ++- src/bundle/Resources/public/scss/_navigation-menu.scss | 6 ++++++ .../views/themes/admin/ui/menu/anchor_menu.html.twig | 4 +++- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js b/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js index 605b61d787..ccf0afe9a7 100644 --- a/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js +++ b/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js @@ -1,5 +1,7 @@ -(function (global, doc) { - if (!doc.querySelector('.ibexa-navigation-menu')) { +(function (global, doc, ibexa) { + const navigationMenu = doc.querySelector('.ibexa-navigation-menu'); + + if (!navigationMenu) { return; } @@ -153,4 +155,5 @@ bindSecondaryMenuEvents(); bindScrollContainerEvents(); fitSecondarySections(); -})(window, window.document); + ibexa.helpers.tooltips.parse(navigationMenu); +})(window, window.document, window.ibexa); diff --git a/src/bundle/Resources/public/scss/_main-container.scss b/src/bundle/Resources/public/scss/_main-container.scss index 74b1d6b120..384117ae57 100644 --- a/src/bundle/Resources/public/scss/_main-container.scss +++ b/src/bundle/Resources/public/scss/_main-container.scss @@ -30,7 +30,8 @@ .ibexa-main-container { &__side-column { width: 25%; - max-width: calculateRem(350px); + min-width: calculateRem(300px); + max-width: calculateRem(400px); } &__content-column { diff --git a/src/bundle/Resources/public/scss/_navigation-menu.scss b/src/bundle/Resources/public/scss/_navigation-menu.scss index 084d992ef7..ec0cb71d67 100644 --- a/src/bundle/Resources/public/scss/_navigation-menu.scss +++ b/src/bundle/Resources/public/scss/_navigation-menu.scss @@ -17,6 +17,7 @@ border: 0; flex-basis: 100%; text-align: center; + overflow: hidden; &--active { background-color: $ibexa-color-white; @@ -93,4 +94,9 @@ &__secondary-item-label { max-width: calc(100% - #{calculateRem(45px)}); } + + &__item-label { + text-overflow: ellipsis; + overflow: hidden; + } } diff --git a/src/bundle/Resources/views/themes/admin/ui/menu/anchor_menu.html.twig b/src/bundle/Resources/views/themes/admin/ui/menu/anchor_menu.html.twig index 9ae16fddcf..a7efceebb7 100644 --- a/src/bundle/Resources/views/themes/admin/ui/menu/anchor_menu.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/menu/anchor_menu.html.twig @@ -133,7 +133,9 @@ {%- set itemTagElement = itemTagElement|default('button') %} <{{ itemTagElement }}{{ knp_menu.attributes(attributes) }}> - {{ block('label') }} +
    + {{ block('label') }} +
    {% endblock %} From 4226b864e50a7a2cdd9cbd6e688b9c3b72d69996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grabowski?= Date: Mon, 8 Aug 2022 11:34:39 +0200 Subject: [PATCH 17/18] fix to active menu and cr --- .../admin.anchor.sections.navigation.js | 28 +++++++++---------- .../public/scss/_navigation-menu.scss | 6 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js b/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js index ccf0afe9a7..a6c5f04ee9 100644 --- a/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js +++ b/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js @@ -18,13 +18,13 @@ const fitSecondarySections = () => { const primarySection = doc.querySelector('.ibexa-edit-content__primary-section--active'); const contentColumn = doc.querySelector('.ibexa-main-container__content-column'); - const firstSection = primarySection.querySelector('.ibexa-edit-content__secondary-section:first-child'); - const lastSection = primarySection.querySelector('.ibexa-edit-content__secondary-section:last-child'); + const firstSection = primarySection.firstElementChild; + const lastSection = primarySection.lastElementChild; const contentContainer = contentColumn.querySelector('.ibexa-edit-content__container'); contentContainer.style.paddingBottom = '0px'; - if (!firstSection.isSameNode(lastSection) && lastSection && lastSection.offsetHeight) { + if (!firstSection.isSameNode(lastSection) && lastSection.offsetHeight) { const headerContainer = doc.querySelector('.ibexa-edit-header__container'); const heightFromLastSection = contentContainer.offsetHeight - lastSection.offsetTop; const contentColumnBodyHeight = contentColumn.offsetHeight - headerContainer.offsetHeight; @@ -74,7 +74,7 @@ const primaryMenuItems = doc.querySelectorAll('.ibexa-navigation-menu__primary--list .ibexa-navigation-menu__primary-item'); primaryMenuItems.forEach((item) => { - item.classList.toggle('ibexa-navigation-menu__primary-item--active', item.isSameNode(event.target)); + item.classList.toggle('ibexa-navigation-menu__primary-item--active', item.isSameNode(event.currentTarget)); }); showPrimarySection(targetId); @@ -97,12 +97,12 @@ navigateTo(targetId); }; - const bindPrimaryMenuListEvents = () => { + const attachPrimaryMenuListEvents = () => { const items = doc.querySelectorAll('.ibexa-navigation-menu__primary--list .ibexa-navigation-menu__primary-item'); items.forEach((item) => item.addEventListener('click', onSelectPrimaryMenuList, false)); }; - const bindPrimaryMenuDropdownEvents = () => { + const attachPrimaryMenuDropdownEvents = () => { const sourceSelect = doc.querySelector('.ibexa-navigation-menu__primary--dropdown .ibexa-dropdown__source .ibexa-input'); if (!sourceSelect) { @@ -111,14 +111,14 @@ sourceSelect.addEventListener('change', onSelectPrimaryMenuDropdown, false); }; - const bindSecondaryMenuEvents = () => { + const attachSecondaryMenuEvents = () => { const items = doc.querySelectorAll('.ibexa-navigation-menu .ibexa-navigation-menu__secondary-item-btn'); items.forEach((item) => item.addEventListener('click', onSelectSecondaryMenu, false)); }; - const bindScrollContainerEvents = () => { - const allSections = [...doc.querySelectorAll('.ibexa-edit-content__secondary-section')]; - const headerContainer = doc.querySelector('.ibexa-edit-header__container'); + const attachScrollContainerEvents = () => { + const allSections = [...formContainerNode.querySelectorAll('.ibexa-edit-content__secondary-section')]; + const headerContainer = formContainerNode.querySelector('.ibexa-edit-header__container'); let previousFirstVisibleSection = null; if (formContainerNode && allSections.length) { @@ -150,10 +150,10 @@ } }; - bindPrimaryMenuListEvents(); - bindPrimaryMenuDropdownEvents(); - bindSecondaryMenuEvents(); - bindScrollContainerEvents(); + attachPrimaryMenuListEvents(); + attachPrimaryMenuDropdownEvents(); + attachSecondaryMenuEvents(); + attachScrollContainerEvents(); fitSecondarySections(); ibexa.helpers.tooltips.parse(navigationMenu); })(window, window.document, window.ibexa); diff --git a/src/bundle/Resources/public/scss/_navigation-menu.scss b/src/bundle/Resources/public/scss/_navigation-menu.scss index ec0cb71d67..11d85805ed 100644 --- a/src/bundle/Resources/public/scss/_navigation-menu.scss +++ b/src/bundle/Resources/public/scss/_navigation-menu.scss @@ -69,7 +69,7 @@ color: $ibexa-color-info; font-weight: 600; - &:before { + &::before { background-color: $ibexa-color-info; } } @@ -79,13 +79,13 @@ background: $ibexa-color-info-100; font-weight: 600; - &:before { + &::before { background-color: $ibexa-color-info; } } &--invalid { - &:after { + &::after { opacity: 1; } } From e160597b3f599aec7222f50d3e452972f90baa54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grabowski?= Date: Mon, 8 Aug 2022 12:59:57 +0200 Subject: [PATCH 18/18] fix to scroll --- .../public/js/scripts/admin.anchor.sections.navigation.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js b/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js index a6c5f04ee9..a6060cef97 100644 --- a/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js +++ b/src/bundle/Resources/public/js/scripts/admin.anchor.sections.navigation.js @@ -118,7 +118,7 @@ }; const attachScrollContainerEvents = () => { const allSections = [...formContainerNode.querySelectorAll('.ibexa-edit-content__secondary-section')]; - const headerContainer = formContainerNode.querySelector('.ibexa-edit-header__container'); + const headerContainer = doc.querySelector('.ibexa-edit-header__container'); let previousFirstVisibleSection = null; if (formContainerNode && allSections.length) {