diff --git a/app/Data/Role/CreateRoleData.php b/app/Data/Role/CreateRoleData.php
index b7dc0ca..3727e7a 100644
--- a/app/Data/Role/CreateRoleData.php
+++ b/app/Data/Role/CreateRoleData.php
@@ -10,5 +10,6 @@ final class CreateRoleData extends Data
{
public function __construct(
public string $name,
+ public int $priority,
) {}
}
diff --git a/app/Data/Role/RoleData.php b/app/Data/Role/RoleData.php
index 33e6a4f..7569917 100644
--- a/app/Data/Role/RoleData.php
+++ b/app/Data/Role/RoleData.php
@@ -13,6 +13,7 @@ final class RoleData extends Data
public function __construct(
public int $id,
public string $name,
+ public int $priority = 0,
#[DataCollectionOf(class: RoleAppData::class)]
public ?DataCollection $apps = null,
#[DataCollectionOf(class: RoleUserData::class)]
diff --git a/app/Data/Role/UpdateRolePriorityData.php b/app/Data/Role/UpdateRolePriorityData.php
new file mode 100644
index 0000000..91cd31f
--- /dev/null
+++ b/app/Data/Role/UpdateRolePriorityData.php
@@ -0,0 +1,15 @@
+ Role::query()->create([
'name' => $data->name,
+ 'priority' => $data->priority,
'guard_name' => 'web',
]));
@@ -93,8 +94,32 @@ public function getPermissionsGroupedByRole(array $roleIds): ?DataCollection
$roles = Role::query()
->with('permissions:id,name')
->whereIn('id', $roleIds)
- ->get(['id', 'name']);
+ ->get(['id', 'name', 'priority']);
return RoleData::collect($roles, DataCollection::class);
}
+
+ /**
+ * Update the priority of a role.
+ *
+ * @throws InvalidArgumentException when roleId is invalid.
+ * @throws Throwable when an error occurs during the update.
+ */
+ public function updatePriority(UpdateRolePriorityData $data): RoleData
+ {
+ if ($data->roleId <= 0) {
+ throw new InvalidArgumentException('Invalid role id');
+ }
+
+ $role = DB::transaction(function () use ($data) {
+ $role = Role::query()->findOrFail($data->roleId);
+ $role->update([
+ 'priority' => $data->priority,
+ ]);
+
+ return $role;
+ });
+
+ return RoleData::from($role);
+ }
}
diff --git a/database/migrations/2026_05_25_050110_add_priority_to_roles_table.php b/database/migrations/2026_05_25_050110_add_priority_to_roles_table.php
new file mode 100644
index 0000000..9b0d5a3
--- /dev/null
+++ b/database/migrations/2026_05_25_050110_add_priority_to_roles_table.php
@@ -0,0 +1,24 @@
+unsignedInteger('priority')->default(100)->after('guard_name');
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::table('roles', function (Blueprint $table): void {
+ $table->dropColumn('priority');
+ });
+ }
+};
diff --git a/resources/views/pages/access-manager/roles-and-apps/⚡index.blade.php b/resources/views/pages/access-manager/roles-and-apps/⚡index.blade.php
index 21dc554..d5ebc9e 100644
--- a/resources/views/pages/access-manager/roles-and-apps/⚡index.blade.php
+++ b/resources/views/pages/access-manager/roles-and-apps/⚡index.blade.php
@@ -37,6 +37,7 @@ public function mount(): void
{
$this->headers = TableHeader::collect([
new TableHeader(key: 'name', label: 'Name'),
+ new TableHeader(key: 'priority', label: 'Priority'),
new TableHeader(key: 'apps', label: 'Apps'),
new TableHeader(key: 'users', label: 'Users'),
], DataCollection::class);
@@ -85,7 +86,10 @@ public function save(): void
$this->form->validate();
$this->attempt(
action: function (): void {
- $role = $this->roleService->create(new CreateRoleData(name: $this->form->name));
+ $role = $this->roleService->create(new CreateRoleData(
+ name: $this->form->name,
+ priority: (int) $this->form->priority,
+ ));
$this->appRoleService->assign(new AssignAppsToRoleData(
roleId: $role->id,
validUpto: $this->form->isUnlimited ? now()->addYears(15) : $this->form->validUpto,
@@ -128,6 +132,10 @@ public function delete(int $roleId): void
{{ $row->name }}
@endscope
+ @scope('cell_priority', $row)
+ {{ $row->priority }}
+ @endscope
+
@scope('cell_apps', $row)
@foreach($row->apps as $app)
@php /** @var RoleAppData $app */ @endphp
@@ -178,6 +186,14 @@ class="btn-sm btn-circle btn-error btn-soft"
autofocus
/>
+
+
appRoleService = $appRoleService;
+ $this->roleService = $roleService;
}
public function mount(int $id): void
@@ -62,6 +68,7 @@ public function mount(int $id): void
$role = Role::query()->findOrFail($id);
$this->roleId = $role->id;
$this->roleName = $role->name;
+ $this->rolePriority = $role->priority;
},
onError: function (): void {
$this->redirectRoute('access-manager.roles-and-apps.index', navigate: true);
@@ -253,6 +260,32 @@ public function detachUser(int $userId): void
successMessage: 'User removed from role.',
);
}
+
+ public function openEditPriorityModal(): void
+ {
+ $this->newPriority = $this->rolePriority;
+ $this->resetErrorBag();
+ $this->showEditPriorityModal = true;
+ }
+
+ public function savePriority(): void
+ {
+ $this->validate([
+ 'newPriority' => 'required|integer|min:0',
+ ]);
+
+ $this->attempt(
+ action: function (): void {
+ $this->roleService->updatePriority(new UpdateRolePriorityData(
+ roleId: $this->roleId,
+ priority: (int) $this->newPriority,
+ ));
+ $this->rolePriority = (int) $this->newPriority;
+ $this->showEditPriorityModal = false;
+ },
+ successMessage: 'Role priority updated successfully!',
+ );
+ }
};
?>
@@ -268,6 +301,16 @@ class="btn-sm btn-ghost"
tooltip-right="Back To Roles & Apps"
/>
{{ $roleName }}
+
+
+
+
@@ -440,4 +483,26 @@ class="toggle-secondary"
+
+
+
+
+
+
+
+ Cancel
+
+
+ Save
+
+
+
+