Skip to content

Commit

Permalink
style: Improved ui for selecting api scopes
Browse files Browse the repository at this point in the history
  • Loading branch information
lewislarsen committed Aug 7, 2024
1 parent c86296c commit 3f40409
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 84 deletions.
195 changes: 125 additions & 70 deletions app/Livewire/Profile/APITokenManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,16 @@ class APITokenManager extends Component
/** @var int|null The ID of the API token being deleted */
public ?int $apiTokenIdBeingDeleted = null;

/** @var array<string, bool> The expanded state of permission groups */
public array $expandedGroups = [];

/**
* Initialize the component
*/
public function mount(): void
{
$this->resetPermissions();
$this->initializeExpandedGroups();
}

/**
Expand Down Expand Up @@ -132,84 +136,94 @@ public function render(): View
}

/**
* Get the list of available permissions
* Get the list of available permissions grouped by category
*
* @return array<string, array<string, string>>
* @return array<string, array<string, array<string, string>>>
*/
public function getPermissions(): array
{
return [
'manage-tags' => [
'name' => __('Manage Tags'),
'description' => __('Allows managing of your tags'),
],
'view-backup-destinations' => [
'name' => __('View Backup Destinations'),
'description' => __('Allows viewing backup destinations'),
],
'create-backup-destinations' => [
'name' => __('Create Backup Destinations'),
'description' => __('Allows creating new backup destinations'),
],
'update-backup-destinations' => [
'name' => __('Update Backup Destinations'),
'description' => __('Allows updating existing backup destinations'),
],
'delete-backup-destinations' => [
'name' => __('Delete Backup Destinations'),
'description' => __('Allows deleting backup destinations'),
],
'view-remote-servers' => [
'name' => __('View Remote Servers'),
'description' => __('Allows viewing remote servers'),
],
'create-remote-servers' => [
'name' => __('Create Remote Servers'),
'description' => __('Allows creating new remote servers'),
],
'update-remote-servers' => [
'name' => __('Update Remote Servers'),
'description' => __('Allows updating existing remote servers'),
],
'delete-remote-servers' => [
'name' => __('Delete Remote Servers'),
'description' => __('Allows deleting remote servers'),
],
'view-notification-streams' => [
'name' => __('View Notification Streams'),
'description' => __('Allows viewing notification streams'),
'General' => [
'manage-tags' => [
'name' => __('Manage Tags'),
'description' => __('Allows managing of your tags'),
],
],
'create-notification-streams' => [
'name' => __('Create Notification Streams'),
'description' => __('Allows creating new notification streams'),
'Backup Destinations' => [
'view-backup-destinations' => [
'name' => __('View Backup Destinations'),
'description' => __('Allows viewing backup destinations'),
],
'create-backup-destinations' => [
'name' => __('Create Backup Destinations'),
'description' => __('Allows creating new backup destinations'),
],
'update-backup-destinations' => [
'name' => __('Update Backup Destinations'),
'description' => __('Allows updating existing backup destinations'),
],
'delete-backup-destinations' => [
'name' => __('Delete Backup Destinations'),
'description' => __('Allows deleting backup destinations'),
],
],
'update-notification-streams' => [
'name' => __('Update Notification Streams'),
'description' => __('Allows updating existing notification streams'),
'Remote Servers' => [
'view-remote-servers' => [
'name' => __('View Remote Servers'),
'description' => __('Allows viewing remote servers'),
],
'create-remote-servers' => [
'name' => __('Create Remote Servers'),
'description' => __('Allows creating new remote servers'),
],
'update-remote-servers' => [
'name' => __('Update Remote Servers'),
'description' => __('Allows updating existing remote servers'),
],
'delete-remote-servers' => [
'name' => __('Delete Remote Servers'),
'description' => __('Allows deleting remote servers'),
],
],
'delete-notification-streams' => [
'name' => __('Delete Notification Streams'),
'description' => __('Allows deleting notification streams'),
'Notification Streams' => [
'view-notification-streams' => [
'name' => __('View Notification Streams'),
'description' => __('Allows viewing notification streams'),
],
'create-notification-streams' => [
'name' => __('Create Notification Streams'),
'description' => __('Allows creating new notification streams'),
],
'update-notification-streams' => [
'name' => __('Update Notification Streams'),
'description' => __('Allows updating existing notification streams'),
],
'delete-notification-streams' => [
'name' => __('Delete Notification Streams'),
'description' => __('Allows deleting notification streams'),
],
],
'view-backup-tasks' => [
'name' => __('View Backup Tasks'),
'description' => __('Allows viewing backup tasks'),
],
'create-backup-tasks' => [
'name' => __('Create Backup Tasks'),
'description' => __('Allows creating new backup tasks'),
],
'update-backup-tasks' => [
'name' => __('Update Backup Tasks'),
'description' => __('Allows updating existing backup tasks'),
],
'delete-backup-tasks' => [
'name' => __('Delete Backup Tasks'),
'description' => __('Allows deleting backup tasks'),
],
'run-backup-tasks' => [
'name' => __('Run Backup Tasks'),
'description' => __('Allows the running of backup tasks'),
'Backup Tasks' => [
'view-backup-tasks' => [
'name' => __('View Backup Tasks'),
'description' => __('Allows viewing backup tasks'),
],
'create-backup-tasks' => [
'name' => __('Create Backup Tasks'),
'description' => __('Allows creating new backup tasks'),
],
'update-backup-tasks' => [
'name' => __('Update Backup Tasks'),
'description' => __('Allows updating existing backup tasks'),
],
'delete-backup-tasks' => [
'name' => __('Delete Backup Tasks'),
'description' => __('Allows deleting backup tasks'),
],
'run-backup-tasks' => [
'name' => __('Run Backup Tasks'),
'description' => __('Allows the running of backup tasks'),
],
],
];
}
Expand All @@ -219,7 +233,40 @@ public function getPermissions(): array
*/
public function resetPermissions(): void
{
$this->permissions = array_fill_keys(array_keys($this->getPermissions()), false);
$this->permissions = array_fill_keys(
array_keys(array_merge(...array_values($this->getPermissions()))),
false
);
}

/**
* Toggle the expanded state of a permission group
*
* @param string $group The group to toggle
*/
public function toggleGroup(string $group): void
{
foreach (array_keys($this->expandedGroups) as $key) {
$this->expandedGroups[$key] = false;
}

$this->expandedGroups[$group] = true;
}

/**
* Select all permissions
*/
public function selectAllPermissions(): void
{
$this->permissions = array_fill_keys(array_keys($this->permissions), true);
}

/**
* Deselect all permissions
*/
public function deselectAllPermissions(): void
{
$this->permissions = array_fill_keys(array_keys($this->permissions), false);
}

/**
Expand All @@ -246,4 +293,12 @@ protected function displayTokenValue(NewAccessToken $newAccessToken): void
$this->dispatch('close-modal', 'create-api-token');
$this->dispatch('open-modal', 'api-token-value');
}

/**
* Initialize the expanded state of permission groups
*/
private function initializeExpandedGroups(): void
{
$this->expandedGroups = array_fill_keys(array_keys($this->getPermissions()), false);
}
}
60 changes: 46 additions & 14 deletions resources/views/livewire/profile/api-token-manager.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,51 @@ class="mt-1 block w-full" required />

<div>
<x-input-label :value="__('Token Permissions')" class="mb-3"/>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
@foreach ($this->getPermissions() as $key => $permission)
<div class="flex items-center space-x-3">
<x-toggle
:name="'permissions.' . $key"
:label="$permission['name']"
:model="'permissions.' . $key"
live
/>
<div>
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ $permission['description'] }}
</p>
<div class="mb-4 flex justify-between items-center">
<x-secondary-button wire:click="selectAllPermissions" type="button">
{{ __('Select All') }}
</x-secondary-button>
<x-secondary-button wire:click="deselectAllPermissions" type="button">
{{ __('Deselect All') }}
</x-secondary-button>
</div>
<div class="space-y-4">
@foreach ($this->getPermissions() as $group => $groupPermissions)
<div class="border border-gray-200 dark:border-gray-700 rounded-md overflow-hidden">
<button type="button" wire:click="toggleGroup('{{ $group }}')"
class="w-full px-4 py-2 text-left bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 dark:hover:bg-gray-700 focus:outline-none">
<span class="font-medium">{{ $group }}</span>
<span class="float-right">
@if ($expandedGroups[$group])
@svg('heroicon-s-chevron-up', 'w-5 h-5 inline')
@else
@svg('heroicon-s-chevron-down', 'w-5 h-5 inline')
@endif
</span>
</button>
<div x-show="$wire.expandedGroups['{{ $group }}']" x-collapse>
<div class="p-4 space-y-4">
@foreach ($groupPermissions as $key => $permission)
<div class="flex items-center space-x-3">
<x-toggle
:name="'permissions.' . $key"
:label="$permission['name']"
:model="'permissions.' . $key"
live
/>
<div class="relative group">
<div>
<p class="text-xs text-gray-500 dark:text-gray-400">
{{ $permission['name'] }}
</p>
</div>
<div class="absolute left-0 bottom-full mb-2 w-48 bg-gray-800 text-white text-xs rounded p-2 hidden group-hover:block z-50">
{{ $permission['description'] }}
</div>
</div>
</div>
@endforeach
</div>
</div>
</div>
@endforeach
Expand All @@ -43,7 +75,7 @@ class="mt-1 block w-full" required />
<div class="mt-6 max-w-3xl mx-auto">
<div class="flex flex-col sm:flex-row sm:space-x-5 space-y-4 sm:space-y-0">
<div class="w-full sm:w-4/6">
<x-primary-button type="submit" class="w-full justify-center" centered action="createApiToken" ire:loading.attr="disabled">
<x-primary-button type="submit" class="w-full justify-center" centered action="createApiToken" wire:loading.attr="disabled">
{{ __('Save') }}
</x-primary-button>
</div>
Expand Down

0 comments on commit 3f40409

Please sign in to comment.