diff --git a/public/js/menu-tree.js b/public/js/menu-tree.js new file mode 100644 index 00000000..976aaa07 --- /dev/null +++ b/public/js/menu-tree.js @@ -0,0 +1,63 @@ +/** + * 메뉴 트리 공통 스크립트 + * - 부서 권한 관리 (department-permissions) - 테이블 기반 + * - 개인 권한 관리 (user-permissions) - 테이블 기반 + * - 권한 분석 (permission-analyze) - div 기반 + */ + +// 자식 메뉴 접기/펼치기 +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 isCollapsed = chevron.classList.contains('rotate-[-90deg]'); + + if (isCollapsed) { + // 펼치기 + chevron.classList.remove('rotate-[-90deg]'); + showChildren(menuId); + } else { + // 접기 + chevron.classList.add('rotate-[-90deg]'); + hideChildren(menuId); + } +}; + +// 자식 요소 선택자 (테이블: tr.menu-row, div: .menu-item) +function getChildElements(parentId) { + // 테이블 기반 (tr.menu-row) + let children = document.querySelectorAll(`tr.menu-row[data-parent-id="${parentId}"]`); + if (children.length > 0) return children; + + // div 기반 (.menu-item) + 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); + } + } + }); +} \ No newline at end of file diff --git a/resources/views/department-permissions/index.blade.php b/resources/views/department-permissions/index.blade.php index e77bc88e..7ca36320 100644 --- a/resources/views/department-permissions/index.blade.php +++ b/resources/views/department-permissions/index.blade.php @@ -148,4 +148,5 @@ function reloadPermissions() { } }); + @endsection diff --git a/resources/views/department-permissions/partials/permission-matrix.blade.php b/resources/views/department-permissions/partials/permission-matrix.blade.php index 2f392564..3e277603 100644 --- a/resources/views/department-permissions/partials/permission-matrix.blade.php +++ b/resources/views/department-permissions/partials/permission-matrix.blade.php @@ -20,16 +20,43 @@ $permissionTypes = ['view', 'create', 'update', 'delete', 'approve', 'export', 'manage']; @endphp @forelse($menus as $index => $menu) - + {{ $index + 1 }} -
+
+ {{-- 트리 구조 표시 --}} @if(($menu->depth ?? 0) > 0) - + └─ @endif - {{ $menu->name }} + + {{-- 폴더/아이템 아이콘 (폴더는 클릭으로 접기/펼치기) --}} + @if($menu->has_children) + + @else + + + + @endif + + {{-- 메뉴명 --}} + + {{ $menu->name }} +
diff --git a/resources/views/menus/index.blade.php b/resources/views/menus/index.blade.php index dcde7456..024d8fdb 100644 --- a/resources/views/menus/index.blade.php +++ b/resources/views/menus/index.blade.php @@ -142,50 +142,6 @@ class="bg-white rounded-lg shadow-sm overflow-hidden"> }); }; - // 자식 메뉴 접기/펼치기 - window.toggleChildren = function(menuId) { - const button = document.querySelector(`.toggle-btn[data-menu-id="${menuId}"]`); - const svg = button.querySelector('svg'); - const isCollapsed = svg.classList.contains('rotate-[-90deg]'); - - if (isCollapsed) { - // 펼치기 - svg.classList.remove('rotate-[-90deg]'); - showChildren(menuId); - } else { - // 접기 - svg.classList.add('rotate-[-90deg]'); - hideChildren(menuId); - } - }; - - // 재귀적으로 자식 메뉴 숨기기 - function hideChildren(parentId) { - const children = document.querySelectorAll(`tr.menu-row[data-parent-id="${parentId}"]`); - children.forEach(child => { - child.style.display = 'none'; - const childId = child.getAttribute('data-menu-id'); - // 하위의 하위도 숨기기 - hideChildren(childId); - }); - } - - // 재귀적으로 직계 자식만 표시 - function showChildren(parentId) { - const children = document.querySelectorAll(`tr.menu-row[data-parent-id="${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 childSvg = childButton.querySelector('svg'); - // 자식이 접혀있으면 그 하위는 보여주지 않음 - if (!childSvg.classList.contains('rotate-[-90deg]')) { - showChildren(childId); - } - } - }); - } + @endpush diff --git a/resources/views/menus/partials/table.blade.php b/resources/views/menus/partials/table.blade.php index 1b24e5ad..48bbbcff 100644 --- a/resources/views/menus/partials/table.blade.php +++ b/resources/views/menus/partials/table.blade.php @@ -21,24 +21,36 @@ {{ $menu->id }} -
+
+ {{-- 트리 구조 표시 --}} + @if(($menu->depth ?? 0) > 0) + └─ + @endif + + {{-- 폴더/아이템 아이콘 (폴더는 클릭으로 접기/펼치기) --}} @if($menu->has_children) @else - + + + @endif - @if(($menu->depth ?? 0) > 0) - - @endif -
-
{{ $menu->name }}
+ + {{-- 메뉴 정보 --}} +
+ + {{ $menu->name }} + @if($menu->is_external) (외부) @endif diff --git a/resources/views/permission-analyze/index.blade.php b/resources/views/permission-analyze/index.blade.php index 481bee35..a3a37df8 100644 --- a/resources/views/permission-analyze/index.blade.php +++ b/resources/views/permission-analyze/index.blade.php @@ -295,4 +295,5 @@ function exportCsv() { } }); + @endpush \ No newline at end of file diff --git a/resources/views/permission-analyze/partials/menu-tree.blade.php b/resources/views/permission-analyze/partials/menu-tree.blade.php index 65337825..55f3ed28 100644 --- a/resources/views/permission-analyze/partials/menu-tree.blade.php +++ b/resources/views/permission-analyze/partials/menu-tree.blade.php @@ -2,6 +2,8 @@