Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IBX-6250: Redesign PB Config panel #880

Merged
merged 15 commits into from
Oct 31, 2023
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];
lucasOsti marked this conversation as resolved.
Show resolved Hide resolved

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
Loading