diff --git a/pages/admin/tenants/_form.phtml b/pages/admin/tenants/_form.phtml index 1067c51..4b53be7 100644 --- a/pages/admin/tenants/_form.phtml +++ b/pages/admin/tenants/_form.phtml @@ -811,10 +811,11 @@ $openOverrideCard = $detailsOpenAll;

+ -
> +
> @@ -862,7 +863,7 @@ $openOverrideCard = $detailsOpenAll;
-
> +
> @@ -890,11 +891,12 @@ $openOverrideCard = $detailsOpenAll;
-
+
$syncFieldLabel): ?>
+ diff --git a/web/js/app-init.js b/web/js/app-init.js index e6d29b8..d268dbb 100644 --- a/web/js/app-init.js +++ b/web/js/app-init.js @@ -18,6 +18,7 @@ import { initTenantSwitcher } from './components/app-tenant-switcher.js'; import { initColorDefaultToggle } from './components/app-color-default-toggle.js'; import { initCustomFieldOptionsToggle } from './components/app-custom-field-options-toggle.js'; import { initTenantSsoToggle } from './components/app-tenant-sso-toggle.js'; +import { initTenantLdapToggle } from './components/app-tenant-ldap-toggle.js'; import { initTelemetrySettings } from './components/app-settings-telemetry.js'; import { initStandardDetailPages } from './components/app-standard-detail-page.js'; import { initAutoSubmit } from './components/app-auto-submit.js'; @@ -231,6 +232,10 @@ const bootRuntime = async () => { scope: 'global', configPath: 'components.tenantSsoToggle', }); + runtime.register('tenant-ldap-toggle', initTenantLdapToggle, { + scope: 'global', + configPath: 'components.tenantLdapToggle', + }); runtime.register('standard-detail-page', initStandardDetailPages, { scope: 'global', configPath: 'components.standardDetailPage', diff --git a/web/js/components/app-tenant-ldap-toggle.js b/web/js/components/app-tenant-ldap-toggle.js new file mode 100644 index 0000000..f66438c --- /dev/null +++ b/web/js/components/app-tenant-ldap-toggle.js @@ -0,0 +1,96 @@ +/** + * Shows/hides LDAP configuration fields based on tenant LDAP toggle. + * Mirrors app-tenant-sso-toggle.js pattern for Microsoft SSO. + */ +import { resolveHost } from '../core/app-dom.js'; + +const syncControlState = (container, show) => { + if (!(container instanceof HTMLElement)) { + return; + } + + container.hidden = !show; + container.querySelectorAll('input, select, textarea, button').forEach((control) => { + if ((control instanceof HTMLInputElement) && control.type === 'hidden') { + return; + } + + if (!control.dataset.initialDisabled) { + control.dataset.initialDisabled = control.hasAttribute('disabled') ? '1' : '0'; + } + + if (!show) { + control.setAttribute('disabled', 'disabled'); + return; + } + + if (control.dataset.initialDisabled === '1') { + control.setAttribute('disabled', 'disabled'); + return; + } + + control.removeAttribute('disabled'); + }); +}; + +const initRoot = (root) => { + const enabledInput = root.querySelector('[data-tenant-ldap-enabled]'); + if (!(enabledInput instanceof HTMLInputElement)) { + return null; + } + + const syncToggle = root.querySelector('[data-tenant-ldap-sync-toggle]'); + const enabledBlocks = root.querySelectorAll('[data-tenant-ldap-when-enabled]'); + const syncFieldsBlock = root.querySelector('[data-tenant-ldap-sync-fields]'); + + const updateUi = () => { + const ldapEnabled = enabledInput.checked; + const syncEnabled = syncToggle instanceof HTMLInputElement ? syncToggle.checked : false; + + enabledBlocks.forEach((block) => syncControlState(block, ldapEnabled)); + syncControlState(syncFieldsBlock, ldapEnabled && syncEnabled); + }; + + enabledInput.addEventListener('change', updateUi); + if (syncToggle instanceof HTMLInputElement) { + syncToggle.addEventListener('change', updateUi); + } + + updateUi(); + return () => { + enabledInput.removeEventListener('change', updateUi); + if (syncToggle instanceof HTMLInputElement) { + syncToggle.removeEventListener('change', updateUi); + } + }; +}; + +export function initTenantLdapToggle(root = document, options = {}) { + const host = resolveHost(root); + const selector = String(options.selector || '[data-tenant-ldap-root]').trim() || '[data-tenant-ldap-root]'; + const roots = Array.from(host.querySelectorAll(selector)); + if (!roots.length) { + return { destroy: () => {} }; + } + + const cleanupFns = []; + roots.forEach((item) => { + if (!(item instanceof HTMLElement) || item.dataset.tenantLdapToggleBound === '1') { + return; + } + item.dataset.tenantLdapToggleBound = '1'; + const cleanup = initRoot(item); + if (typeof cleanup === 'function') { + cleanupFns.push(cleanup); + } + cleanupFns.push(() => { + delete item.dataset.tenantLdapToggleBound; + }); + }); + + const destroy = () => { + cleanupFns.forEach((cleanup) => cleanup()); + }; + + return { destroy }; +}