Skip to content

Commit

Permalink
IBX-6250: Redesign PB Config panel (#880)
Browse files Browse the repository at this point in the history
Co-authored-by: Dariusz Szut <[email protected]>
Co-authored-by: katarzynazawada <>
  • Loading branch information
GrabowskiM and dew326 authored Oct 31, 2023
1 parent 9d8cd93 commit f6b11f7
Show file tree
Hide file tree
Showing 19 changed files with 644 additions and 458 deletions.
1 change: 1 addition & 0 deletions src/bundle/Resources/encore/ibexa.js.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const layout = [
path.resolve(__dirname, '../public/js/scripts/admin.form.error.js'),
path.resolve(__dirname, '../public/js/scripts/embedded.item.actions'),
path.resolve(__dirname, '../public/js/scripts/widgets/flatpickr.js'),
path.resolve(__dirname, '../public/js/scripts/admin.form.tabs.validation.js'),
];
const fieldTypes = [];

Expand Down
178 changes: 52 additions & 126 deletions src/bundle/Resources/public/js/scripts/admin.anchor.navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,82 +12,15 @@
const lastSectionObserver = new ResizeObserver(() => {
fitSections();
});
const getSectionGroupActiveItems = () => {
const sectionGroupNode = formContainerNode.querySelector('.ibexa-anchor-navigation__section-group') ?? formContainerNode;
const sections = sectionGroupNode.querySelectorAll('.ibexa-anchor-navigation__section');

return [...sections];
};
let currentlyVisibleSections = getSectionGroupActiveItems();
const attachSectionGroupsMenuListEvents = () => {
const items = doc.querySelectorAll('.ibexa-anchor-navigation-menu__section-groups--list .ibexa-tab-switcher__item');

items.forEach((item) => item.addEventListener('click', onSelectSectionGroupsMenuList, false));
};
const attachSectionGroupsMenuDropdownEvents = () => {
const sourceSelect = doc.querySelector(
'.ibexa-anchor-navigation-menu__section-groups--dropdown .ibexa-dropdown__source .ibexa-input',
);

if (!sourceSelect) {
return;
}

sourceSelect.addEventListener('change', onSelectSectionGroupsMenuDropdown, false);
};
const onSelectSectionGroupsMenuList = (event) => {
const { targetId } = event.currentTarget.dataset;
const sectionsMenuNode = doc.querySelector(`.ibexa-anchor-navigation-menu__sections[data-id="${targetId}"]`);
const sectionGroupsMenuItems = doc.querySelectorAll(
'.ibexa-anchor-navigation-menu__section-groups--list .ibexa-tab-switcher__item',
);

sectionGroupsMenuItems.forEach((item) => {
item.classList.toggle('ibexa-tab-switcher__item--active', item.isSameNode(event.currentTarget));
});
showSectionGroup(targetId);
showSectionsMenu(sectionsMenuNode);
};
const onSelectSectionGroupsMenuDropdown = (event) => {
const targetId = event.currentTarget.value;
const sectionsMenuNode = doc.querySelector(`.ibexa-anchor-navigation-menu__sections[data-id="${targetId}"]`);
const getVisibleSections = () => {
let sectionGroupNode = formContainerNode;

showSectionGroup(targetId);
showSectionsMenu(sectionsMenuNode);
};
const showSectionsMenu = (node) => {
const items = doc.querySelectorAll('.ibexa-anchor-navigation-menu__sections');

items.forEach((item) => item.classList.toggle('ibexa-anchor-navigation-menu__sections--active', item.isSameNode(node)));
};
const showSectionGroup = (id) => {
const sectionGroupItems = formContainerNode.querySelectorAll('.ibexa-anchor-navigation__section-group');

sectionGroupItems.forEach((item) => {
item.classList.toggle('ibexa-anchor-navigation__section-group--active', item.dataset.id === id);
});

currentlyVisibleSections = getSectionGroupActiveItems();

initFitSection();
};
const attachSectionsMenuEvents = () => {
const items = doc.querySelectorAll('.ibexa-anchor-navigation-menu .ibexa-anchor-navigation-menu__sections-item-btn');
sectionGroupNode = formContainerNode.querySelector('.ibexa-anchor-navigation__section-group--active') ?? sectionGroupNode;
sectionGroupNode = formContainerNode.querySelector('.ibexa-anchor-navigation__section-group') ?? sectionGroupNode;

items.forEach((item) => item.addEventListener('click', onSelectSectionsMenu, false));
};
const onSelectSectionsMenu = (event) => {
const { targetId } = event.currentTarget.dataset;

navigateTo(targetId);
};
const navigateTo = (targetId) => {
const sectionNode = formContainerNode.querySelector(`.ibexa-anchor-navigation__section[data-id="${targetId}"]`);
const sections = sectionGroupNode.querySelectorAll('.ibexa-anchor-navigation__section');

formContainerNode.scrollTo({
top: sectionNode.offsetTop,
behavior: 'smooth',
});
return [...sections];
};
const getFirstSection = (sectionGroup) => {
return sectionGroup.querySelector('.ibexa-anchor-navigation__section');
Expand Down Expand Up @@ -151,15 +84,16 @@

if (formContainerNode && allSections.length) {
formContainerNode.addEventListener('scroll', () => {
let firstVisibleSection = currentlyVisibleSections.find((section) => {
const visibleSections = getVisibleSections();
let firstVisibleSection = visibleSections.find((section) => {
const { top, height } = section.getBoundingClientRect();
const headerBottomContainerHeight = header.offsetHeight - headerContainer?.offsetHeight;

return top + height >= headerContainer?.offsetHeight + headerBottomContainerHeight + SECTION_ADJUST_MARGIN_TOP;
});

if (!firstVisibleSection) {
firstVisibleSection = currentlyVisibleSections.at(-1);
firstVisibleSection = visibleSections.at(-1);
}

if (previousFirstVisibleSection === firstVisibleSection) {
Expand All @@ -186,61 +120,53 @@
item.classList.toggle('ibexa-anchor-navigation-menu__sections-item-btn--active', item.isSameNode(node));
});
};
const attachListenForIsInvalidClass = () => {
const classChangedCallback = (mutationList) => {
mutationList.forEach((mutation) => {
const { oldValue, target } = mutation;
const hadIsInvalidClass = oldValue?.includes('.is-invalid') ?? false;
const hasIsInvalidClass = target.classList.contains('is-invalid');

if (hadIsInvalidClass !== hasIsInvalidClass) {
const sectionGroup = target.closest('.ibexa-anchor-navigation__section-group');

if (!sectionGroup) {
return;
}

const { id } = sectionGroup.dataset;
const hasGroupError = !!sectionGroup.querySelector('.is-invalid');
const correspondingMenuItem =
doc.querySelector(`.ibexa-tab-switcher__item[data-target-id="${id}"]`) ??
doc.querySelector(`.ibexa-anchor-navigation-menu .ibexa-dropdown__item[data-value="${id}"]`);

if (!correspondingMenuItem) {
return;
}

const errorIconNode = correspondingMenuItem.querySelector('.ibexa-tab-switcher__item-error');
const dropdownWidget = doc.querySelector('.ibexa-anchor-navigation-menu .ibexa-dropdown');

errorIconNode.classList.toggle('ibexa-tab-switcher__item-error--hidden', !hasGroupError);

if (dropdownWidget) {
const hasError = !!dropdownWidget.querySelector(
'.ibexa-anchor-navigation-menu__item-error:not(ibexa-anchor-navigation-menu__item-error--hidden)',
);
const errorDropdownContainer = doc.querySelector('.ibexa-anchor-navigation-menu__error');

errorDropdownContainer.classList.toggle('ibexa-anchor-navigation-menu__error--hidden', !hasError);
}
}
const getTabHash = (node) => {
const nodeId = node.href.split('#')[1];

return `#${nodeId}`;
};
const attachMenuTabShowEvents = () => {
doc.querySelectorAll('.ibexa-anchor-navigation .ibexa-tabs__tab:not(.ibexa-tabs__tab--more)').forEach((tabLink) => {
tabLink.addEventListener('shown.bs.tab', (event) => {
const { target, relatedTarget } = event;
const prevHashId = getTabHash(relatedTarget);
const currHashId = getTabHash(target);
const prevMainContentTab = doc.querySelector(`[data-id="${prevHashId}"]`);
const currMainContentTab = doc.querySelector(`[data-id="${currHashId}"]`);

prevMainContentTab?.classList.toggle('ibexa-anchor-navigation__section-group--active', false);
currMainContentTab?.classList.toggle('ibexa-anchor-navigation__section-group--active', true);

initFitSection();
});
};
const observer = new MutationObserver(classChangedCallback);

observer.observe(formContainerNode, {
subtree: true,
attributes: true,
attributeFilter: ['class'],
attributeOldValue: true,
});
};
const attachMenuSectionsEvents = () => {
const items = doc.querySelectorAll('.ibexa-anchor-navigation-menu .ibexa-anchor-navigation-menu__sections-item-btn');

attachSectionGroupsMenuListEvents();
attachSectionGroupsMenuDropdownEvents();
attachSectionsMenuEvents();
attachScrollContainerEvents();
attachListenForIsInvalidClass();
items.forEach((item) => item.addEventListener('click', onSelectSectionsMenu, false));
};
const onSelectSectionsMenu = (event) => {
const { targetId } = event.currentTarget.dataset;

navigateTo(targetId);
};
const navigateTo = (targetId) => {
const sectionNode = formContainerNode.querySelector(`.ibexa-anchor-navigation__section[data-id="${targetId}"]`);

if (!sectionNode) {
return;
}

formContainerNode.scrollTo({
top: sectionNode.offsetTop,
behavior: 'smooth',
});
};

attachMenuTabShowEvents();
attachMenuSectionsEvents();
initFitSection();
attachScrollContainerEvents();
ibexa.helpers.tooltips.parse(navigationMenu);
})(window, window.document, window.ibexa);
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
(function (global, doc) {
const tabsHeaders = doc.querySelectorAll('.ibexa-tabs[data-form-selector]');
const getHrefFromGroup = (group) => {
if (group.dataset.id) {
return group.dataset.id;
}

return `#${group.id}`;
};

tabsHeaders.forEach((tabsHeader) => {
const popupMenu = tabsHeader.querySelector('.ibexa-tabs__popup-menu');
const moreBtn = tabsHeader.querySelector('.ibexa-tabs__tab--more');
const { formSelector, formTabGroupSelector } = tabsHeader.dataset;
const formNode = doc.querySelector(formSelector);
const classInvalidChangedCallback = (mutationList) => {
mutationList.forEach((mutation) => {
const { oldValue, target } = mutation;
const hadIsInvalidClass = oldValue?.includes('is-invalid') ?? false;
const hasIsInvalidClass = target.classList.contains('is-invalid');

if (hadIsInvalidClass !== hasIsInvalidClass) {
const sectionGroup = target.closest(formTabGroupSelector);

if (!sectionGroup) {
return;
}

const href = getHrefFromGroup(sectionGroup);
const hasGroupError = !!sectionGroup.querySelector('.is-invalid');
const correspondingMenuItemLink = doc.querySelector(`.ibexa-tabs__tab [href="${href}"]`);
const correspondingMenuItem = correspondingMenuItemLink.parentNode;

correspondingMenuItem?.classList.toggle('ibexa-tabs__tab--error', hasGroupError);

if (correspondingMenuItemLink) {
const tabLinkId = correspondingMenuItemLink.id;
const popupMenuItem = popupMenu.querySelector(`[data-tab-link-id="${tabLinkId}"]`);

popupMenuItem?.classList.toggle('ibexa-popup-menu__item--error', hasGroupError);
}
}
});
};
const invalidObserver = new MutationObserver(classInvalidChangedCallback);

invalidObserver.observe(formNode, {
subtree: true,
attributes: true,
attributeFilter: ['class'],
attributeOldValue: true,
});

if (popupMenu) {
const classInvalidHiddenChangedCallback = (mutationList) => {
mutationList.forEach(() => {
const popupMenuItems = popupMenu.querySelectorAll(
'.ibexa-popup-menu__item--error:not(.ibexa-popup-menu__item--hidden)',
);

moreBtn.classList.toggle('ibexa-tabs__tab--error', popupMenuItems.length);
});
};
const invalidHiddenObserver = new MutationObserver(classInvalidHiddenChangedCallback);

invalidHiddenObserver.observe(popupMenu, {
subtree: true,
attributes: true,
attributeFilter: ['class'],
attributeOldValue: true,
});
}
});
})(window, window.document);
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@
}
};

doc.querySelectorAll('.ibexa-tabs .nav-link').forEach((tab) => tab.addEventListener('shown.bs.tab', invalidateSizeMap));
doc.querySelectorAll('.ibexa-tabs--content .nav-link').forEach((tab) => tab.addEventListener('shown.bs.tab', invalidateSizeMap));

ibexa.addConfig('fieldTypeValidators', [validator], true);
})(window, window.document, window.ibexa, window.L, window.Translator);
16 changes: 9 additions & 7 deletions src/bundle/Resources/public/scss/_anchor-navigation.scss
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,19 @@
min-width: calculateRem(240px);
list-style: none;
display: none;
padding-left: 0;

&:not(:first-child) {
margin: calculateRem(24px) 0 0;
padding: calculateRem(24px) 0 0;
border-top: calculateRem(1px) solid $ibexa-color-light;
}
margin: calculateRem(24px) 0 0;
padding: calculateRem(24px) 0 0;
border-top: calculateRem(1px) solid $ibexa-color-light;

&--active {
display: block;
}

&--no-border {
border: 0;
margin-top: 0;
padding-top: 0;
}
}

&__sections-item-btn {
Expand Down
13 changes: 8 additions & 5 deletions src/bundle/Resources/public/scss/_buttons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -124,23 +124,26 @@
}

&--ghost.ibexa-btn {
--ibexa-btn-primary-color: var(--ibexa-primary-color, #{$ibexa-color-primary});

color: $ibexa-color-dark;
fill: $ibexa-color-dark;

&:hover {
color: $ibexa-color-primary;
color: var(--ibexa-btn-primary-color);

.ibexa-icon {
fill: $ibexa-color-primary;
fill: var(--ibexa-btn-primary-color);
}
}

&:focus {
color: $ibexa-color-primary;
border-color: $ibexa-color-primary;
color: var(--ibexa-btn-primary-color);
border-color: var(--ibexa-btn-primary-color);
box-shadow: 0 0 0 calculateRem(3px) var(--ibexa-btn-shadow-box-primary-color);

.ibexa-icon {
fill: $ibexa-color-primary;
fill: var(--ibexa-btn-primary-color);
}
}

Expand Down
Loading

0 comments on commit f6b11f7

Please sign in to comment.