Files

159 lines
9.7 KiB
PHP

{{-- Permission grid partial. Expects: $model (string), $permissionGroups (array), $allVerbs (array), $isSystem (bool) --}}
@php $isSystem = $isSystem ?? false; @endphp
<div class="-mx-6 overflow-x-auto px-6">
<div style="min-width: calc(140px + {{ count($allVerbs) }} * 72px)">
@if ($isSystem)
<div class="mb-2 flex items-center gap-1.5 text-xs text-gray-500">
<x-icon name="lock-closed" class="h-3.5 w-3.5" />
{{ __('System role permissions are locked and cannot be modified.') }}
</div>
@endif
@foreach ($permissionGroups as $group)
@if (!empty($group['section']))
<div class="mt-3 mb-1 border-t border-gray-200 pt-2">
<span class="text-xs font-semibold uppercase tracking-wide text-gray-400">{{ __($group['section']) }}</span>
</div>
@elseif (!empty($group['inline']))
@php $inlinePerms = array_values($group['permissions']); $inlineKeys = array_keys($group['permissions']); @endphp
<div class="grid gap-x-1 rounded hover:bg-gray-50 py-2"
style="grid-template-columns: 140px repeat({{ count($allVerbs) }}, 72px); align-items: start;">
<div class="text-xs font-medium text-gray-700 pl-1">{{ __($group['inline']) }}</div>
@foreach ($allVerbs as $vIndex => $verb)
<div class="flex justify-center">
@if (isset($inlineKeys[$vIndex]))
<label class="flex flex-col items-center gap-0.5 {{ $isSystem ? 'cursor-not-allowed' : 'cursor-pointer' }}">
<input
type="checkbox"
value="{{ $inlineKeys[$vIndex] }}"
wire:model="{{ $model }}.permissions"
{{ $isSystem ? 'disabled' : '' }}
class="rounded border-gray-300 text-theme-brand focus:ring-theme-brand h-3.5 w-3.5 {{ $isSystem ? 'cursor-not-allowed opacity-60' : 'cursor-pointer' }}">
<span class="text-xs text-gray-500">{{ __($inlinePerms[$vIndex]) }}</span>
</label>
@endif
</div>
@endforeach
</div>
@elseif (!empty($group['fixed']))
@foreach ($group['fixed'] as $fixedPermission)
<div class="grid gap-x-1 rounded hover:bg-gray-50 py-2" style="grid-template-columns: 140px repeat({{ count($allVerbs) }}, 72px); align-items: start;">
<div class="text-xs font-medium text-gray-700 pl-1 truncate">
{{ __($fixedPermission) }}
</div>
@foreach ($allVerbs as $verb)
<div class="flex justify-center">
@if ($loop->last)
<label class="flex flex-col items-center gap-0.5 {{ $isSystem ? 'cursor-not-allowed' : 'cursor-pointer' }}">
<input
type="checkbox"
value="{{ $fixedPermission }}"
wire:model="{{ $model }}.permissions"
{{ $isSystem ? 'disabled' : '' }}
class="rounded border-gray-300 text-theme-brand focus:ring-theme-brand h-3.5 w-3.5 {{ $isSystem ? 'cursor-not-allowed opacity-60' : 'cursor-pointer' }}">
<span class="text-xs text-gray-500">{{ __($verb) }}</span>
</label>
@endif
</div>
@endforeach
</div>
@endforeach
@else
@php
$resource = $group['resource'];
$verbs = $group['verbs'];
$allPerms = array_map(fn($v) => $v . ' ' . $resource, $verbs);
$allPermsJs = json_encode($allPerms);
$manageKey = 'manage ' . $resource;
$rowLocked = $isSystem && empty($group['unlocked']);
@endphp
<div
class="grid gap-x-1 rounded hover:bg-gray-50 py-2"
style="grid-template-columns: 140px repeat({{ count($allVerbs) }}, 72px); align-items: start;"
@if (!$rowLocked)
x-data="{
toggleManage(checked, allPerms) {
let current = [...($wire.get('{{ $model }}.permissions') || [])];
allPerms.forEach(perm => {
if (checked) {
if (!current.includes(perm)) current.push(perm);
} else {
current = current.filter(p => p !== perm);
}
});
$wire.set('{{ $model }}.permissions', current);
},
uncheckManage(manageKey) {
let current = [...($wire.get('{{ $model }}.permissions') || [])];
current = current.filter(p => p !== manageKey);
$wire.set('{{ $model }}.permissions', current);
},
checkView(viewKey) {
let current = [...($wire.get('{{ $model }}.permissions') || [])];
if (!current.includes(viewKey)) {
current.push(viewKey);
$wire.set('{{ $model }}.permissions', current);
}
},
uncheckAll(allPerms) {
let current = [...($wire.get('{{ $model }}.permissions') || [])];
current = current.filter(p => !allPerms.includes(p));
$wire.set('{{ $model }}.permissions', current);
}
}"
@endif
>
<div class="text-xs font-medium text-gray-700 pl-1 truncate">
{{ __($group['label']) }}
</div>
@foreach ($allVerbs as $verb)
<div class="flex justify-center">
@if (in_array($verb, $verbs))
@if ($verb === 'manage')
<label class="flex flex-col items-center gap-0.5 {{ $rowLocked ? 'cursor-not-allowed' : 'cursor-pointer' }}">
<input
type="checkbox"
value="{{ $manageKey }}"
wire:model="{{ $model }}.permissions"
{{ $rowLocked ? 'disabled' : '' }}
@if (!$rowLocked)
x-on:change="toggleManage($event.target.checked, {{ $allPermsJs }}); {{ in_array('view', $verbs) ? "if (\$event.target.checked) checkView('view {$resource}')" : '' }}"
@endif
class="rounded border-gray-300 text-theme-brand focus:ring-theme-brand h-3.5 w-3.5 {{ $rowLocked ? 'cursor-not-allowed opacity-60' : 'cursor-pointer' }}">
<span class="text-xs text-gray-500">{{ __($verb) }}</span>
</label>
@elseif ($verb === 'view')
<label class="flex flex-col items-center gap-0.5 {{ $rowLocked ? 'cursor-not-allowed' : 'cursor-pointer' }}">
<input
type="checkbox"
value="view {{ $resource }}"
wire:model="{{ $model }}.permissions"
{{ $rowLocked ? 'disabled' : '' }}
@if (!$rowLocked)
x-on:change="if (!$event.target.checked) uncheckAll({{ $allPermsJs }})"
@endif
class="rounded border-gray-300 text-theme-brand focus:ring-theme-brand h-3.5 w-3.5 {{ $rowLocked ? 'cursor-not-allowed opacity-60' : 'cursor-pointer' }}">
<span class="text-xs text-gray-500">{{ __($verb) }}</span>
</label>
@else
<label class="flex flex-col items-center gap-0.5 {{ $rowLocked ? 'cursor-not-allowed' : 'cursor-pointer' }}">
<input
type="checkbox"
value="{{ $verb }} {{ $resource }}"
wire:model="{{ $model }}.permissions"
{{ $rowLocked ? 'disabled' : '' }}
@if (!$rowLocked)
x-on:change="if (!$event.target.checked) uncheckManage('{{ $manageKey }}'); if ($event.target.checked) checkView('view {{ $resource }}')"
@endif
class="rounded border-gray-300 text-theme-brand focus:ring-theme-brand h-3.5 w-3.5 {{ $rowLocked ? 'cursor-not-allowed opacity-60' : 'cursor-pointer' }}">
<span class="text-xs text-gray-500">{{ __($verb) }}</span>
</label>
@endif
@endif
</div>
@endforeach
</div>
@endif
@endforeach
</div>
</div>