- 테넌트 선택: 헤더에서 선택된 테넌트 기준으로 동작 - UI 개선: 레벨 뱃지(Lv.2, Lv.3), 동기화 필요 메뉴만 체크박스 활성화 - 전체선택 체크박스 추가 (로컬/원격 각각) - 선택된 메뉴 개수 표시 (Push/Pull 버튼 옆) - 상위 메뉴 선택 시 하위 메뉴 자동 선택 - Pull 시 부모 메뉴 이름 기반 매핑 수정 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
122 lines
6.3 KiB
PHP
122 lines
6.3 KiB
PHP
@php
|
|
$isLocalOnly = $side === 'local' && in_array($menu['name'], $diff['local_only'] ?? []);
|
|
$isRemoteOnly = $side === 'remote' && in_array($menu['name'], $diff['remote_only'] ?? []);
|
|
$isBoth = in_array($menu['name'], $diff['both'] ?? []);
|
|
|
|
// 동기화 필요 여부 (로컬에서는 local_only만, 원격에서는 remote_only만 체크 가능)
|
|
$needsSync = $isLocalOnly || $isRemoteOnly;
|
|
|
|
$bgClass = '';
|
|
$badgeClass = '';
|
|
$badgeText = '';
|
|
|
|
if ($isLocalOnly) {
|
|
$bgClass = 'bg-green-50';
|
|
$badgeClass = 'bg-green-100 text-green-700';
|
|
$badgeText = 'NEW';
|
|
} elseif ($isRemoteOnly) {
|
|
$bgClass = 'bg-purple-50';
|
|
$badgeClass = 'bg-purple-100 text-purple-700';
|
|
$badgeText = 'NEW';
|
|
} else {
|
|
$bgClass = 'hover:bg-gray-50';
|
|
}
|
|
@endphp
|
|
|
|
@php
|
|
$menuKey = $side . '_' . ($menu['id'] ?? Str::slug($menu['name']));
|
|
@endphp
|
|
<div class="menu-group" data-menu-key="{{ $menuKey }}">
|
|
<div class="border rounded-lg mb-1 {{ $bgClass }}" style="margin-left: {{ $depth * 2 }}rem;">
|
|
<div class="flex items-center gap-2 px-3 py-2">
|
|
<!-- 체크박스 (동기화 필요한 메뉴만 활성화) - 양쪽 모두 이름으로 매핑 -->
|
|
@if($side === 'local')
|
|
<input type="checkbox" name="local_menu" value="{{ $menu['name'] }}"
|
|
data-menu-id="{{ $menu['id'] }}"
|
|
data-menu-key="{{ $menuKey }}"
|
|
data-has-children="{{ !empty($menu['children']) ? 'true' : 'false' }}"
|
|
onchange="toggleChildren(this)"
|
|
class="w-4 h-4 rounded focus:ring-green-500 {{ $needsSync ? 'text-green-600 border-gray-300' : 'bg-gray-200 border-gray-300 cursor-not-allowed' }}"
|
|
{{ !$needsSync ? 'disabled' : '' }}>
|
|
@else
|
|
<input type="checkbox" name="remote_menu" value="{{ $menu['name'] }}"
|
|
data-menu-key="{{ $menuKey }}"
|
|
data-has-children="{{ !empty($menu['children']) ? 'true' : 'false' }}"
|
|
onchange="toggleChildren(this)"
|
|
class="w-4 h-4 rounded focus:ring-purple-500 {{ $needsSync ? 'text-purple-600 border-gray-300' : 'bg-gray-200 border-gray-300 cursor-not-allowed' }}"
|
|
{{ !$needsSync ? 'disabled' : '' }}>
|
|
@endif
|
|
|
|
<!-- 아이콘 -->
|
|
@if(!empty($menu['icon']))
|
|
<span class="w-5 h-5 flex items-center justify-center text-gray-400">
|
|
@switch($menu['icon'])
|
|
@case('home')
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
|
|
</svg>
|
|
@break
|
|
@case('folder')
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z" />
|
|
</svg>
|
|
@break
|
|
@case('cog')
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
|
</svg>
|
|
@break
|
|
@case('cube')
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" />
|
|
</svg>
|
|
@break
|
|
@case('collection')
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
|
|
</svg>
|
|
@break
|
|
@default
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
|
</svg>
|
|
@endswitch
|
|
</span>
|
|
@endif
|
|
|
|
<!-- 메뉴 이름 + 뎁스 레벨 -->
|
|
<span class="flex-1 text-sm text-gray-800 flex items-center gap-2">
|
|
{{ $menu['name'] }}
|
|
@if($depth > 0)
|
|
<span class="text-[10px] text-gray-400 bg-gray-100 px-1 rounded">Lv.{{ $depth + 1 }}</span>
|
|
@endif
|
|
</span>
|
|
|
|
<!-- 배지 -->
|
|
@if($badgeText)
|
|
<span class="px-1.5 py-0.5 text-xs font-medium rounded {{ $badgeClass }}">{{ $badgeText }}</span>
|
|
@endif
|
|
|
|
<!-- URL -->
|
|
@if($menu['url'] !== '#')
|
|
<span class="text-xs text-gray-400 font-mono">{{ Str::limit($menu['url'], 20) }}</span>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 자식 메뉴 -->
|
|
@if(!empty($menu['children']))
|
|
<div class="children-container">
|
|
@foreach($menu['children'] as $child)
|
|
@include('menus._sync_menu_item', [
|
|
'menu' => $child,
|
|
'side' => $side,
|
|
'diff' => $diff,
|
|
'depth' => $depth + 1
|
|
])
|
|
@endforeach
|
|
</div>
|
|
@endif
|
|
</div>
|