improvements

This commit is contained in:
Mark Gregory
2026-08-26 09:25:29 +01:00
parent 53a11ae0c7
commit 21d7b6eba9
6 changed files with 209 additions and 38 deletions
@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
if (Schema::hasTable('helpdesk_team_user')) {
return;
}
Schema::create('helpdesk_team_user', static function (Blueprint $table): void {
$table->foreignId('team_id')
->constrained('helpdesk_teams')
->cascadeOnDelete();
$table->foreignId('user_id')
->constrained('users')
->cascadeOnDelete();
$table->timestamps();
$table->primary(['team_id', 'user_id']);
});
}
public function down(): void
{
Schema::dropIfExists('helpdesk_team_user');
}
};
+38 -8
View File
@@ -42,7 +42,7 @@ final class SettingsManager extends Component
public array $categoryForm = ['id' => null, 'name' => '', 'slug' => '', 'color' => 'blue', 'description' => '', 'is_default' => false]; public array $categoryForm = ['id' => null, 'name' => '', 'slug' => '', 'color' => 'blue', 'description' => '', 'is_default' => false];
/** @var array<string, mixed> */ /** @var array<string, mixed> */
public array $teamForm = ['id' => null, 'name' => '', 'slug' => '', 'color' => 'indigo', 'description' => '', 'is_default' => false, 'archived_at' => null]; public array $teamForm = ['id' => null, 'name' => '', 'slug' => '', 'color' => 'indigo', 'description' => '', 'is_default' => false, 'archived_at' => null, 'user_ids' => []];
/** @var array<string, mixed> */ /** @var array<string, mixed> */
public array $projectForm = ['id' => null, 'team_id' => null, 'title' => '', 'slug' => '', 'color' => 'blue', 'description' => '', 'is_default' => false, 'archived_at' => null]; public array $projectForm = ['id' => null, 'team_id' => null, 'title' => '', 'slug' => '', 'color' => 'blue', 'description' => '', 'is_default' => false, 'archived_at' => null];
@@ -80,7 +80,7 @@ final class SettingsManager extends Component
$this->statusForm += ['id' => null, 'name' => '', 'slug' => '', 'color' => 'gray', 'sort_order' => 0, 'is_closed' => false, 'is_default' => false]; $this->statusForm += ['id' => null, 'name' => '', 'slug' => '', 'color' => 'gray', 'sort_order' => 0, 'is_closed' => false, 'is_default' => false];
$this->priorityForm += ['id' => null, 'name' => '', 'slug' => '', 'color' => 'gray', 'sort_order' => 0, 'is_default' => false]; $this->priorityForm += ['id' => null, 'name' => '', 'slug' => '', 'color' => 'gray', 'sort_order' => 0, 'is_default' => false];
$this->categoryForm += ['id' => null, 'name' => '', 'slug' => '', 'color' => 'blue', 'description' => '', 'is_default' => false]; $this->categoryForm += ['id' => null, 'name' => '', 'slug' => '', 'color' => 'blue', 'description' => '', 'is_default' => false];
$this->teamForm += ['id' => null, 'name' => '', 'slug' => '', 'color' => 'indigo', 'description' => '', 'is_default' => false, 'archived_at' => null]; $this->teamForm += ['id' => null, 'name' => '', 'slug' => '', 'color' => 'indigo', 'description' => '', 'is_default' => false, 'archived_at' => null, 'user_ids' => []];
$this->projectForm += ['id' => null, 'team_id' => null, 'title' => '', 'slug' => '', 'color' => 'blue', 'description' => '', 'is_default' => false, 'archived_at' => null]; $this->projectForm += ['id' => null, 'team_id' => null, 'title' => '', 'slug' => '', 'color' => 'blue', 'description' => '', 'is_default' => false, 'archived_at' => null];
$this->boardForm += ['id' => null, 'name' => '', 'slug' => '', 'description' => '', 'owner_id' => null, 'is_default' => false, 'sort_order' => 0, 'status_ids' => []]; $this->boardForm += ['id' => null, 'name' => '', 'slug' => '', 'description' => '', 'owner_id' => null, 'is_default' => false, 'sort_order' => 0, 'status_ids' => []];
$this->repositoryForm += ['id' => null, 'project_id' => null, 'name' => '', 'provider' => 'git', 'remote_url' => '', 'default_branch' => 'main', 'webhook_secret' => '']; $this->repositoryForm += ['id' => null, 'project_id' => null, 'name' => '', 'provider' => 'git', 'remote_url' => '', 'default_branch' => 'main', 'webhook_secret' => ''];
@@ -250,22 +250,33 @@ final class SettingsManager extends Component
'teamForm.color' => ['required', 'string', Color::validationRule()], 'teamForm.color' => ['required', 'string', Color::validationRule()],
'teamForm.description' => ['nullable', 'string'], 'teamForm.description' => ['nullable', 'string'],
'teamForm.is_default' => ['boolean'], 'teamForm.is_default' => ['boolean'],
'teamForm.user_ids' => ['array'],
'teamForm.user_ids.*' => ['integer', 'distinct', 'exists:users,id'],
])['teamForm']; ])['teamForm'];
$userIds = array_values(array_unique(array_map('intval', $data['user_ids'] ?? [])));
unset($data['user_ids']);
$data['slug'] = $this->slug($data['slug'] ?: $data['name']); $data['slug'] = $this->slug($data['slug'] ?: $data['name']);
$data = $this->guardDefaultColumn('helpdesk_teams', $data); $data = $this->guardDefaultColumn('helpdesk_teams', $data);
if ((bool) ($data['is_default'] ?? false)) { if ((bool) ($data['is_default'] ?? false)) {
$this->clearOtherDefaults(Team::class, $this->teamForm['id']); $this->clearOtherDefaults(Team::class, $this->teamForm['id']);
} }
$this->persistSettingModel(Team::class, $this->teamForm['id'], $data);
/** @var Team $team */
$team = $this->persistSettingModel(Team::class, $this->teamForm['id'], $data);
$team->users()->sync($userIds);
$this->resetTeamForm(); $this->resetTeamForm();
session()->flash('success', 'Team saved.'); session()->flash('success', 'Team saved.');
} }
public function editTeam(int $id): void public function editTeam(int $id): void
{ {
$this->teamForm = Team::query()->findOrFail($id)->only(['id', 'name', 'slug', 'color', 'description', 'is_default', 'archived_at']); $team = Team::query()->with('users:id')->findOrFail($id);
$this->teamForm = $team->only(['id', 'name', 'slug', 'color', 'description', 'is_default', 'archived_at']);
$this->teamForm['user_ids'] = $team->users->pluck('id')->map(static fn ($id): int => (int) $id)->all();
$this->teamForm['color'] = Color::normalise($this->teamForm['color'] ?? 'indigo'); $this->teamForm['color'] = Color::normalise($this->teamForm['color'] ?? 'indigo');
$this->section = 'teams'; $this->section = 'teams';
} }
@@ -276,9 +287,24 @@ final class SettingsManager extends Component
session()->flash('success', 'Team deleted.'); session()->flash('success', 'Team deleted.');
} }
public function removeUserFromTeam(int $teamId, int $userId): void
{
$team = Team::query()->findOrFail($teamId);
$team->users()->detach($userId);
if ((int) ($this->teamForm['id'] ?? 0) === $teamId) {
$this->teamForm['user_ids'] = array_values(array_filter(
array_map('intval', $this->teamForm['user_ids'] ?? []),
static fn (int $id): bool => $id !== $userId,
));
}
session()->flash('success', 'User removed from team.');
}
public function resetTeamForm(): void public function resetTeamForm(): void
{ {
$this->teamForm = ['id' => null, 'name' => '', 'slug' => '', 'color' => 'indigo', 'description' => '', 'is_default' => false, 'archived_at' => null]; $this->teamForm = ['id' => null, 'name' => '', 'slug' => '', 'color' => 'indigo', 'description' => '', 'is_default' => false, 'archived_at' => null, 'user_ids' => []];
} }
public function saveProject(): void public function saveProject(): void
@@ -699,11 +725,14 @@ final class SettingsManager extends Component
public function render(): View public function render(): View
{ {
return view('modules.helpdesk.livewire.settings-manager', [ return view('helpdesk::livewire.settings-manager', [
'statuses' => $this->orderedStatuses(), 'statuses' => $this->orderedStatuses(),
'priorities' => $this->orderedPriorities(), 'priorities' => $this->orderedPriorities(),
'categories' => $this->orderedCategories(), 'categories' => $this->orderedCategories(),
'teams' => $this->orderedTeams(), 'teams' => $this->orderedTeams(),
'teamUsers' => User::query()
->orderBy('name')
->get(['id', 'name', 'email', 'helpdesk_agent', 'helpdesk_admin']),
'projects' => $this->orderedProjects(), 'projects' => $this->orderedProjects(),
'boardOwners' => User::query()->where(static function ($query): void { 'boardOwners' => User::query()->where(static function ($query): void {
$query->where('helpdesk_agent', true)->orWhere('helpdesk_admin', true); $query->where('helpdesk_agent', true)->orWhere('helpdesk_admin', true);
@@ -718,7 +747,7 @@ final class SettingsManager extends Component
'tags' => Tag::query()->orderBy('name')->get(), 'tags' => Tag::query()->orderBy('name')->get(),
'checklistTemplates' => ChecklistTemplate::query()->orderBy('name')->get(), 'checklistTemplates' => ChecklistTemplate::query()->orderBy('name')->get(),
'colourOptions' => Color::options(), 'colourOptions' => Color::options(),
])->layout('layouts.app'); ])->layout('helpdesk::layouts.app.sidebar');
} }
private function orderedStatuses(): mixed private function orderedStatuses(): mixed
@@ -753,7 +782,8 @@ final class SettingsManager extends Component
private function orderedTeams(): mixed private function orderedTeams(): mixed
{ {
return Team::query() return Team::query()
->withCount(['projects', 'tickets']) ->with(['users:id,name,email'])
->withCount(['projects', 'tickets', 'users'])
->when($this->hasDefaultColumn('helpdesk_teams'), fn ($query) => $query->orderByDesc('is_default')) ->when($this->hasDefaultColumn('helpdesk_teams'), fn ($query) => $query->orderByDesc('is_default'))
->orderBy('name') ->orderBy('name')
->get(); ->get();
+14
View File
@@ -4,8 +4,11 @@ declare(strict_types=1);
namespace Modules\Helpdesk\Models; namespace Modules\Helpdesk\Models;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
@@ -25,6 +28,17 @@ final class Team extends Model
'is_default' => 'boolean', 'is_default' => 'boolean',
]; ];
/** @return BelongsToMany<User, Team> */
public function users(): BelongsToMany
{
return $this->belongsToMany(
User::class,
'helpdesk_team_user',
'team_id',
'user_id'
)->withTimestamps();
}
/** @return HasMany<Project> */ /** @return HasMany<Project> */
public function projects(): HasMany public function projects(): HasMany
{ {
@@ -3,29 +3,53 @@
<thead <thead
class="bg-zinc-50 text-left text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:bg-zinc-800 dark:text-zinc-300"> class="bg-zinc-50 text-left text-xs font-semibold uppercase tracking-wide text-zinc-500 dark:bg-zinc-800 dark:text-zinc-300">
<tr> <tr>
<th class="px-3 py-2.5">Team</th> <th class="px-4 py-3">Team</th>
<th class="px-3 py-2.5">Colour</th> <th class="px-4 py-3">Colour</th>
<th class="px-3 py-2.5">Default</th> <th class="px-4 py-3">Default</th>
<th class="px-3 py-2.5">Tickets</th> <th class="px-4 py-3">Members</th>
<th class="px-3 py-2.5 text-right">Actions</th> <th class="px-4 py-3">Tickets</th>
<th class="px-4 py-3 text-right">Actions</th>
</tr> </tr>
</thead> </thead>
<tbody class="divide-y divide-zinc-100 dark:divide-zinc-800"> <tbody class="divide-y divide-zinc-100 dark:divide-zinc-800">
@forelse ($items as $item) @forelse ($items as $item)
<tr> <tr>
<td class="px-3 py-2.5 font-medium text-zinc-900 dark:text-zinc-100">{{ $item->name }}</td> <td class="px-4 py-4 align-top">
<td class="px-3 py-2.5"> <div class="font-semibold text-zinc-900 dark:text-zinc-100">{{ $item->name }}</div>
@if($item->description)
<div class="mt-1 max-w-sm text-xs leading-5 text-zinc-500">{{ $item->description }}</div>
@endif
</td>
<td class="px-4 py-4 align-top">
<span class="inline-flex items-center gap-2 rounded-full border border-zinc-200 bg-white px-2.5 py-1 text-xs font-semibold text-zinc-700 shadow-sm dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200"> <span class="inline-flex items-center gap-2 rounded-full border border-zinc-200 bg-white px-2.5 py-1 text-xs font-semibold text-zinc-700 shadow-sm dark:border-zinc-700 dark:bg-zinc-950 dark:text-zinc-200">
<span class="h-3 w-3 rounded-full" style="background-color: {{ \Modules\Helpdesk\Support\Color::css($item->color) }}"></span> <span class="h-3 w-3 rounded-full" style="background-color: {{ \Modules\Helpdesk\Support\Color::css($item->color) }}"></span>
{{ \Illuminate\Support\Str::of(\Modules\Helpdesk\Support\Color::normalise($item->color))->headline() }} {{ \Illuminate\Support\Str::of(\Modules\Helpdesk\Support\Color::normalise($item->color))->headline() }}
</span> </span>
</td> </td>
<td class="px-3 py-2.5"> <td class="px-4 py-4 align-top">
<flux:badge color="{{ $item->is_default ?? false ? 'emerald' : 'zinc' }}"> <flux:badge color="{{ $item->is_default ?? false ? 'emerald' : 'zinc' }}">
{{ $item->is_default ?? false ? 'Default' : 'No' }}</flux:badge> {{ $item->is_default ?? false ? 'Default' : 'No' }}</flux:badge>
</td> </td>
<td class="px-3 py-2.5 text-zinc-500">{{ $item->tickets_count ?? 0 }}</td> <td class="px-4 py-4 align-top">
<td class="px-3 py-2.5 text-right"> <div class="flex max-w-xl flex-wrap gap-1.5">
@forelse($item->users as $member)
<span class="inline-flex items-center gap-1.5 rounded-full border border-zinc-700 bg-zinc-900 px-2.5 py-1 text-xs font-medium text-zinc-200">
{{ $member->name }}
<button
type="button"
wire:click="removeUserFromTeam({{ $item->id }}, {{ $member->id }})"
wire:confirm="Remove {{ $member->name }} from {{ $item->name }}?"
class="inline-flex h-4 w-4 items-center justify-center rounded-full text-zinc-500 transition hover:bg-red-500/15 hover:text-red-300"
title="Remove {{ $member->name }} from team"
>×</button>
</span>
@empty
<span class="text-xs text-zinc-500">No members</span>
@endforelse
</div>
</td>
<td class="px-4 py-4 align-top text-zinc-500">{{ $item->tickets_count ?? 0 }}</td>
<td class="px-4 py-4 align-top text-right">
<div class="flex justify-end gap-1.5"><button type="button" <div class="flex justify-end gap-1.5"><button type="button"
wire:click="editTeam({{ $item->id }})" wire:click="editTeam({{ $item->id }})"
class="hd-btn hd-btn-sm hd-btn-blue">Edit</button><button type="button" class="hd-btn hd-btn-sm hd-btn-blue">Edit</button><button type="button"
@@ -209,7 +209,7 @@
@if ($section === 'teams') @if ($section === 'teams')
<x-helpdesk.settings-section title="Teams" <x-helpdesk.settings-section title="Teams"
description="Create support teams and assign projects to them."> description="Create support teams, assign users and organise projects.">
<x-slot:form> <x-slot:form>
<form wire:submit.prevent="saveTeam" class="grid gap-3 xl:grid-cols-12"> <form wire:submit.prevent="saveTeam" class="grid gap-3 xl:grid-cols-12">
<div class="xl:col-span-3"> <div class="xl:col-span-3">
@@ -224,6 +224,43 @@
<div class="xl:col-span-12"> <div class="xl:col-span-12">
<flux:textarea wire:model="teamForm.description" label="Description" rows="3" /> <flux:textarea wire:model="teamForm.description" label="Description" rows="3" />
</div> </div>
<div class="xl:col-span-12">
<div class="rounded-xl border border-zinc-700/80 bg-zinc-950/35 p-4">
<div class="mb-3 flex flex-wrap items-center justify-between gap-2">
<div>
<div class="text-sm font-semibold text-zinc-100">Team members</div>
<div class="mt-0.5 text-xs text-zinc-500">Select one or more users to assign to this team.</div>
</div>
<div class="rounded-full bg-blue-500/10 px-2.5 py-1 text-xs font-semibold text-blue-300">
{{ count($teamForm['user_ids'] ?? []) }} selected
</div>
</div>
<div class="grid gap-2 sm:grid-cols-2 xl:grid-cols-3">
@forelse ($teamUsers as $teamUser)
<label class="flex cursor-pointer items-center gap-3 rounded-lg border border-zinc-700 bg-zinc-900/60 p-3 transition hover:border-blue-500/60 hover:bg-zinc-900">
<input
type="checkbox"
wire:model="teamForm.user_ids"
value="{{ $teamUser->id }}"
class="h-4 w-4 rounded border-zinc-600 bg-zinc-950 text-blue-600 focus:ring-blue-500"
>
<div class="min-w-0 flex-1">
<div class="truncate text-sm font-semibold text-zinc-100">{{ $teamUser->name }}</div>
<div class="truncate text-xs text-zinc-500">{{ $teamUser->email }}</div>
</div>
@if ($teamUser->helpdesk_admin)
<span class="rounded-full bg-purple-500/10 px-2 py-0.5 text-[10px] font-bold uppercase text-purple-300">Admin</span>
@elseif ($teamUser->helpdesk_agent)
<span class="rounded-full bg-blue-500/10 px-2 py-0.5 text-[10px] font-bold uppercase text-blue-300">Agent</span>
@endif
</label>
@empty
<div class="text-sm text-zinc-500">No users are available.</div>
@endforelse
</div>
</div>
</div>
<label class="flex min-h-9 items-center gap-2 rounded-lg border border-zinc-200 bg-white px-3 py-2 text-xs font-semibold text-zinc-700 shadow-sm dark:border-zinc-700 dark:bg-zinc-950/60 dark:text-zinc-200 xl:col-span-4"> <label class="flex min-h-9 items-center gap-2 rounded-lg border border-zinc-200 bg-white px-3 py-2 text-xs font-semibold text-zinc-700 shadow-sm dark:border-zinc-700 dark:bg-zinc-950/60 dark:text-zinc-200 xl:col-span-4">
<input type="checkbox" wire:model="teamForm.is_default" <input type="checkbox" wire:model="teamForm.is_default"
class="rounded border-zinc-300 bg-zinc-950 text-blue-600 focus:ring-blue-500"> class="rounded border-zinc-300 bg-zinc-950 text-blue-600 focus:ring-blue-500">
@@ -15,18 +15,36 @@
@if(session('status'))<div class="hd-alert hd-alert-success">{{ session('status') }}</div>@endif @if(session('status'))<div class="hd-alert hd-alert-success">{{ session('status') }}</div>@endif
@if($errors->any())<div class="hd-alert hd-alert-danger"><ul>@foreach($errors->all() as $error)<li>{{ $error }}</li>@endforeach</ul></div>@endif @if($errors->any())<div class="hd-alert hd-alert-danger"><ul>@foreach($errors->all() as $error)<li>{{ $error }}</li>@endforeach</ul></div>@endif
<section class="hd-panel overflow-x-auto"> <section class="hd-panel overflow-hidden">
<div class="p-5 border-b border-zinc-700"><h2 class="text-xl font-semibold">Roles</h2></div> <div class="p-5 border-b border-zinc-700"><h2 class="text-xl font-semibold">Roles</h2></div>
<table class="w-full min-w-[760px]"> <div class="overflow-x-auto"><table class="w-full min-w-[820px] border-collapse">
<thead><tr><th>Name</th><th>Slug</th><th>Users</th><th>Permissions</th><th class="text-right">Actions</th></tr></thead> <thead class="bg-zinc-900/55 text-left text-xs uppercase tracking-[0.12em] text-zinc-400">
<tbody> <tr>
<th class="px-6 py-4 font-semibold">Name</th>
<th class="px-6 py-4 font-semibold">Slug</th>
<th class="px-6 py-4 text-center font-semibold">Users</th>
<th class="px-6 py-4 text-center font-semibold">Permissions</th>
<th class="px-6 py-4 text-right font-semibold">Actions</th>
</tr>
</thead>
<tbody class="divide-y divide-zinc-800/90">
@forelse($roles as $role) @forelse($roles as $role)
<tr> <tr>
<td><strong>{{ $role->name }}</strong>@if($role->is_system) <span class="hd-badge">System</span>@endif</td> <td class="px-6 py-4">
<td><code>{{ $role->slug }}</code></td> <div class="flex items-center gap-2">
<td>{{ $role->users_count }}</td> <strong class="text-sm font-semibold text-zinc-100">{{ $role->name }}</strong>
<td>{{ $role->permissions_count }}</td> @if($role->is_system)
<td><div class="flex justify-end gap-2"> <span class="rounded-full border border-blue-500/30 bg-blue-500/10 px-2 py-0.5 text-[10px] font-bold uppercase tracking-wide text-blue-300">System</span>
@endif
</div>
@if($role->description)
<div class="mt-1 max-w-xl text-xs leading-5 text-zinc-500">{{ $role->description }}</div>
@endif
</td>
<td class="px-6 py-4"><code class="rounded-md bg-black/25 px-2 py-1 text-xs text-zinc-300">{{ $role->slug }}</code></td>
<td class="px-6 py-4 text-center text-sm text-zinc-300">{{ $role->users_count }}</td>
<td class="px-6 py-4 text-center text-sm text-zinc-300">{{ $role->permissions_count }}</td>
<td class="px-6 py-4"><div class="flex justify-end gap-2">
<a class="hd-action hd-action-blue" href="{{ route('user-management.roles.edit', $role) }}">Edit</a> <a class="hd-action hd-action-blue" href="{{ route('user-management.roles.edit', $role) }}">Edit</a>
@unless($role->is_system) @unless($role->is_system)
<form method="POST" action="{{ route('user-management.roles.destroy', $role) }}" onsubmit="return confirm('Delete this role?')">@csrf @method('DELETE') <form method="POST" action="{{ route('user-management.roles.destroy', $role) }}" onsubmit="return confirm('Delete this role?')">@csrf @method('DELETE')
@@ -39,20 +57,32 @@
<tr><td colspan="5" class="p-5">No roles created.</td></tr> <tr><td colspan="5" class="p-5">No roles created.</td></tr>
@endforelse @endforelse
</tbody> </tbody>
</table> </table></div>
</section> </section>
<section class="hd-panel overflow-x-auto"> <section class="hd-panel overflow-hidden">
<div class="p-5 border-b border-zinc-700"><h2 class="text-xl font-semibold">Permissions</h2></div> <div class="p-5 border-b border-zinc-700"><h2 class="text-xl font-semibold">Permissions</h2></div>
<table class="w-full min-w-[760px]"> <div class="overflow-x-auto"><table class="w-full min-w-[820px] border-collapse">
<thead><tr><th>Name</th><th>Slug</th><th>Roles</th><th class="text-right">Actions</th></tr></thead> <thead class="bg-zinc-900/55 text-left text-xs uppercase tracking-[0.12em] text-zinc-400">
<tbody> <tr>
<th class="px-6 py-4 font-semibold">Name</th>
<th class="px-6 py-4 font-semibold">Slug</th>
<th class="px-6 py-4 text-center font-semibold">Roles</th>
<th class="px-6 py-4 text-right font-semibold">Actions</th>
</tr>
</thead>
<tbody class="divide-y divide-zinc-800/90">
@forelse($permissions as $permission) @forelse($permissions as $permission)
<tr> <tr>
<td><strong>{{ $permission->name }}</strong></td> <td class="px-6 py-4">
<td><code>{{ $permission->slug }}</code></td> <strong class="text-sm font-semibold text-zinc-100">{{ $permission->name }}</strong>
<td>{{ $permission->roles_count }}</td> @if($permission->description)
<td><div class="flex justify-end gap-2"> <div class="mt-1 max-w-xl text-xs leading-5 text-zinc-500">{{ $permission->description }}</div>
@endif
</td>
<td class="px-6 py-4"><code class="rounded-md bg-black/25 px-2 py-1 text-xs text-zinc-300">{{ $permission->slug }}</code></td>
<td class="px-6 py-4 text-center text-sm text-zinc-300">{{ $permission->roles_count }}</td>
<td class="px-6 py-4"><div class="flex justify-end gap-2">
<a class="hd-action hd-action-blue" href="{{ route('user-management.permissions.edit', $permission) }}">Edit</a> <a class="hd-action hd-action-blue" href="{{ route('user-management.permissions.edit', $permission) }}">Edit</a>
<form method="POST" action="{{ route('user-management.permissions.destroy', $permission) }}" onsubmit="return confirm('Delete this permission?')">@csrf @method('DELETE') <form method="POST" action="{{ route('user-management.permissions.destroy', $permission) }}" onsubmit="return confirm('Delete this permission?')">@csrf @method('DELETE')
<button class="hd-action hd-action-red" type="submit">Delete</button> <button class="hd-action hd-action-red" type="submit">Delete</button>
@@ -63,7 +93,7 @@
<tr><td colspan="4" class="p-5">No permissions created.</td></tr> <tr><td colspan="4" class="p-5">No permissions created.</td></tr>
@endforelse @endforelse
</tbody> </tbody>
</table> </table></div>
</section> </section>
</div> </div>
</x-layouts::app> </x-layouts::app>