OMNI Access
v1.3.0
Free
~20 min read
CRUD Example: Permissions Management
Copy-paste ready Permissions CRUD: controller, grouped-permission views, routes, and JavaScript helpers for the admin panel.
01
Step 1 of 8
Introduction
Complete Permission management system with group organization and role assignments.
02
Step 2 of 8
Controller: app/Http/Controllers/Admin/PermissionController.php
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use RbacSuite\OmniAccess\Models\Permission;
use RbacSuite\OmniAccess\Models\Group;
use RbacSuite\OmniAccess\Models\Role;
use RbacSuite\OmniAccess\Services\CacheService;
class PermissionController extends Controller
{
protected $cacheService;
public function __construct(CacheService $cacheService)
{
$this->cacheService = $cacheService;
// Apply middleware
$this->middleware('auth');
$this->middleware('permission:permissions.view')->only(['index', 'show']);
$this->middleware('permission:permissions.create')->only(['create', 'store']);
$this->middleware('permission:permissions.edit')->only(['edit', 'update']);
$this->middleware('permission:permissions.delete')->only('destroy');
}
/**
* Display a listing of permissions
*/
public function index(Request $request)
{
$query = Permission::with('group')->withCount('roles');
// Filter by group
if ($request->filled('group')) {
$query->where('group_id', $request->get('group'));
}
// Search functionality
if ($request->filled('search')) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
->orWhere('slug', 'like', "%{$search}%")
->orWhere('description', 'like', "%{$search}%");
});
}
// Sort functionality
$sortField = $request->get('sort', 'name');
$sortDirection = $request->get('direction', 'asc');
if (in_array($sortField, ['name', 'slug', 'created_at', 'roles_count'])) {
$query->orderBy($sortField, $sortDirection);
} else {
$query->leftJoin('permission_groups', 'permissions.group_id', '=', 'permission_groups.id')
->orderBy('permission_groups.sort_order')
->orderBy('permissions.name');
}
$permissions = $query->paginate(15)->withQueryString();
$groups = Group::orderBy('sort_order')->get();
return view('admin.permissions.index', compact('permissions', 'groups'));
}
/**
* Show the form for creating a new permission
*/
public function create()
{
$groups = Group::orderBy('sort_order')->get();
$roles = Role::orderBy('name')->get();
return view('admin.permissions.create', compact('groups', 'roles'));
}
/**
* Store a newly created permission
*/
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:50',
'slug' => 'required|string|max:50|unique:permissions,slug|regex:/^[a-z0-9\.\-\_]+$/',
'group_id' => 'nullable|exists:permission_groups,id',
'description' => 'nullable|string|max:255',
'roles' => 'nullable|array',
'roles.*' => 'exists:roles,id'
]);
// Create permission
$permission = Permission::create([
'name' => $validated['name'],
'slug' => $validated['slug'],
'group_id' => $validated['group_id'],
'description' => $validated['description']
]);
// Assign to roles
if (!empty($validated['roles'])) {
$permission->roles()->sync($validated['roles']);
}
// Clear cache
$this->cacheService->forgetPermission($permission->id);
if ($request->input('create_another')) {
return redirect()
->route('admin.permissions.create')
->with('success', 'Permission created successfully! You can add another.');
}
return redirect()
->route('admin.permissions.index')
->with('success', 'Permission created successfully!');
}
/**
* Display the specified permission
*/
public function show(Permission $permission)
{
$permission->load(['group', 'roles.users']);
return view('admin.permissions.show', compact('permission'));
}
/**
* Show the form for editing the specified permission
*/
public function edit(Permission $permission)
{
$groups = Group::orderBy('sort_order')->get();
$roles = Role::orderBy('name')->get();
$permissionRoles = $permission->roles->pluck('id')->toArray();
return view('admin.permissions.edit', compact('permission', 'groups', 'roles', 'permissionRoles'));
}
/**
* Update the specified permission
*/
public function update(Request $request, Permission $permission)
{
$validated = $request->validate([
'name' => 'required|string|max:50',
'slug' => 'required|string|max:50|unique:permissions,slug,' . $permission->id . '|regex:/^[a-z0-9\.\-\_]+$/',
'group_id' => 'nullable|exists:permission_groups,id',
'description' => 'nullable|string|max:255',
'roles' => 'nullable|array',
'roles.*' => 'exists:roles,id'
]);
// Update permission
$permission->update([
'name' => $validated['name'],
'slug' => $validated['slug'],
'group_id' => $validated['group_id'],
'description' => $validated['description']
]);
// Sync roles
$permission->roles()->sync($validated['roles'] ?? []);
// Clear cache
$this->cacheService->forgetPermission($permission->id);
if ($request->input('save_and_continue')) {
return redirect()
->route('admin.permissions.edit', $permission)
->with('success', 'Permission updated successfully!');
}
return redirect()
->route('admin.permissions.show', $permission)
->with('success', 'Permission updated successfully!');
}
/**
* Remove the specified permission
*/
public function destroy(Permission $permission)
{
// Check if permission has roles
if ($permission->roles()->count() > 0) {
return response()->json([
'success' => false,
'message' => 'Cannot delete permission that is assigned to roles!'
], 403);
}
$permission->delete();
// Clear cache
$this->cacheService->forgetPermission($permission->id);
if (request()->wantsJson()) {
return response()->json([
'success' => true,
'message' => 'Permission deleted successfully!'
]);
}
return redirect()
->route('admin.permissions.index')
->with('success', 'Permission deleted successfully!');
}
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use RbacSuite\OmniAccess\Models\Permission;
use RbacSuite\OmniAccess\Models\Group;
use RbacSuite\OmniAccess\Models\Role;
use RbacSuite\OmniAccess\Services\CacheService;
class PermissionController extends Controller
{
protected $cacheService;
public function __construct(CacheService $cacheService)
{
$this->cacheService = $cacheService;
// Apply middleware
$this->middleware('auth');
$this->middleware('permission:permissions.view')->only(['index', 'show']);
$this->middleware('permission:permissions.create')->only(['create', 'store']);
$this->middleware('permission:permissions.edit')->only(['edit', 'update']);
$this->middleware('permission:permissions.delete')->only('destroy');
}
/**
* Display a listing of permissions
*/
public function index(Request $request)
{
$query = Permission::with('group')->withCount('roles');
// Filter by group
if ($request->filled('group')) {
$query->where('group_id', $request->get('group'));
}
// Search functionality
if ($request->filled('search')) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
->orWhere('slug', 'like', "%{$search}%")
->orWhere('description', 'like', "%{$search}%");
});
}
// Sort functionality
$sortField = $request->get('sort', 'name');
$sortDirection = $request->get('direction', 'asc');
if (in_array($sortField, ['name', 'slug', 'created_at', 'roles_count'])) {
$query->orderBy($sortField, $sortDirection);
} else {
$query->leftJoin('permission_groups', 'permissions.group_id', '=', 'permission_groups.id')
->orderBy('permission_groups.sort_order')
->orderBy('permissions.name');
}
$permissions = $query->paginate(15)->withQueryString();
$groups = Group::orderBy('sort_order')->get();
return view('admin.permissions.index', compact('permissions', 'groups'));
}
/**
* Show the form for creating a new permission
*/
public function create()
{
$groups = Group::orderBy('sort_order')->get();
$roles = Role::orderBy('name')->get();
return view('admin.permissions.create', compact('groups', 'roles'));
}
/**
* Store a newly created permission
*/
public function store(Request $request)
{
$validated = $request->validate([
'name' => 'required|string|max:50',
'slug' => 'required|string|max:50|unique:permissions,slug|regex:/^[a-z0-9\.\-\_]+$/',
'group_id' => 'nullable|exists:permission_groups,id',
'description' => 'nullable|string|max:255',
'roles' => 'nullable|array',
'roles.*' => 'exists:roles,id'
]);
// Create permission
$permission = Permission::create([
'name' => $validated['name'],
'slug' => $validated['slug'],
'group_id' => $validated['group_id'],
'description' => $validated['description']
]);
// Assign to roles
if (!empty($validated['roles'])) {
$permission->roles()->sync($validated['roles']);
}
// Clear cache
$this->cacheService->forgetPermission($permission->id);
if ($request->input('create_another')) {
return redirect()
->route('admin.permissions.create')
->with('success', 'Permission created successfully! You can add another.');
}
return redirect()
->route('admin.permissions.index')
->with('success', 'Permission created successfully!');
}
/**
* Display the specified permission
*/
public function show(Permission $permission)
{
$permission->load(['group', 'roles.users']);
return view('admin.permissions.show', compact('permission'));
}
/**
* Show the form for editing the specified permission
*/
public function edit(Permission $permission)
{
$groups = Group::orderBy('sort_order')->get();
$roles = Role::orderBy('name')->get();
$permissionRoles = $permission->roles->pluck('id')->toArray();
return view('admin.permissions.edit', compact('permission', 'groups', 'roles', 'permissionRoles'));
}
/**
* Update the specified permission
*/
public function update(Request $request, Permission $permission)
{
$validated = $request->validate([
'name' => 'required|string|max:50',
'slug' => 'required|string|max:50|unique:permissions,slug,' . $permission->id . '|regex:/^[a-z0-9\.\-\_]+$/',
'group_id' => 'nullable|exists:permission_groups,id',
'description' => 'nullable|string|max:255',
'roles' => 'nullable|array',
'roles.*' => 'exists:roles,id'
]);
// Update permission
$permission->update([
'name' => $validated['name'],
'slug' => $validated['slug'],
'group_id' => $validated['group_id'],
'description' => $validated['description']
]);
// Sync roles
$permission->roles()->sync($validated['roles'] ?? []);
// Clear cache
$this->cacheService->forgetPermission($permission->id);
if ($request->input('save_and_continue')) {
return redirect()
->route('admin.permissions.edit', $permission)
->with('success', 'Permission updated successfully!');
}
return redirect()
->route('admin.permissions.show', $permission)
->with('success', 'Permission updated successfully!');
}
/**
* Remove the specified permission
*/
public function destroy(Permission $permission)
{
// Check if permission has roles
if ($permission->roles()->count() > 0) {
return response()->json([
'success' => false,
'message' => 'Cannot delete permission that is assigned to roles!'
], 403);
}
$permission->delete();
// Clear cache
$this->cacheService->forgetPermission($permission->id);
if (request()->wantsJson()) {
return response()->json([
'success' => true,
'message' => 'Permission deleted successfully!'
]);
}
return redirect()
->route('admin.permissions.index')
->with('success', 'Permission deleted successfully!');
}
03
Step 3 of 8
View: resources/views/admin/permissions/index.blade.php
@extends('layouts.admin')
@section('title', 'Permissions Management')
@section('content')
<div class="container-fluid">
<!-- Page Header -->
<div class="row mb-4">
<div class="col-12">
<div class="page-header d-flex justify-content-between align-items-center">
<div>
<h1 class="h3 mb-0 text-gray-800">Permissions Management</h1>
<p class="text-muted mb-0">Manage system permissions and assign them to roles</p>
</div>
<div>
@permission('permissions.create')
<a href="{{ route('admin.permissions.create') }}" class="btn btn-primary">
<i class="bi bi-plus-circle me-2"></i>Create New Permission
</a>
@endpermission
</div>
</div>
</div>
</div>
<!-- Statistics Cards -->
<div class="row mb-4">
<div class="col-xl-3 col-md-6 mb-3">
<div class="card border-left-primary shadow-sm h-100">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
Total Permissions
</div>
<div class="h5 mb-0 font-weight-bold">{{ \RbacSuite\OmniAccess\Models\Permission::count() }}</div>
</div>
<div class="col-auto">
<i class="bi bi-key fs-2 text-primary"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card border-left-success shadow-sm h-100">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
Permission Groups
</div>
<div class="h5 mb-0 font-weight-bold">{{ \RbacSuite\OmniAccess\Models\Group::count() }}</div>
</div>
<div class="col-auto">
<i class="bi bi-collection fs-2 text-success"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card border-left-info shadow-sm h-100">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">
Assigned to Roles
</div>
<div class="h5 mb-0 font-weight-bold">
{{ \RbacSuite\OmniAccess\Models\Permission::has('roles')->count() }}
</div>
</div>
<div class="col-auto">
<i class="bi bi-link-45deg fs-2 text-info"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card border-left-warning shadow-sm h-100">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
Unassigned
</div>
<div class="h5 mb-0 font-weight-bold">
{{ \RbacSuite\OmniAccess\Models\Permission::doesntHave('roles')->count() }}
</div>
</div>
<div class="col-auto">
<i class="bi bi-exclamation-circle fs-2 text-warning"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Alerts -->
@if(session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
<i class="bi bi-check-circle me-2"></i>{{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
<!-- Main Card -->
<div class="card shadow-sm">
<div class="card-header bg-white py-3">
<div class="row align-items-center">
<div class="col-md-4">
<form action="{{ route('admin.permissions.index') }}" method="GET" class="d-flex">
<div class="input-group">
<input type="text"
name="search"
class="form-control"
placeholder="Search permissions..."
value="{{ request('search') }}">
<button class="btn btn-outline-secondary" type="submit">
<i class="bi bi-search"></i>
</button>
@if(request('search') || request('group'))
<a href="{{ route('admin.permissions.index') }}" class="btn btn-outline-secondary">
<i class="bi bi-x-lg"></i>
</a>
@endif
</div>
</form>
</div>
<div class="col-md-3">
<form action="{{ route('admin.permissions.index') }}" method="GET">
<select name="group" class="form-select" onchange="this.form.submit()">
<option value="">All Groups</option>
@foreach($groups as $group)
<option value="{{ $group->id }}" {{ request('group') == $group->id ? 'selected' : '' }}>
{{ $group->name }}
</option>
@endforeach
<option value="0" {{ request('group') === '0' ? 'selected' : '' }}>Ungrouped</option>
</select>
@if(request('search'))
<input type="hidden" name="search" value="{{ request('search') }}">
@endif
</form>
</div>
<div class="col-md-5 text-end">
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-secondary" onclick="toggleBulkSelect()">
<i class="bi bi-check-square me-1"></i>Select
</button>
<button type="button" class="btn btn-outline-danger d-none" id="bulkDeleteBtn" onclick="bulkDeletePermissions()">
<i class="bi bi-trash me-1"></i>Delete Selected
</button>
</div>
</div>
</div>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th class="bulk-select-column d-none" style="width: 40px;">
<input type="checkbox" class="form-check-input" id="selectAll">
</th>
<th>Permission</th>
<th>Slug</th>
<th>Group</th>
<th>Description</th>
<th class="text-center">Roles</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
@forelse($permissions as $permission)
<tr>
<td class="bulk-select-column d-none">
@if($permission->roles_count == 0)
<input type="checkbox" class="form-check-input permission-checkbox" value="{{ $permission->id }}">
@endif
</td>
<td>
<div class="d-flex align-items-center">
<div class="avatar-sm bg-info bg-opacity-10 rounded-circle me-2">
<i class="bi bi-key text-info"></i>
</div>
<div>
<div class="fw-semibold">{{ $permission->name }}</div>
@if($permission->deleted_at)
<span class="badge bg-danger">Deleted</span>
@endif
</div>
</div>
</td>
<td>
<code class="text-primary">{{ $permission->slug }}</code>
</td>
<td>
@if($permission->group)
<span class="badge bg-secondary">{{ $permission->group->name }}</span>
@else
<span class="text-muted">-</span>
@endif
</td>
<td>
<span class="text-muted small">{{ Str::limit($permission->description, 50) ?: '-' }}</span>
</td>
<td class="text-center">
@if($permission->roles_count > 0)
<span class="badge bg-success">{{ $permission->roles_count }}</span>
@else
<span class="badge bg-warning">0</span>
@endif
</td>
<td class="text-end">
<div class="btn-group" role="group">
<a href="{{ route('admin.permissions.show', $permission) }}"
class="btn btn-sm btn-outline-info"
title="View">
<i class="bi bi-eye"></i>
</a>
@permission('permissions.edit')
<a href="{{ route('admin.permissions.edit', $permission) }}"
class="btn btn-sm btn-outline-primary"
title="Edit">
<i class="bi bi-pencil"></i>
</a>
@endpermission
@permission('permissions.create')
<button type="button"
class="btn btn-sm btn-outline-secondary"
onclick="clonePermission({{ $permission->id }})"
title="Clone">
<i class="bi bi-files"></i>
</button>
@endpermission
@permission('permissions.delete')
@if($permission->roles_count == 0)
<button type="button"
class="btn btn-sm btn-outline-danger"
onclick="deletePermission({{ $permission->id }}, '{{ $permission->name }}')"
title="Delete">
<i class="bi bi-trash"></i>
</button>
@endif
@endpermission
</div>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="text-center py-4">
<div class="text-muted">
<i class="bi bi-inbox fs-1"></i>
<p class="mt-2">No permissions found</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
@if($permissions->hasPages())
<div class="card-footer bg-white">
<div class="d-flex justify-content-between align-items-center">
<div class="text-muted">
Showing {{ $permissions->firstItem() }} to {{ $permissions->lastItem() }} of {{ $permissions->total() }} results
</div>
<div>
{{ $permissions->links('pagination::bootstrap-5') }}
</div>
</div>
</div>
@endif
</div>
</div>
@endsection
@extends('layouts.admin')
@section('title', 'Permissions Management')
@section('content')
<div class="container-fluid">
<!-- Page Header -->
<div class="row mb-4">
<div class="col-12">
<div class="page-header d-flex justify-content-between align-items-center">
<div>
<h1 class="h3 mb-0 text-gray-800">Permissions Management</h1>
<p class="text-muted mb-0">Manage system permissions and assign them to roles</p>
</div>
<div>
@permission('permissions.create')
<a href="{{ route('admin.permissions.create') }}" class="btn btn-primary">
<i class="bi bi-plus-circle me-2"></i>Create New Permission
</a>
@endpermission
</div>
</div>
</div>
</div>
<!-- Statistics Cards -->
<div class="row mb-4">
<div class="col-xl-3 col-md-6 mb-3">
<div class="card border-left-primary shadow-sm h-100">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-primary text-uppercase mb-1">
Total Permissions
</div>
<div class="h5 mb-0 font-weight-bold">{{ \RbacSuite\OmniAccess\Models\Permission::count() }}</div>
</div>
<div class="col-auto">
<i class="bi bi-key fs-2 text-primary"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card border-left-success shadow-sm h-100">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
Permission Groups
</div>
<div class="h5 mb-0 font-weight-bold">{{ \RbacSuite\OmniAccess\Models\Group::count() }}</div>
</div>
<div class="col-auto">
<i class="bi bi-collection fs-2 text-success"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card border-left-info shadow-sm h-100">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">
Assigned to Roles
</div>
<div class="h5 mb-0 font-weight-bold">
{{ \RbacSuite\OmniAccess\Models\Permission::has('roles')->count() }}
</div>
</div>
<div class="col-auto">
<i class="bi bi-link-45deg fs-2 text-info"></i>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-3">
<div class="card border-left-warning shadow-sm h-100">
<div class="card-body">
<div class="row no-gutters align-items-center">
<div class="col mr-2">
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
Unassigned
</div>
<div class="h5 mb-0 font-weight-bold">
{{ \RbacSuite\OmniAccess\Models\Permission::doesntHave('roles')->count() }}
</div>
</div>
<div class="col-auto">
<i class="bi bi-exclamation-circle fs-2 text-warning"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Alerts -->
@if(session('success'))
<div class="alert alert-success alert-dismissible fade show" role="alert">
<i class="bi bi-check-circle me-2"></i>{{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
<!-- Main Card -->
<div class="card shadow-sm">
<div class="card-header bg-white py-3">
<div class="row align-items-center">
<div class="col-md-4">
<form action="{{ route('admin.permissions.index') }}" method="GET" class="d-flex">
<div class="input-group">
<input type="text"
name="search"
class="form-control"
placeholder="Search permissions..."
value="{{ request('search') }}">
<button class="btn btn-outline-secondary" type="submit">
<i class="bi bi-search"></i>
</button>
@if(request('search') || request('group'))
<a href="{{ route('admin.permissions.index') }}" class="btn btn-outline-secondary">
<i class="bi bi-x-lg"></i>
</a>
@endif
</div>
</form>
</div>
<div class="col-md-3">
<form action="{{ route('admin.permissions.index') }}" method="GET">
<select name="group" class="form-select" onchange="this.form.submit()">
<option value="">All Groups</option>
@foreach($groups as $group)
<option value="{{ $group->id }}" {{ request('group') == $group->id ? 'selected' : '' }}>
{{ $group->name }}
</option>
@endforeach
<option value="0" {{ request('group') === '0' ? 'selected' : '' }}>Ungrouped</option>
</select>
@if(request('search'))
<input type="hidden" name="search" value="{{ request('search') }}">
@endif
</form>
</div>
<div class="col-md-5 text-end">
<div class="btn-group" role="group">
<button type="button" class="btn btn-outline-secondary" onclick="toggleBulkSelect()">
<i class="bi bi-check-square me-1"></i>Select
</button>
<button type="button" class="btn btn-outline-danger d-none" id="bulkDeleteBtn" onclick="bulkDeletePermissions()">
<i class="bi bi-trash me-1"></i>Delete Selected
</button>
</div>
</div>
</div>
</div>
<div class="card-body p-0">
<div class="table-responsive">
<table class="table table-hover mb-0">
<thead class="table-light">
<tr>
<th class="bulk-select-column d-none" style="width: 40px;">
<input type="checkbox" class="form-check-input" id="selectAll">
</th>
<th>Permission</th>
<th>Slug</th>
<th>Group</th>
<th>Description</th>
<th class="text-center">Roles</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
@forelse($permissions as $permission)
<tr>
<td class="bulk-select-column d-none">
@if($permission->roles_count == 0)
<input type="checkbox" class="form-check-input permission-checkbox" value="{{ $permission->id }}">
@endif
</td>
<td>
<div class="d-flex align-items-center">
<div class="avatar-sm bg-info bg-opacity-10 rounded-circle me-2">
<i class="bi bi-key text-info"></i>
</div>
<div>
<div class="fw-semibold">{{ $permission->name }}</div>
@if($permission->deleted_at)
<span class="badge bg-danger">Deleted</span>
@endif
</div>
</div>
</td>
<td>
<code class="text-primary">{{ $permission->slug }}</code>
</td>
<td>
@if($permission->group)
<span class="badge bg-secondary">{{ $permission->group->name }}</span>
@else
<span class="text-muted">-</span>
@endif
</td>
<td>
<span class="text-muted small">{{ Str::limit($permission->description, 50) ?: '-' }}</span>
</td>
<td class="text-center">
@if($permission->roles_count > 0)
<span class="badge bg-success">{{ $permission->roles_count }}</span>
@else
<span class="badge bg-warning">0</span>
@endif
</td>
<td class="text-end">
<div class="btn-group" role="group">
<a href="{{ route('admin.permissions.show', $permission) }}"
class="btn btn-sm btn-outline-info"
title="View">
<i class="bi bi-eye"></i>
</a>
@permission('permissions.edit')
<a href="{{ route('admin.permissions.edit', $permission) }}"
class="btn btn-sm btn-outline-primary"
title="Edit">
<i class="bi bi-pencil"></i>
</a>
@endpermission
@permission('permissions.create')
<button type="button"
class="btn btn-sm btn-outline-secondary"
onclick="clonePermission({{ $permission->id }})"
title="Clone">
<i class="bi bi-files"></i>
</button>
@endpermission
@permission('permissions.delete')
@if($permission->roles_count == 0)
<button type="button"
class="btn btn-sm btn-outline-danger"
onclick="deletePermission({{ $permission->id }}, '{{ $permission->name }}')"
title="Delete">
<i class="bi bi-trash"></i>
</button>
@endif
@endpermission
</div>
</td>
</tr>
@empty
<tr>
<td colspan="7" class="text-center py-4">
<div class="text-muted">
<i class="bi bi-inbox fs-1"></i>
<p class="mt-2">No permissions found</p>
</div>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
@if($permissions->hasPages())
<div class="card-footer bg-white">
<div class="d-flex justify-content-between align-items-center">
<div class="text-muted">
Showing {{ $permissions->firstItem() }} to {{ $permissions->lastItem() }} of {{ $permissions->total() }} results
</div>
<div>
{{ $permissions->links('pagination::bootstrap-5') }}
</div>
</div>
</div>
@endif
</div>
</div>
@endsection
04
Step 4 of 8
View: resources/views/admin/permissions/create.blade.php
@extends('layouts.admin')
@section('title', 'Create Permission')
@section('content')
<div class="container-fluid">
<!-- Page Header -->
<div class="row mb-4">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{{ route('admin.permissions.index') }}">Permissions</a></li>
<li class="breadcrumb-item active">Create Permission</li>
</ol>
</nav>
<h1 class="h3 mb-0 text-gray-800">Create New Permission</h1>
</div>
</div>
<form action="{{ route('admin.permissions.store') }}" method="POST" id="createPermissionForm">
@csrf
<div class="row">
<!-- Permission Information -->
<div class="col-lg-8">
<div class="card shadow-sm mb-4">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Permission Information</h5>
</div>
<div class="card-body">
<div class="mb-3">
<label for="name" class="form-label">Permission Name <span class="text-danger">*</span></label>
<input type="text"
class="form-control @error('name') is-invalid @enderror"
id="name"
name="name"
value="{{ old('name') }}"
placeholder="e.g., Edit Posts"
required>
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
<small class="form-text text-muted">Human-readable name for the permission</small>
</div>
<div class="mb-3">
<label for="slug" class="form-label">Slug <span class="text-danger">*</span></label>
<input type="text"
class="form-control @error('slug') is-invalid @enderror"
id="slug"
name="slug"
value="{{ old('slug') }}"
placeholder="e.g., posts.edit"
pattern="[a-z0-9\.\-\_]+"
required>
@error('slug')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
<small class="form-text text-muted">Unique identifier using dots for namespace (e.g., posts.edit, users.delete)</small>
</div>
<div class="mb-3">
<label for="group_id" class="form-label">Permission Group</label>
<select class="form-select @error('group_id') is-invalid @enderror"
id="group_id"
name="group_id">
<option value="">No Group</option>
@foreach($groups as $group)
<option value="{{ $group->id }}" {{ old('group_id') == $group->id ? 'selected' : '' }}>
{{ $group->name }}
</option>
@endforeach
</select>
@error('group_id')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
<small class="form-text text-muted">Organize permissions into logical groups</small>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control @error('description') is-invalid @enderror"
id="description"
name="description"
rows="3"
placeholder="What does this permission allow?">{{ old('description') }}</textarea>
@error('description')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
</div>
<!-- Assign to Roles -->
<div class="card shadow-sm">
<div class="card-header bg-white d-flex justify-content-between align-items-center">
<h5 class="mb-0"><i class="bi bi-person-badge me-2"></i>Assign to Roles</h5>
<div>
<button type="button" class="btn btn-sm btn-outline-primary" onclick="selectAllRoles()">
Select All
</button>
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="selectNoRoles()">
Clear All
</button>
</div>
</div>
<div class="card-body">
<div class="row">
@forelse($roles as $role)
<div class="col-md-6 col-lg-4 mb-3">
<div class="form-check">
<input class="form-check-input role-checkbox"
type="checkbox"
name="roles[]"
value="{{ $role->id }}"
id="role_{{ $role->id }}"
{{ in_array($role->id, old('roles', [])) ? 'checked' : '' }}>
<label class="form-check-label" for="role_{{ $role->id }}">
<strong>{{ $role->name }}</strong>
@if($role->slug === config('omni-access.super_admin_role'))
<span class="badge bg-danger ms-1">Super Admin</span>
@endif
@if($role->is_default)
<span class="badge bg-info ms-1">Default</span>
@endif
<br>
<small class="text-muted">{{ $role->description ?: 'No description' }}</small>
</label>
</div>
</div>
@empty
<div class="col-12 text-center text-muted">
No roles available
</div>
@endforelse
</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- Quick Actions -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-lightning me-2"></i>Quick Actions</h5>
</div>
<div class="card-body">
<button type="submit" class="btn btn-primary w-100 mb-2">
<i class="bi bi-check-circle me-2"></i>Create Permission
</button>
<button type="submit" name="create_another" value="1" class="btn btn-outline-primary w-100 mb-2">
<i class="bi bi-plus-circle me-2"></i>Create & Add Another
</button>
<a href="{{ route('admin.permissions.index') }}" class="btn btn-outline-secondary w-100">
<i class="bi bi-x-circle me-2"></i>Cancel
</a>
</div>
</div>
<!-- Common Permissions -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-star me-2"></i>Common Permissions</h5>
</div>
<div class="card-body">
<p class="small text-muted mb-3">Click to use these common permission patterns:</p>
<div class="d-grid gap-2">
<button type="button" class="btn btn-sm btn-outline-secondary text-start" onclick="fillPermission('View', 'view')">
<i class="bi bi-eye me-2"></i>View
</button>
<button type="button" class="btn btn-sm btn-outline-secondary text-start" onclick="fillPermission('Create', 'create')">
<i class="bi bi-plus-circle me-2"></i>Create
</button>
<button type="button" class="btn btn-sm btn-outline-secondary text-start" onclick="fillPermission('Edit', 'edit')">
<i class="bi bi-pencil me-2"></i>Edit
</button>
<button type="button" class="btn btn-sm btn-outline-secondary text-start" onclick="fillPermission('Delete', 'delete')">
<i class="bi bi-trash me-2"></i>Delete
</button>
<button type="button" class="btn btn-sm btn-outline-secondary text-start" onclick="fillPermission('Publish', 'publish')">
<i class="bi bi-send me-2"></i>Publish
</button>
<button type="button" class="btn btn-sm btn-outline-secondary text-start" onclick="fillPermission('Export', 'export')">
<i class="bi bi-download me-2"></i>Export
</button>
</div>
</div>
</div>
<!-- Help -->
<div class="card shadow-sm">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-question-circle me-2"></i>Help</h5>
</div>
<div class="card-body">
<p class="small mb-2"><strong>Naming Convention:</strong></p>
<ul class="small text-muted ps-3">
<li>Use dots to namespace: <code>posts.edit</code></li>
<li>Keep slugs lowercase</li>
<li>Be descriptive but concise</li>
<li>Group related permissions</li>
</ul>
</div>
</div>
</div>
</div>
</form>
</div>
@endsection
@extends('layouts.admin')
@section('title', 'Create Permission')
@section('content')
<div class="container-fluid">
<!-- Page Header -->
<div class="row mb-4">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{{ route('admin.permissions.index') }}">Permissions</a></li>
<li class="breadcrumb-item active">Create Permission</li>
</ol>
</nav>
<h1 class="h3 mb-0 text-gray-800">Create New Permission</h1>
</div>
</div>
<form action="{{ route('admin.permissions.store') }}" method="POST" id="createPermissionForm">
@csrf
<div class="row">
<!-- Permission Information -->
<div class="col-lg-8">
<div class="card shadow-sm mb-4">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Permission Information</h5>
</div>
<div class="card-body">
<div class="mb-3">
<label for="name" class="form-label">Permission Name <span class="text-danger">*</span></label>
<input type="text"
class="form-control @error('name') is-invalid @enderror"
id="name"
name="name"
value="{{ old('name') }}"
placeholder="e.g., Edit Posts"
required>
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
<small class="form-text text-muted">Human-readable name for the permission</small>
</div>
<div class="mb-3">
<label for="slug" class="form-label">Slug <span class="text-danger">*</span></label>
<input type="text"
class="form-control @error('slug') is-invalid @enderror"
id="slug"
name="slug"
value="{{ old('slug') }}"
placeholder="e.g., posts.edit"
pattern="[a-z0-9\.\-\_]+"
required>
@error('slug')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
<small class="form-text text-muted">Unique identifier using dots for namespace (e.g., posts.edit, users.delete)</small>
</div>
<div class="mb-3">
<label for="group_id" class="form-label">Permission Group</label>
<select class="form-select @error('group_id') is-invalid @enderror"
id="group_id"
name="group_id">
<option value="">No Group</option>
@foreach($groups as $group)
<option value="{{ $group->id }}" {{ old('group_id') == $group->id ? 'selected' : '' }}>
{{ $group->name }}
</option>
@endforeach
</select>
@error('group_id')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
<small class="form-text text-muted">Organize permissions into logical groups</small>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control @error('description') is-invalid @enderror"
id="description"
name="description"
rows="3"
placeholder="What does this permission allow?">{{ old('description') }}</textarea>
@error('description')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
</div>
<!-- Assign to Roles -->
<div class="card shadow-sm">
<div class="card-header bg-white d-flex justify-content-between align-items-center">
<h5 class="mb-0"><i class="bi bi-person-badge me-2"></i>Assign to Roles</h5>
<div>
<button type="button" class="btn btn-sm btn-outline-primary" onclick="selectAllRoles()">
Select All
</button>
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="selectNoRoles()">
Clear All
</button>
</div>
</div>
<div class="card-body">
<div class="row">
@forelse($roles as $role)
<div class="col-md-6 col-lg-4 mb-3">
<div class="form-check">
<input class="form-check-input role-checkbox"
type="checkbox"
name="roles[]"
value="{{ $role->id }}"
id="role_{{ $role->id }}"
{{ in_array($role->id, old('roles', [])) ? 'checked' : '' }}>
<label class="form-check-label" for="role_{{ $role->id }}">
<strong>{{ $role->name }}</strong>
@if($role->slug === config('omni-access.super_admin_role'))
<span class="badge bg-danger ms-1">Super Admin</span>
@endif
@if($role->is_default)
<span class="badge bg-info ms-1">Default</span>
@endif
<br>
<small class="text-muted">{{ $role->description ?: 'No description' }}</small>
</label>
</div>
</div>
@empty
<div class="col-12 text-center text-muted">
No roles available
</div>
@endforelse
</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- Quick Actions -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-lightning me-2"></i>Quick Actions</h5>
</div>
<div class="card-body">
<button type="submit" class="btn btn-primary w-100 mb-2">
<i class="bi bi-check-circle me-2"></i>Create Permission
</button>
<button type="submit" name="create_another" value="1" class="btn btn-outline-primary w-100 mb-2">
<i class="bi bi-plus-circle me-2"></i>Create & Add Another
</button>
<a href="{{ route('admin.permissions.index') }}" class="btn btn-outline-secondary w-100">
<i class="bi bi-x-circle me-2"></i>Cancel
</a>
</div>
</div>
<!-- Common Permissions -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-star me-2"></i>Common Permissions</h5>
</div>
<div class="card-body">
<p class="small text-muted mb-3">Click to use these common permission patterns:</p>
<div class="d-grid gap-2">
<button type="button" class="btn btn-sm btn-outline-secondary text-start" onclick="fillPermission('View', 'view')">
<i class="bi bi-eye me-2"></i>View
</button>
<button type="button" class="btn btn-sm btn-outline-secondary text-start" onclick="fillPermission('Create', 'create')">
<i class="bi bi-plus-circle me-2"></i>Create
</button>
<button type="button" class="btn btn-sm btn-outline-secondary text-start" onclick="fillPermission('Edit', 'edit')">
<i class="bi bi-pencil me-2"></i>Edit
</button>
<button type="button" class="btn btn-sm btn-outline-secondary text-start" onclick="fillPermission('Delete', 'delete')">
<i class="bi bi-trash me-2"></i>Delete
</button>
<button type="button" class="btn btn-sm btn-outline-secondary text-start" onclick="fillPermission('Publish', 'publish')">
<i class="bi bi-send me-2"></i>Publish
</button>
<button type="button" class="btn btn-sm btn-outline-secondary text-start" onclick="fillPermission('Export', 'export')">
<i class="bi bi-download me-2"></i>Export
</button>
</div>
</div>
</div>
<!-- Help -->
<div class="card shadow-sm">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-question-circle me-2"></i>Help</h5>
</div>
<div class="card-body">
<p class="small mb-2"><strong>Naming Convention:</strong></p>
<ul class="small text-muted ps-3">
<li>Use dots to namespace: <code>posts.edit</code></li>
<li>Keep slugs lowercase</li>
<li>Be descriptive but concise</li>
<li>Group related permissions</li>
</ul>
</div>
</div>
</div>
</div>
</form>
</div>
@endsection
05
Step 5 of 8
View: resources/views/admin/permissions/edit.blade.php
@extends('layouts.admin')
@section('title', 'Edit Permission - ' . $permission->name)
@section('content')
<div class="container-fluid">
<!-- Page Header -->
<div class="row mb-4">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{{ route('admin.permissions.index') }}">Permissions</a></li>
<li class="breadcrumb-item active">Edit Permission</li>
</ol>
</nav>
<div class="d-flex justify-content-between align-items-center">
<h1 class="h3 mb-0 text-gray-800">Edit Permission: {{ $permission->name }}</h1>
<a href="{{ route('admin.permissions.show', $permission) }}" class="btn btn-outline-info">
<i class="bi bi-eye me-2"></i>View Permission
</a>
</div>
</div>
</div>
<form action="{{ route('admin.permissions.update', $permission) }}" method="POST">
@csrf
@method('PUT')
<div class="row">
<!-- Permission Information -->
<div class="col-lg-8">
<div class="card shadow-sm mb-4">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Permission Information</h5>
</div>
<div class="card-body">
<div class="mb-3">
<label for="name" class="form-label">Permission Name <span class="text-danger">*</span></label>
<input type="text"
class="form-control @error('name') is-invalid @enderror"
id="name"
name="name"
value="{{ old('name', $permission->name) }}"
required>
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="slug" class="form-label">Slug <span class="text-danger">*</span></label>
<input type="text"
class="form-control @error('slug') is-invalid @enderror"
id="slug"
name="slug"
value="{{ old('slug', $permission->slug) }}"
pattern="[a-z0-9\.\-\_]+"
required>
@error('slug')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
<small class="form-text text-muted">⚠️ Changing the slug may affect existing code references</small>
</div>
<div class="mb-3">
<label for="group_id" class="form-label">Permission Group</label>
<select class="form-select @error('group_id') is-invalid @enderror"
id="group_id"
name="group_id">
<option value="">No Group</option>
@foreach($groups as $group)
<option value="{{ $group->id }}"
{{ old('group_id', $permission->group_id) == $group->id ? 'selected' : '' }}>
{{ $group->name }}
</option>
@endforeach
</select>
@error('group_id')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control @error('description') is-invalid @enderror"
id="description"
name="description"
rows="3">{{ old('description', $permission->description) }}</textarea>
@error('description')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
</div>
<!-- Assign to Roles -->
<div class="card shadow-sm">
<div class="card-header bg-white d-flex justify-content-between align-items-center">
<h5 class="mb-0"><i class="bi bi-person-badge me-2"></i>Assigned to Roles</h5>
<div>
<span class="badge bg-primary me-2">
<span id="selectedCount">{{ count($permissionRoles) }}</span> selected
</span>
<button type="button" class="btn btn-sm btn-outline-primary" onclick="selectAllRoles()">
Select All
</button>
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="selectNoRoles()">
Clear All
</button>
</div>
</div>
<div class="card-body">
<div class="row">
@forelse($roles as $role)
<div class="col-md-6 col-lg-4 mb-3">
<div class="form-check">
<input class="form-check-input role-checkbox"
type="checkbox"
name="roles[]"
value="{{ $role->id }}"
id="role_{{ $role->id }}"
{{ in_array($role->id, old('roles', $permissionRoles)) ? 'checked' : '' }}
onchange="updateRoleCount()">
<label class="form-check-label" for="role_{{ $role->id }}">
<strong>{{ $role->name }}</strong>
@if($role->slug === config('omni-access.super_admin_role'))
<span class="badge bg-danger ms-1">Super Admin</span>
@endif
@if($role->is_default)
<span class="badge bg-info ms-1">Default</span>
@endif
<br>
<small class="text-muted">
{{ $role->users()->count() }} users
</small>
</label>
</div>
</div>
@empty
<div class="col-12 text-center text-muted">
No roles available
</div>
@endforelse
</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- Actions -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-lightning me-2"></i>Actions</h5>
</div>
<div class="card-body">
<button type="submit" class="btn btn-primary w-100 mb-2">
<i class="bi bi-save me-2"></i>Save Changes
</button>
<button type="submit" name="save_and_continue" value="1" class="btn btn-outline-primary w-100 mb-2">
<i class="bi bi-save me-2"></i>Save & Continue Editing
</button>
<a href="{{ route('admin.permissions.index') }}" class="btn btn-outline-secondary w-100">
<i class="bi bi-x-circle me-2"></i>Cancel
</a>
</div>
</div>
<!-- Permission Details -->
<div class="card shadow-sm">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Permission Details</h5>
</div>
<div class="card-body">
<dl class="row mb-0">
<dt class="col-5">Created:</dt>
<dd class="col-7">{{ $permission->created_at->format('M d, Y') }}</dd>
<dt class="col-5">Updated:</dt>
<dd class="col-7">{{ $permission->updated_at->format('M d, Y') }}</dd>
<dt class="col-5">Roles:</dt>
<dd class="col-7">
<span class="badge bg-success">{{ $permission->roles()->count() }}</span>
</dd>
</dl>
</div>
</div>
</div>
</div>
</form>
</div>
@endsection
@extends('layouts.admin')
@section('title', 'Edit Permission - ' . $permission->name)
@section('content')
<div class="container-fluid">
<!-- Page Header -->
<div class="row mb-4">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{{ route('admin.permissions.index') }}">Permissions</a></li>
<li class="breadcrumb-item active">Edit Permission</li>
</ol>
</nav>
<div class="d-flex justify-content-between align-items-center">
<h1 class="h3 mb-0 text-gray-800">Edit Permission: {{ $permission->name }}</h1>
<a href="{{ route('admin.permissions.show', $permission) }}" class="btn btn-outline-info">
<i class="bi bi-eye me-2"></i>View Permission
</a>
</div>
</div>
</div>
<form action="{{ route('admin.permissions.update', $permission) }}" method="POST">
@csrf
@method('PUT')
<div class="row">
<!-- Permission Information -->
<div class="col-lg-8">
<div class="card shadow-sm mb-4">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Permission Information</h5>
</div>
<div class="card-body">
<div class="mb-3">
<label for="name" class="form-label">Permission Name <span class="text-danger">*</span></label>
<input type="text"
class="form-control @error('name') is-invalid @enderror"
id="name"
name="name"
value="{{ old('name', $permission->name) }}"
required>
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="slug" class="form-label">Slug <span class="text-danger">*</span></label>
<input type="text"
class="form-control @error('slug') is-invalid @enderror"
id="slug"
name="slug"
value="{{ old('slug', $permission->slug) }}"
pattern="[a-z0-9\.\-\_]+"
required>
@error('slug')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
<small class="form-text text-muted">⚠️ Changing the slug may affect existing code references</small>
</div>
<div class="mb-3">
<label for="group_id" class="form-label">Permission Group</label>
<select class="form-select @error('group_id') is-invalid @enderror"
id="group_id"
name="group_id">
<option value="">No Group</option>
@foreach($groups as $group)
<option value="{{ $group->id }}"
{{ old('group_id', $permission->group_id) == $group->id ? 'selected' : '' }}>
{{ $group->name }}
</option>
@endforeach
</select>
@error('group_id')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<textarea class="form-control @error('description') is-invalid @enderror"
id="description"
name="description"
rows="3">{{ old('description', $permission->description) }}</textarea>
@error('description')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
</div>
</div>
<!-- Assign to Roles -->
<div class="card shadow-sm">
<div class="card-header bg-white d-flex justify-content-between align-items-center">
<h5 class="mb-0"><i class="bi bi-person-badge me-2"></i>Assigned to Roles</h5>
<div>
<span class="badge bg-primary me-2">
<span id="selectedCount">{{ count($permissionRoles) }}</span> selected
</span>
<button type="button" class="btn btn-sm btn-outline-primary" onclick="selectAllRoles()">
Select All
</button>
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="selectNoRoles()">
Clear All
</button>
</div>
</div>
<div class="card-body">
<div class="row">
@forelse($roles as $role)
<div class="col-md-6 col-lg-4 mb-3">
<div class="form-check">
<input class="form-check-input role-checkbox"
type="checkbox"
name="roles[]"
value="{{ $role->id }}"
id="role_{{ $role->id }}"
{{ in_array($role->id, old('roles', $permissionRoles)) ? 'checked' : '' }}
onchange="updateRoleCount()">
<label class="form-check-label" for="role_{{ $role->id }}">
<strong>{{ $role->name }}</strong>
@if($role->slug === config('omni-access.super_admin_role'))
<span class="badge bg-danger ms-1">Super Admin</span>
@endif
@if($role->is_default)
<span class="badge bg-info ms-1">Default</span>
@endif
<br>
<small class="text-muted">
{{ $role->users()->count() }} users
</small>
</label>
</div>
</div>
@empty
<div class="col-12 text-center text-muted">
No roles available
</div>
@endforelse
</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="col-lg-4">
<!-- Actions -->
<div class="card shadow-sm mb-4">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-lightning me-2"></i>Actions</h5>
</div>
<div class="card-body">
<button type="submit" class="btn btn-primary w-100 mb-2">
<i class="bi bi-save me-2"></i>Save Changes
</button>
<button type="submit" name="save_and_continue" value="1" class="btn btn-outline-primary w-100 mb-2">
<i class="bi bi-save me-2"></i>Save & Continue Editing
</button>
<a href="{{ route('admin.permissions.index') }}" class="btn btn-outline-secondary w-100">
<i class="bi bi-x-circle me-2"></i>Cancel
</a>
</div>
</div>
<!-- Permission Details -->
<div class="card shadow-sm">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Permission Details</h5>
</div>
<div class="card-body">
<dl class="row mb-0">
<dt class="col-5">Created:</dt>
<dd class="col-7">{{ $permission->created_at->format('M d, Y') }}</dd>
<dt class="col-5">Updated:</dt>
<dd class="col-7">{{ $permission->updated_at->format('M d, Y') }}</dd>
<dt class="col-5">Roles:</dt>
<dd class="col-7">
<span class="badge bg-success">{{ $permission->roles()->count() }}</span>
</dd>
</dl>
</div>
</div>
</div>
</div>
</form>
</div>
@endsection
06
Step 6 of 8
View: resources/views/admin/permissions/show.blade.php
@extends('layouts.admin')
@section('title', 'Permission Details - ' . $permission->name)
@section('content')
<div class="container-fluid">
<!-- Page Header -->
<div class="row mb-4">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{{ route('admin.permissions.index') }}">Permissions</a></li>
<li class="breadcrumb-item active">{{ $permission->name }}</li>
</ol>
</nav>
<div class="d-flex justify-content-between align-items-center">
<div>
<h1 class="h3 mb-2 text-gray-800">{{ $permission->name }}</h1>
<code class="fs-6 text-primary">{{ $permission->slug }}</code>
</div>
<div>
@permission('permissions.edit')
<a href="{{ route('admin.permissions.edit', $permission) }}" class="btn btn-primary">
<i class="bi bi-pencil me-2"></i>Edit Permission
</a>
@endpermission
</div>
</div>
</div>
</div>
<div class="row">
<!-- Permission Information -->
<div class="col-lg-4 mb-4">
<div class="card shadow-sm">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Permission Information</h5>
</div>
<div class="card-body">
<dl class="row">
<dt class="col-sm-4">Name:</dt>
<dd class="col-sm-8">{{ $permission->name }}</dd>
<dt class="col-sm-4">Slug:</dt>
<dd class="col-sm-8"><code>{{ $permission->slug }}</code></dd>
<dt class="col-sm-4">Group:</dt>
<dd class="col-sm-8">
@if($permission->group)
<span class="badge bg-secondary">{{ $permission->group->name }}</span>
@else
<span class="text-muted">No group</span>
@endif
</dd>
<dt class="col-sm-4">Description:</dt>
<dd class="col-sm-8">{{ $permission->description ?: 'No description' }}</dd>
<dt class="col-sm-4">Created:</dt>
<dd class="col-sm-8">
{{ $permission->created_at->format('M d, Y') }}
<small class="text-muted d-block">{{ $permission->created_at->diffForHumans() }}</small>
</dd>
<dt class="col-sm-4">Updated:</dt>
<dd class="col-sm-8">
{{ $permission->updated_at->format('M d, Y') }}
<small class="text-muted d-block">{{ $permission->updated_at->diffForHumans() }}</small>
</dd>
</dl>
<hr>
<div class="text-center">
<h3 class="mb-0">{{ $permission->roles->count() }}</h3>
<p class="text-muted mb-0">Assigned Roles</p>
</div>
</div>
</div>
<!-- Quick Actions -->
<div class="card shadow-sm mt-4">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-lightning me-2"></i>Quick Actions</h5>
</div>
<div class="card-body">
@permission('permissions.edit')
<a href="{{ route('admin.permissions.edit', $permission) }}" class="btn btn-outline-primary w-100 mb-2">
<i class="bi bi-pencil me-2"></i>Edit Permission
</a>
@endpermission
@permission('permissions.create')
<form action="{{ route('admin.permissions.clone', $permission) }}" method="POST" class="mb-2">
@csrf
<button type="submit" class="btn btn-outline-secondary w-100">
<i class="bi bi-files me-2"></i>Clone Permission
</button>
</form>
@endpermission
@permission('permissions.delete')
@if($permission->roles->isEmpty())
<button type="button"
class="btn btn-outline-danger w-100"
onclick="confirmDelete()">
<i class="bi bi-trash me-2"></i>Delete Permission
</button>
@endif
@endpermission
</div>
</div>
</div>
<!-- Assigned Roles -->
<div class="col-lg-8 mb-4">
<div class="card shadow-sm">
<div class="card-header bg-white">
<h5 class="mb-0">
<i class="bi bi-person-badge me-2"></i>
Roles with this Permission
<span class="badge bg-primary ms-2">{{ $permission->roles->count() }}</span>
</h5>
</div>
<div class="card-body">
@forelse($permission->roles as $role)
<div class="mb-4">
<div class="d-flex justify-content-between align-items-start border-bottom pb-3">
<div>
<h6 class="mb-1">
{{ $role->name }}
@if($role->slug === config('omni-access.super_admin_role'))
<span class="badge bg-danger ms-2">Super Admin</span>
@endif
@if($role->is_default)
<span class="badge bg-info ms-2">Default</span>
@endif
</h6>
<p class="text-muted small mb-2">{{ $role->description ?: 'No description' }}</p>
<div class="d-flex gap-3">
<small class="text-muted">
<i class="bi bi-people me-1"></i>
{{ $role->users->count() }} users
</small>
<small class="text-muted">
<i class="bi bi-key me-1"></i>
{{ $role->permissions->count() }} permissions
</small>
</div>
</div>
<div>
<a href="{{ route('admin.roles.show', $role) }}" class="btn btn-sm btn-outline-info">
<i class="bi bi-eye"></i> View
</a>
</div>
</div>
@if(!$loop->last && $role->users->count() > 0)
<div class="mt-3 mb-3">
<small class="text-muted">Sample users with this role:</small>
<div class="d-flex flex-wrap gap-2 mt-2">
@foreach($role->users->take(5) as $user)
<span class="badge bg-light text-dark">
<i class="bi bi-person"></i> {{ $user->name }}
</span>
@endforeach
@if($role->users->count() > 5)
<span class="badge bg-secondary">
+{{ $role->users->count() - 5 }} more
</span>
@endif
</div>
</div>
@endif
</div>
@empty
<div class="text-center py-5">
<i class="bi bi-person-x fs-1 text-muted"></i>
<p class="mt-2 text-muted">This permission is not assigned to any roles</p>
@permission('permissions.edit')
<a href="{{ route('admin.permissions.edit', $permission) }}" class="btn btn-primary">
<i class="bi bi-plus-circle me-2"></i>Assign to Roles
</a>
@endpermission
</div>
@endforelse
</div>
</div>
</div>
</div>
</div>
@push('scripts')
<script>
function confirmDelete() {
if (confirm('Are you sure you want to delete this permission? This action cannot be undone.')) {
fetch('{{ route("admin.permissions.destroy", $permission) }}', {
method: 'DELETE',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'Accept': 'application/json'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
window.location.href = '{{ route("admin.permissions.index") }}';
} else {
alert(data.message || 'Error deleting permission');
}
})
.catch(error => {
console.error('Error:', error);
alert('An error occurred');
});
}
}
</script>
@endpush
@endsection
@extends('layouts.admin')
@section('title', 'Permission Details - ' . $permission->name)
@section('content')
<div class="container-fluid">
<!-- Page Header -->
<div class="row mb-4">
<div class="col-12">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ route('admin.dashboard') }}">Dashboard</a></li>
<li class="breadcrumb-item"><a href="{{ route('admin.permissions.index') }}">Permissions</a></li>
<li class="breadcrumb-item active">{{ $permission->name }}</li>
</ol>
</nav>
<div class="d-flex justify-content-between align-items-center">
<div>
<h1 class="h3 mb-2 text-gray-800">{{ $permission->name }}</h1>
<code class="fs-6 text-primary">{{ $permission->slug }}</code>
</div>
<div>
@permission('permissions.edit')
<a href="{{ route('admin.permissions.edit', $permission) }}" class="btn btn-primary">
<i class="bi bi-pencil me-2"></i>Edit Permission
</a>
@endpermission
</div>
</div>
</div>
</div>
<div class="row">
<!-- Permission Information -->
<div class="col-lg-4 mb-4">
<div class="card shadow-sm">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-info-circle me-2"></i>Permission Information</h5>
</div>
<div class="card-body">
<dl class="row">
<dt class="col-sm-4">Name:</dt>
<dd class="col-sm-8">{{ $permission->name }}</dd>
<dt class="col-sm-4">Slug:</dt>
<dd class="col-sm-8"><code>{{ $permission->slug }}</code></dd>
<dt class="col-sm-4">Group:</dt>
<dd class="col-sm-8">
@if($permission->group)
<span class="badge bg-secondary">{{ $permission->group->name }}</span>
@else
<span class="text-muted">No group</span>
@endif
</dd>
<dt class="col-sm-4">Description:</dt>
<dd class="col-sm-8">{{ $permission->description ?: 'No description' }}</dd>
<dt class="col-sm-4">Created:</dt>
<dd class="col-sm-8">
{{ $permission->created_at->format('M d, Y') }}
<small class="text-muted d-block">{{ $permission->created_at->diffForHumans() }}</small>
</dd>
<dt class="col-sm-4">Updated:</dt>
<dd class="col-sm-8">
{{ $permission->updated_at->format('M d, Y') }}
<small class="text-muted d-block">{{ $permission->updated_at->diffForHumans() }}</small>
</dd>
</dl>
<hr>
<div class="text-center">
<h3 class="mb-0">{{ $permission->roles->count() }}</h3>
<p class="text-muted mb-0">Assigned Roles</p>
</div>
</div>
</div>
<!-- Quick Actions -->
<div class="card shadow-sm mt-4">
<div class="card-header bg-white">
<h5 class="mb-0"><i class="bi bi-lightning me-2"></i>Quick Actions</h5>
</div>
<div class="card-body">
@permission('permissions.edit')
<a href="{{ route('admin.permissions.edit', $permission) }}" class="btn btn-outline-primary w-100 mb-2">
<i class="bi bi-pencil me-2"></i>Edit Permission
</a>
@endpermission
@permission('permissions.create')
<form action="{{ route('admin.permissions.clone', $permission) }}" method="POST" class="mb-2">
@csrf
<button type="submit" class="btn btn-outline-secondary w-100">
<i class="bi bi-files me-2"></i>Clone Permission
</button>
</form>
@endpermission
@permission('permissions.delete')
@if($permission->roles->isEmpty())
<button type="button"
class="btn btn-outline-danger w-100"
onclick="confirmDelete()">
<i class="bi bi-trash me-2"></i>Delete Permission
</button>
@endif
@endpermission
</div>
</div>
</div>
<!-- Assigned Roles -->
<div class="col-lg-8 mb-4">
<div class="card shadow-sm">
<div class="card-header bg-white">
<h5 class="mb-0">
<i class="bi bi-person-badge me-2"></i>
Roles with this Permission
<span class="badge bg-primary ms-2">{{ $permission->roles->count() }}</span>
</h5>
</div>
<div class="card-body">
@forelse($permission->roles as $role)
<div class="mb-4">
<div class="d-flex justify-content-between align-items-start border-bottom pb-3">
<div>
<h6 class="mb-1">
{{ $role->name }}
@if($role->slug === config('omni-access.super_admin_role'))
<span class="badge bg-danger ms-2">Super Admin</span>
@endif
@if($role->is_default)
<span class="badge bg-info ms-2">Default</span>
@endif
</h6>
<p class="text-muted small mb-2">{{ $role->description ?: 'No description' }}</p>
<div class="d-flex gap-3">
<small class="text-muted">
<i class="bi bi-people me-1"></i>
{{ $role->users->count() }} users
</small>
<small class="text-muted">
<i class="bi bi-key me-1"></i>
{{ $role->permissions->count() }} permissions
</small>
</div>
</div>
<div>
<a href="{{ route('admin.roles.show', $role) }}" class="btn btn-sm btn-outline-info">
<i class="bi bi-eye"></i> View
</a>
</div>
</div>
@if(!$loop->last && $role->users->count() > 0)
<div class="mt-3 mb-3">
<small class="text-muted">Sample users with this role:</small>
<div class="d-flex flex-wrap gap-2 mt-2">
@foreach($role->users->take(5) as $user)
<span class="badge bg-light text-dark">
<i class="bi bi-person"></i> {{ $user->name }}
</span>
@endforeach
@if($role->users->count() > 5)
<span class="badge bg-secondary">
+{{ $role->users->count() - 5 }} more
</span>
@endif
</div>
</div>
@endif
</div>
@empty
<div class="text-center py-5">
<i class="bi bi-person-x fs-1 text-muted"></i>
<p class="mt-2 text-muted">This permission is not assigned to any roles</p>
@permission('permissions.edit')
<a href="{{ route('admin.permissions.edit', $permission) }}" class="btn btn-primary">
<i class="bi bi-plus-circle me-2"></i>Assign to Roles
</a>
@endpermission
</div>
@endforelse
</div>
</div>
</div>
</div>
</div>
@push('scripts')
<script>
function confirmDelete() {
if (confirm('Are you sure you want to delete this permission? This action cannot be undone.')) {
fetch('{{ route("admin.permissions.destroy", $permission) }}', {
method: 'DELETE',
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}',
'Accept': 'application/json'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
window.location.href = '{{ route("admin.permissions.index") }}';
} else {
alert(data.message || 'Error deleting permission');
}
})
.catch(error => {
console.error('Error:', error);
alert('An error occurred');
});
}
}
</script>
@endpush
@endsection
07
Step 7 of 8
Routes Configuration
// Add to routes/web.php
Route::prefix('admin')->name('admin.')->middleware(['auth'])->group(function () {
// Permissions Management
Route::prefix('permissions')->name('permissions.')->group(function () {
Route::get('/', [PermissionController::class, 'index'])->name('index');
Route::get('/create', [PermissionController::class, 'create'])->name('create');
Route::post('/', [PermissionController::class, 'store'])->name('store');
Route::get('/{permission}', [PermissionController::class, 'show'])->name('show');
Route::get('/{permission}/edit', [PermissionController::class, 'edit'])->name('edit');
Route::put('/{permission}', [PermissionController::class, 'update'])->name('update');
Route::delete('/{permission}', [PermissionController::class, 'destroy'])->name('destroy');
// Additional routes
Route::post('/bulk-delete', [PermissionController::class, 'bulkDelete'])->name('bulk-delete');
Route::post('/{permission}/clone', [PermissionController::class, 'clone'])->name('clone');
});
});
// Add to routes/web.php
Route::prefix('admin')->name('admin.')->middleware(['auth'])->group(function () {
// Permissions Management
Route::prefix('permissions')->name('permissions.')->group(function () {
Route::get('/', [PermissionController::class, 'index'])->name('index');
Route::get('/create', [PermissionController::class, 'create'])->name('create');
Route::post('/', [PermissionController::class, 'store'])->name('store');
Route::get('/{permission}', [PermissionController::class, 'show'])->name('show');
Route::get('/{permission}/edit', [PermissionController::class, 'edit'])->name('edit');
Route::put('/{permission}', [PermissionController::class, 'update'])->name('update');
Route::delete('/{permission}', [PermissionController::class, 'destroy'])->name('destroy');
// Additional routes
Route::post('/bulk-delete', [PermissionController::class, 'bulkDelete'])->name('bulk-delete');
Route::post('/{permission}/clone', [PermissionController::class, 'clone'])->name('clone');
});
});
08
Step 8 of 8
JavaScript Functions for Permission Views
// Permission-specific JavaScript functions
// Select all roles
function selectAllRoles() {
document.querySelectorAll('.role-checkbox').forEach(cb => cb.checked = true);
updateRoleCount?.();
}
// Clear all roles
function selectNoRoles() {
document.querySelectorAll('.role-checkbox').forEach(cb => cb.checked = false);
updateRoleCount?.();
}
// Update role count
function updateRoleCount() {
const count = document.querySelectorAll('.role-checkbox:checked').length;
const counter = document.getElementById('selectedCount');
if (counter) {
counter.textContent = count;
}
}
// Fill permission form with common patterns
function fillPermission(name, slug) {
const nameInput = document.getElementById('name');
const slugInput = document.getElementById('slug');
if (nameInput && nameInput.value === '') {
nameInput.value = name + ' ';
nameInput.focus();
nameInput.setSelectionRange(nameInput.value.length, nameInput.value.length);
}
if (slugInput && slugInput.value === '') {
slugInput.value = slug;
}
}
// Delete single permission
function deletePermission(id, name) {
if (!confirm(`Are you sure you want to delete the permission "${name}"?`)) {
return;
}
fetch(`/admin/permissions/${id}`, {
method: 'DELETE',
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert(data.message || 'Error deleting permission');
}
})
.catch(error => {
console.error('Error:', error);
alert('An error occurred while deleting the permission');
});
}
// Clone permission
function clonePermission(id) {
if (confirm('Clone this permission?')) {
const form = document.createElement('form');
form.method = 'POST';
form.action = `/admin/permissions/${id}/clone`;
const csrfToken = document.createElement('input');
csrfToken.type = 'hidden';
csrfToken.name = '_token';
csrfToken.value = document.querySelector('meta[name="csrf-token"]').content;
form.appendChild(csrfToken);
document.body.appendChild(form);
form.submit();
}
}
// Bulk delete permissions
function bulkDeletePermissions() {
const selected = Array.from(document.querySelectorAll('.permission-checkbox:checked'))
.map(cb => cb.value);
if (selected.length === 0) {
alert('Please select at least one permission to delete');
return;
}
if (!confirm(`Delete ${selected.length} selected permission(s)?`)) {
return;
}
fetch('/admin/permissions/bulk-delete', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ ids: selected })
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert(data.message);
}
})
.catch(error => {
console.error('Error:', error);
alert('An error occurred');
});
}
// Permission-specific JavaScript functions
// Select all roles
function selectAllRoles() {
document.querySelectorAll('.role-checkbox').forEach(cb => cb.checked = true);
updateRoleCount?.();
}
// Clear all roles
function selectNoRoles() {
document.querySelectorAll('.role-checkbox').forEach(cb => cb.checked = false);
updateRoleCount?.();
}
// Update role count
function updateRoleCount() {
const count = document.querySelectorAll('.role-checkbox:checked').length;
const counter = document.getElementById('selectedCount');
if (counter) {
counter.textContent = count;
}
}
// Fill permission form with common patterns
function fillPermission(name, slug) {
const nameInput = document.getElementById('name');
const slugInput = document.getElementById('slug');
if (nameInput && nameInput.value === '') {
nameInput.value = name + ' ';
nameInput.focus();
nameInput.setSelectionRange(nameInput.value.length, nameInput.value.length);
}
if (slugInput && slugInput.value === '') {
slugInput.value = slug;
}
}
// Delete single permission
function deletePermission(id, name) {
if (!confirm(`Are you sure you want to delete the permission "${name}"?`)) {
return;
}
fetch(`/admin/permissions/${id}`, {
method: 'DELETE',
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
'Accept': 'application/json',
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert(data.message || 'Error deleting permission');
}
})
.catch(error => {
console.error('Error:', error);
alert('An error occurred while deleting the permission');
});
}
// Clone permission
function clonePermission(id) {
if (confirm('Clone this permission?')) {
const form = document.createElement('form');
form.method = 'POST';
form.action = `/admin/permissions/${id}/clone`;
const csrfToken = document.createElement('input');
csrfToken.type = 'hidden';
csrfToken.name = '_token';
csrfToken.value = document.querySelector('meta[name="csrf-token"]').content;
form.appendChild(csrfToken);
document.body.appendChild(form);
form.submit();
}
}
// Bulk delete permissions
function bulkDeletePermissions() {
const selected = Array.from(document.querySelectorAll('.permission-checkbox:checked'))
.map(cb => cb.value);
if (selected.length === 0) {
alert('Please select at least one permission to delete');
return;
}
if (!confirm(`Delete ${selected.length} selected permission(s)?`)) {
return;
}
fetch('/admin/permissions/bulk-delete', {
method: 'POST',
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ ids: selected })
})
.then(response => response.json())
.then(data => {
if (data.success) {
location.reload();
} else {
alert(data.message);
}
})
.catch(error => {
console.error('Error:', error);
alert('An error occurred');
});
}
Community Discussions 0
Ask questions, share step solutions, or discuss software workflows with other professionals.
Moderated Community
Join the Community Discussion
Got stuck on a step or have a question about this configuration? Sign in to join the discussion and receive direct advice from instructors and peers.
Guide Checklist
8 Steps
Tutorial Progress
0%
1
Introduction
2
Controller: app/Http/Controllers/Admin/PermissionController.php
3
View: resources/views/admin/permissions/index.blade.php
4
View: resources/views/admin/permissions/create.blade.php
5
View: resources/views/admin/permissions/edit.blade.php
6
View: resources/views/admin/permissions/show.blade.php
7
Routes Configuration
8
JavaScript Functions for Permission Views
No Discussions Yet
Have a question or found a clever tip for this guide? Start the conversation using the comment box above!