/** * 메뉴 트리 공통 스크립트 * - 부서 권한 관리 (department-permissions) - 테이블 기반 * - 개인 권한 관리 (user-permissions) - 테이블 기반 * - 권한 분석 (permission-analyze) - div 기반 * - 메뉴 관리 (menus) - 테이블 기반 * * localStorage 키: 'menu-tree-collapsed' (접힌 메뉴 ID 배열) * IIFE로 감싸서 HTMX swap 시 재실행해도 const 재선언 에러 방지 */ (function() { 'use strict'; const MENU_TREE_STORAGE_KEY = 'menu-tree-collapsed'; function getCollapsedMenuIds() { try { const data = localStorage.getItem(MENU_TREE_STORAGE_KEY); return data ? new Set(JSON.parse(data)) : new Set(); } catch (e) { return new Set(); } } function saveCollapsedMenuIds(collapsedSet) { try { localStorage.setItem(MENU_TREE_STORAGE_KEY, JSON.stringify([...collapsedSet])); } catch (e) { // storage full 등 무시 } } function getChildElements(parentId) { let children = document.querySelectorAll(`tr.menu-row[data-parent-id="${parentId}"]`); if (children.length > 0) return children; return document.querySelectorAll(`.menu-item[data-parent-id="${parentId}"]`); } function hideChildren(parentId) { const children = getChildElements(parentId); children.forEach(child => { child.style.display = 'none'; const childId = child.getAttribute('data-menu-id'); hideChildren(childId); }); } function showChildren(parentId) { const children = getChildElements(parentId); children.forEach(child => { child.style.display = ''; const childId = child.getAttribute('data-menu-id'); const childButton = child.querySelector(`.toggle-btn[data-menu-id="${childId}"]`); if (childButton) { const chevron = childButton.querySelector('.chevron-icon'); if (chevron && !chevron.classList.contains('rotate-[-90deg]')) { showChildren(childId); } } }); } window.toggleChildren = function(menuId) { const button = document.querySelector(`.toggle-btn[data-menu-id="${menuId}"]`); if (!button) return; const chevron = button.querySelector('.chevron-icon'); if (!chevron) return; const collapsedSet = getCollapsedMenuIds(); const isCollapsed = chevron.classList.contains('rotate-[-90deg]'); if (isCollapsed) { chevron.classList.remove('rotate-[-90deg]'); showChildren(menuId); collapsedSet.delete(String(menuId)); } else { chevron.classList.add('rotate-[-90deg]'); hideChildren(menuId); collapsedSet.add(String(menuId)); } saveCollapsedMenuIds(collapsedSet); }; window.toggleAllChildren = function(collapse) { const buttons = document.querySelectorAll('.toggle-btn'); const collapsedSet = collapse ? new Set() : new Set(); buttons.forEach(btn => { const menuId = btn.getAttribute('data-menu-id'); const chevron = btn.querySelector('.chevron-icon'); if (!chevron) return; if (collapse) { chevron.classList.add('rotate-[-90deg]'); hideChildren(menuId); collapsedSet.add(String(menuId)); } else { chevron.classList.remove('rotate-[-90deg]'); showChildren(menuId); } }); saveCollapsedMenuIds(collapsedSet); }; window.restoreMenuTreeState = function() { const collapsedSet = getCollapsedMenuIds(); if (collapsedSet.size === 0) return; collapsedSet.forEach(menuId => { const button = document.querySelector(`.toggle-btn[data-menu-id="${menuId}"]`); if (!button) return; const chevron = button.querySelector('.chevron-icon'); if (chevron) { chevron.classList.add('rotate-[-90deg]'); hideChildren(menuId); } }); }; })();