diff --git a/app/Http/Livewire/Administration/TicketPriorities.php b/app/Http/Livewire/Administration/TicketPriorities.php index be7f523f..26ca836c 100644 --- a/app/Http/Livewire/Administration/TicketPriorities.php +++ b/app/Http/Livewire/Administration/TicketPriorities.php @@ -3,67 +3,98 @@ namespace App\Http\Livewire\Administration; use App\Models\TicketPriority; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Concerns\InteractsWithForms; -use Filament\Forms\Contracts\HasForms; +use Filament\Tables\Actions\Action; +use Filament\Tables\Columns\TextColumn; +use Filament\Tables\Concerns\InteractsWithTable; +use Filament\Tables\Contracts\HasTable; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\Relation; +use Illuminate\Support\HtmlString; use Livewire\Component; -class TicketPriorities extends Component implements HasForms +class TicketPriorities extends Component implements HasTable { - use InteractsWithForms; + use InteractsWithTable; - public $search; public $selectedPriority; protected $listeners = ['prioritySaved', 'priorityDeleted']; - public function mount(): void + public function render() { - $this->form->fill(); + return view('livewire.administration.ticket-priorities'); } - public function render() + /** + * Table query definition + * + * @return Builder|Relation + */ + protected function getTableQuery(): Builder|Relation { - $query = TicketPriority::query(); - if ($this->search) { - $query->where('title', 'like', '%' . $this->search . '%') - ->orWhere('text_color', 'like', '%' . $this->search . '%') - ->orWhere('bg_color', 'like', '%' . $this->search . '%') - ->orWhere('icon', 'like', '%' . $this->search . '%'); - } - $priorities = $query->paginate(); - return view('livewire.administration.ticket-priorities', compact('priorities')); + return TicketPriority::query(); } /** - * Form schema definition + * Table definition * * @return array */ - protected function getFormSchema(): array + protected function getTableColumns(): array { return [ - Grid::make(1) - ->schema([ - TextInput::make('search') - ->label(__('Search for tickets priorities')) - ->disableLabel() - ->type('search') - ->placeholder(__('Search for tickets priorities')), - ]), + TextColumn::make('title') + ->label(__('Title')) + ->searchable() + ->sortable() + ->formatStateUsing(fn(TicketPriority $record) => new HtmlString(' + + ' . $record->title . ' + + ')), + + TextColumn::make('created_at') + ->label(__('Created at')) + ->sortable() + ->searchable() + ->dateTime(), ]; } /** - * Search for tickets priorities + * Table actions definition * - * @return void + * @return array + */ + protected function getTableActions(): array + { + return [ + Action::make('edit') + ->icon('heroicon-o-pencil') + ->link() + ->label(__('Edit priority')) + ->action(fn(TicketPriority $record) => $this->updatePriority($record->id)) + ]; + } + + /** + * Table default sort column definition + * + * @return string|null + */ + protected function getDefaultTableSortColumn(): ?string + { + return 'created_at'; + } + + /** + * Table default sort direction definition + * + * @return string|null */ - public function search(): void + protected function getDefaultTableSortDirection(): ?string { - $data = $this->form->getState(); - $this->search = $data['search'] ?? null; + return 'desc'; } /** @@ -105,8 +136,8 @@ public function cancelPriority() * * @return void */ - public function prioritySaved() { - $this->search(); + public function prioritySaved() + { $this->cancelPriority(); } @@ -115,7 +146,8 @@ public function prioritySaved() { * * @return void */ - public function priorityDeleted() { + public function priorityDeleted() + { $this->prioritySaved(); } } diff --git a/app/Http/Livewire/Administration/TicketStatuses.php b/app/Http/Livewire/Administration/TicketStatuses.php index 104bffb8..a3c11df3 100644 --- a/app/Http/Livewire/Administration/TicketStatuses.php +++ b/app/Http/Livewire/Administration/TicketStatuses.php @@ -3,66 +3,108 @@ namespace App\Http\Livewire\Administration; use App\Models\TicketStatus; +use App\Models\User; use Filament\Forms\Components\Grid; use Filament\Forms\Components\TextInput; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; +use Filament\Tables\Actions\Action; +use Filament\Tables\Columns\BadgeColumn; +use Filament\Tables\Columns\BooleanColumn; +use Filament\Tables\Columns\TextColumn; +use Filament\Tables\Concerns\InteractsWithTable; +use Filament\Tables\Contracts\HasTable; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\Relation; +use Illuminate\Support\HtmlString; use Livewire\Component; -class TicketStatuses extends Component implements HasForms +class TicketStatuses extends Component implements HasTable { - use InteractsWithForms; + use InteractsWithTable; - public $search; public $selectedStatus; protected $listeners = ['statusSaved', 'statusDeleted']; - public function mount(): void + public function render() { - $this->form->fill(); + return view('livewire.administration.ticket-statuses'); } - public function render() + /** + * Table query definition + * + * @return Builder|Relation + */ + protected function getTableQuery(): Builder|Relation { - $query = TicketStatus::query(); - if ($this->search) { - $query->where('title', 'like', '%' . $this->search . '%') - ->orWhere('text_color', 'like', '%' . $this->search . '%') - ->orWhere('bg_color', 'like', '%' . $this->search . '%'); - } - $statuses = $query->paginate(); - return view('livewire.administration.ticket-statuses', compact('statuses')); + return TicketStatus::query(); } /** - * Form schema definition + * Table definition * * @return array */ - protected function getFormSchema(): array + protected function getTableColumns(): array { return [ - Grid::make(1) - ->schema([ - TextInput::make('search') - ->label(__('Search for tickets statuses')) - ->disableLabel() - ->type('search') - ->placeholder(__('Search for tickets statuses')), - ]), + TextColumn::make('title') + ->label(__('Title')) + ->searchable() + ->sortable() + ->formatStateUsing(fn (TicketStatus $record) => new HtmlString(' + ' . $record->title . ' + ')), + + BooleanColumn::make('default') + ->label(__('Default status')) + ->sortable() + ->searchable(), + + TextColumn::make('created_at') + ->label(__('Created at')) + ->sortable() + ->searchable() + ->dateTime(), ]; } /** - * Search for tickets statuses + * Table actions definition * - * @return void + * @return array + */ + protected function getTableActions(): array + { + return [ + Action::make('edit') + ->icon('heroicon-o-pencil') + ->link() + ->label(__('Edit status')) + ->action(fn(TicketStatus $record) => $this->updateStatus($record->id)) + ]; + } + + /** + * Table default sort column definition + * + * @return string|null + */ + protected function getDefaultTableSortColumn(): ?string + { + return 'created_at'; + } + + /** + * Table default sort direction definition + * + * @return string|null */ - public function search(): void + protected function getDefaultTableSortDirection(): ?string { - $data = $this->form->getState(); - $this->search = $data['search'] ?? null; + return 'desc'; } /** @@ -105,7 +147,6 @@ public function cancelStatus() * @return void */ public function statusSaved() { - $this->search(); $this->cancelStatus(); } diff --git a/app/Http/Livewire/Administration/TicketTypes.php b/app/Http/Livewire/Administration/TicketTypes.php index 031d47b4..ba3f8e6e 100644 --- a/app/Http/Livewire/Administration/TicketTypes.php +++ b/app/Http/Livewire/Administration/TicketTypes.php @@ -2,68 +2,105 @@ namespace App\Http\Livewire\Administration; +use App\Models\TicketStatus; use App\Models\TicketType; use Filament\Forms\Components\Grid; use Filament\Forms\Components\TextInput; use Filament\Forms\Concerns\InteractsWithForms; use Filament\Forms\Contracts\HasForms; +use Filament\Tables\Actions\Action; +use Filament\Tables\Columns\BooleanColumn; +use Filament\Tables\Columns\TextColumn; +use Filament\Tables\Concerns\InteractsWithTable; +use Filament\Tables\Contracts\HasTable; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\Relation; +use Illuminate\Support\HtmlString; use Livewire\Component; -class TicketTypes extends Component implements HasForms +class TicketTypes extends Component implements HasTable { - use InteractsWithForms; + use InteractsWithTable; - public $search; public $selectedType; protected $listeners = ['typeSaved', 'typeDeleted']; - public function mount(): void + public function render() { - $this->form->fill(); + return view('livewire.administration.ticket-types'); } - public function render() + /** + * Table query definition + * + * @return Builder|Relation + */ + protected function getTableQuery(): Builder|Relation { - $query = TicketType::query(); - if ($this->search) { - $query->where('title', 'like', '%' . $this->search . '%') - ->orWhere('text_color', 'like', '%' . $this->search . '%') - ->orWhere('bg_color', 'like', '%' . $this->search . '%') - ->orWhere('icon', 'like', '%' . $this->search . '%'); - } - $types = $query->paginate(); - return view('livewire.administration.ticket-types', compact('types')); + return TicketType::query(); } /** - * Form schema definition + * Table definition * * @return array */ - protected function getFormSchema(): array + protected function getTableColumns(): array { return [ - Grid::make(1) - ->schema([ - TextInput::make('search') - ->label(__('Search for tickets types')) - ->disableLabel() - ->type('search') - ->placeholder(__('Search for tickets types')), - ]), + TextColumn::make('title') + ->label(__('Title')) + ->searchable() + ->sortable() + ->formatStateUsing(fn (TicketType $record) => new HtmlString(' + + ' . $record->title . ' + + ')), + + TextColumn::make('created_at') + ->label(__('Created at')) + ->sortable() + ->searchable() + ->dateTime(), ]; } /** - * Search for tickets types + * Table actions definition * - * @return void + * @return array + */ + protected function getTableActions(): array + { + return [ + Action::make('edit') + ->icon('heroicon-o-pencil') + ->link() + ->label(__('Edit type')) + ->action(fn(TicketType $record) => $this->updateType($record->id)) + ]; + } + + /** + * Table default sort column definition + * + * @return string|null + */ + protected function getDefaultTableSortColumn(): ?string + { + return 'created_at'; + } + + /** + * Table default sort direction definition + * + * @return string|null */ - public function search(): void + protected function getDefaultTableSortDirection(): ?string { - $data = $this->form->getState(); - $this->search = $data['search'] ?? null; + return 'desc'; } /** @@ -106,7 +143,6 @@ public function cancelType() * @return void */ public function typeSaved() { - $this->search(); $this->cancelType(); } diff --git a/app/Http/Livewire/Administration/Users.php b/app/Http/Livewire/Administration/Users.php index 7c54ff34..6db099f5 100644 --- a/app/Http/Livewire/Administration/Users.php +++ b/app/Http/Livewire/Administration/Users.php @@ -4,66 +4,115 @@ use App\Models\User; use App\Notifications\UserCreatedNotification; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Concerns\InteractsWithForms; -use Filament\Forms\Contracts\HasForms; use Filament\Notifications\Notification; +use Filament\Tables\Actions\Action; +use Filament\Tables\Columns\BadgeColumn; +use Filament\Tables\Columns\BooleanColumn; +use Filament\Tables\Columns\TextColumn; +use Filament\Tables\Concerns\InteractsWithTable; +use Filament\Tables\Contracts\HasTable; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\Relation; use Livewire\Component; -class Users extends Component implements HasForms +class Users extends Component implements HasTable { - use InteractsWithForms; + use InteractsWithTable; - public $search; public $selectedUser; protected $listeners = ['userSaved', 'userDeleted']; - public function mount(): void + public function render() { - $this->form->fill(); + return view('livewire.administration.users'); } - public function render() + /** + * Table query definition + * + * @return Builder|Relation + */ + protected function getTableQuery(): Builder|Relation { - $query = User::query(); - if ($this->search) { - $query->where('name', 'like', '%' . $this->search . '%') - ->orWhere('email', 'like', '%' . $this->search . '%'); - } - $users = $query->paginate(); - return view('livewire.administration.users', compact('users')); + return User::query(); } /** - * Form schema definition + * Table definition * * @return array */ - protected function getFormSchema(): array + protected function getTableColumns(): array { return [ - Grid::make(1) - ->schema([ - TextInput::make('search') - ->label(__('Search for users')) - ->disableLabel() - ->type('search') - ->placeholder(__('Search for users')), - ]), + TextColumn::make('name') + ->label(__('Full name')) + ->searchable() + ->sortable(), + + BadgeColumn::make('role') + ->label(__('Role')) + ->searchable() + ->sortable() + ->enum(roles_list()) + ->colors(roles_list_badges()), + + BooleanColumn::make('isAccountActivated') + ->label(__('Account activated')) + ->sortable() + ->searchable(), + + TextColumn::make('created_at') + ->label(__('Created at')) + ->sortable() + ->searchable() + ->dateTime(), ]; } /** - * Search for users + * Table actions definition * - * @return void + * @return array */ - public function search(): void + protected function getTableActions(): array { - $data = $this->form->getState(); - $this->search = $data['search'] ?? null; + return [ + Action::make('resend_email_registration') + ->icon('heroicon-o-at-symbol') + ->link() + ->color('warning') + ->label(__('Resend activation email')) + ->visible(fn(User $record) => $record->register_token) + ->action(fn(User $record) => $this->resendActivationEmail($record->id)), + + Action::make('edit') + ->icon('heroicon-o-pencil') + ->link() + ->label(__('Edit user')) + ->action(fn(User $record) => $this->updateUser($record->id)) + ]; + } + + /** + * Table default sort column definition + * + * @return string|null + */ + protected function getDefaultTableSortColumn(): ?string + { + return 'created_at'; + } + + /** + * Table default sort direction definition + * + * @return string|null + */ + protected function getDefaultTableSortDirection(): ?string + { + return 'desc'; } /** @@ -105,8 +154,8 @@ public function cancelUser() * * @return void */ - public function userSaved() { - $this->search(); + public function userSaved() + { $this->cancelUser(); } @@ -115,17 +164,20 @@ public function userSaved() { * * @return void */ - public function userDeleted() { + public function userDeleted() + { $this->userSaved(); } /** * Resend the account activation email to a specific user * - * @param User $user + * @param int $userId * @return void */ - public function resendActivationEmail(User $user) { + public function resendActivationEmail(int $userId) + { + $user = User::find($userId); if ($user->register_token) { $user->notify(new UserCreatedNotification($user)); Notification::make() diff --git a/app/Http/Livewire/Projects.php b/app/Http/Livewire/Projects.php index 2189494c..354da103 100644 --- a/app/Http/Livewire/Projects.php +++ b/app/Http/Livewire/Projects.php @@ -4,32 +4,40 @@ use App\Models\FavoriteProject; use App\Models\Project; -use App\Notifications\ProjectCreatedNotification; -use Filament\Forms\Components\Grid; -use Filament\Forms\Components\TextInput; -use Filament\Forms\Concerns\InteractsWithForms; -use Filament\Forms\Contracts\HasForms; +use App\Tables\Columns\UserColumn; use Filament\Notifications\Notification; +use Filament\Tables\Actions\Action; +use Filament\Tables\Columns\TextColumn; +use Filament\Tables\Concerns\InteractsWithTable; +use Filament\Tables\Contracts\HasTable; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Relations\Relation; +use Illuminate\Support\HtmlString; +use Illuminate\Support\Str; use Livewire\Component; -class Projects extends Component implements HasForms +class Projects extends Component implements HasTable { - use InteractsWithForms; + use InteractsWithTable; - public $search; public $selectedProject; protected $listeners = ['projectSaved', 'projectDeleted']; - public function mount(): void + public function render() { - $this->form->fill(); + return view('livewire.projects'); } - public function render() + /** + * Table query definition + * + * @return Builder|Relation + */ + protected function getTableQuery(): Builder|Relation { $query = Project::query(); - $query->with('favoriteUsers'); + $query->withCount('tickets'); if (has_all_permissions(auth()->user(), 'view-own-projects') && !has_all_permissions(auth()->user(), 'view-all-projects')) { $query->where(function ($query) { $query->where('owner_id', auth()->user()->id) @@ -38,42 +46,89 @@ public function render() }); }); } - if ($this->search) { - $query->where('name', 'like', '%' . $this->search . '%') - ->orWhere('description', 'like', '%' . $this->search . '%'); - } - $projects = $query->paginate(); - return view('livewire.projects', compact('projects')); + return $query; } /** - * Form schema definition + * Table definition * * @return array */ - protected function getFormSchema(): array + protected function getTableColumns(): array { return [ - Grid::make(1) - ->schema([ - TextInput::make('search') - ->label(__('Search for projects')) - ->disableLabel() - ->type('search') - ->placeholder(__('Search for projects')), - ]), + TextColumn::make('make_favorite') + ->label('') + ->formatStateUsing(function (Project $record) { + $btnClass = $record->favoriteUsers()->where('user_id', auth()->user()->id)->count() ? 'text-warning-500' : 'text-gray-500'; + $iconClass = $record->favoriteUsers()->where('user_id', auth()->user()->id)->count() ? 'fa-star' : 'fa-star-o'; + return new HtmlString(' + + '); + }), + + TextColumn::make('name') + ->label(__('Project name')) + ->searchable() + ->sortable(), + + TextColumn::make('description') + ->label(__('Description')) + ->searchable() + ->sortable() + ->formatStateUsing(fn(string $state) => Str::limit(htmlspecialchars(strip_tags($state)), 50)), + + UserColumn::make('owner') + ->label(__('Owner')), + + TextColumn::make('tickets_count') + ->label(__('Tickets')) + ->sortable(), + + TextColumn::make('created_at') + ->label(__('Created at')) + ->sortable() + ->searchable() + ->dateTime(), ]; } /** - * Search for projects + * Table actions definition * - * @return void + * @return array + */ + protected function getTableActions(): array + { + return [ + Action::make('edit') + ->icon('heroicon-o-pencil') + ->link() + ->label(__('Edit project')) + ->action(fn(Project $record) => $this->updateProject($record->id)) + ]; + } + + /** + * Table default sort column definition + * + * @return string|null */ - public function search(): void + protected function getDefaultTableSortColumn(): ?string { - $data = $this->form->getState(); - $this->search = $data['search'] ?? null; + return 'created_at'; + } + + /** + * Table default sort direction definition + * + * @return string|null + */ + protected function getDefaultTableSortDirection(): ?string + { + return 'desc'; } /** @@ -115,8 +170,8 @@ public function cancelProject() * * @return void */ - public function projectSaved() { - $this->search(); + public function projectSaved() + { $this->cancelProject(); } @@ -125,17 +180,20 @@ public function projectSaved() { * * @return void */ - public function projectDeleted() { + public function projectDeleted() + { $this->projectSaved(); } /** * Add / Remove project from authenticated user favorite projects * - * @param Project $project + * @param int $projectId * @return void */ - public function toggleFavoriteProject(Project $project) { + public function toggleFavoriteProject(int $projectId) + { + $project = Project::find($projectId); if (FavoriteProject::where('user_id', auth()->user()->id)->where('project_id', $project->id)->count()) { FavoriteProject::where('user_id', auth()->user()->id)->where('project_id', $project->id)->delete(); Notification::make() @@ -154,6 +212,5 @@ public function toggleFavoriteProject(Project $project) { ->body(__('The project has been successfully added to your favorite projects')) ->send(); } - $this->search(); } } diff --git a/app/Models/User.php b/app/Models/User.php index 73a54243..0a141460 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -5,6 +5,7 @@ // use Illuminate\Contracts\Auth\MustVerifyEmail; use App\Core\HasLogsActivity; use App\Core\LogsActivity; +use Devaslanphp\FilamentAvatar\Core\HasAvatarUrl; use Illuminate\Auth\Passwords\CanResetPassword; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Casts\Attribute; @@ -18,7 +19,7 @@ class User extends Authenticatable implements HasLogsActivity { - use HasApiTokens, HasFactory, Notifiable, CanResetPassword, SoftDeletes, LogsActivity; + use HasApiTokens, HasFactory, Notifiable, CanResetPassword, SoftDeletes, LogsActivity, HasAvatarUrl; /** * The attributes that are mass assignable. @@ -53,10 +54,6 @@ class User extends Authenticatable implements HasLogsActivity 'email_verified_at' => 'datetime', ]; - protected $appends = [ - 'avatar_url' - ]; - protected static function boot() { parent::boot(); @@ -65,13 +62,6 @@ protected static function boot() }); } - public function avatarUrl(): Attribute - { - return new Attribute( - get: fn() => 'https://ui-avatars.com/api/?color=FFFFFF&background=111827&name=' . $this->name - ); - } - public function projects(): HasMany { return $this->hasMany(Project::class, 'owner_id'); @@ -110,4 +100,11 @@ public function activityLogLink(): string { return route('administration.users'); } + + public function isAccountActivated(): Attribute + { + return new Attribute( + get: fn() => $this->register_token == null + ); + } } diff --git a/app/Tables/Columns/UserColumn.php b/app/Tables/Columns/UserColumn.php new file mode 100644 index 00000000..102f3100 --- /dev/null +++ b/app/Tables/Columns/UserColumn.php @@ -0,0 +1,10 @@ + VALUE (role title) + * + * @return array + */ + function roles_list_badges(): array + { + $roles = []; + foreach (config('system.roles') as $key => $value) { + $roles[$value['badge-color']] = $key; + } + return $roles; + } +} + if (!function_exists('has_all_permissions')) { /** * Check if the user has all the permissions passed as parameters diff --git a/composer.json b/composer.json index 5858659f..45958a28 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "license": "MIT", "require": { "php": "^8.0.2", + "devaslanphp/filament-avatar": "^1.0", "filament/forms": "^2.15", "filament/notifications": "^2.15", "guzzlehttp/guzzle": "^7.2", diff --git a/composer.lock b/composer.lock index e0dcd513..6787d447 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2584428e458fa96e07fdbb8de179a760", + "content-hash": "66b739442c43a1297dbf8d7c2d2d7cd2", "packages": [ { "name": "akaunting/laravel-money", @@ -145,16 +145,16 @@ }, { "name": "blade-ui-kit/blade-icons", - "version": "v1.3.1", + "version": "1.3.2", "source": { "type": "git", "url": "https://github.com/blade-ui-kit/blade-icons.git", - "reference": "efa53eb8bfc674306a02304eb6186adb078c8815" + "reference": "88eda22d90138c854ddad856de0ddf581d2f0d79" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/blade-ui-kit/blade-icons/zipball/efa53eb8bfc674306a02304eb6186adb078c8815", - "reference": "efa53eb8bfc674306a02304eb6186adb078c8815", + "url": "https://api.github.com/repos/blade-ui-kit/blade-icons/zipball/88eda22d90138c854ddad856de0ddf581d2f0d79", + "reference": "88eda22d90138c854ddad856de0ddf581d2f0d79", "shasum": "" }, "require": { @@ -222,7 +222,7 @@ "type": "github" } ], - "time": "2022-08-24T13:35:42+00:00" + "time": "2022-09-21T11:34:49+00:00" }, { "name": "brick/math", @@ -385,6 +385,61 @@ ], "time": "2022-01-21T11:26:58+00:00" }, + { + "name": "devaslanphp/filament-avatar", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/devaslanphp/filament-avatar.git", + "reference": "36f1151f48e6938bc16dc3ece03e3ec153a88806" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/devaslanphp/filament-avatar/zipball/36f1151f48e6938bc16dc3ece03e3ec153a88806", + "reference": "36f1151f48e6938bc16dc3ece03e3ec153a88806", + "shasum": "" + }, + "require": { + "php": "^8.0", + "spatie/laravel-package-tools": "^1.9" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Devaslanphp\\FilamentAvatar\\FilamentAvatarProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Devaslanphp\\FilamentAvatar\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "EL OUFIR Hatim", + "email": "eloufirhatim@gmail.com" + } + ], + "description": "A complete and customizable User Avatar provider for your Filament project, and also for any project using a User Model.", + "homepage": "https://github.com/devaslanphp/filament-avatar", + "keywords": [ + "avatar", + "filament", + "provider", + "user" + ], + "support": { + "issues": "https://github.com/devaslanphp/filament-avatar/issues", + "source": "https://github.com/devaslanphp/filament-avatar/tree/1.0.0" + }, + "time": "2022-09-20T13:56:28+00:00" + }, { "name": "dflydev/dot-access-data", "version": "v3.0.1", @@ -758,16 +813,16 @@ }, { "name": "filament/filament", - "version": "v2.16.5", + "version": "v2.16.14", "source": { "type": "git", "url": "https://github.com/filamentphp/admin.git", - "reference": "94320edcd20fbd30db5b93c0ba43326d83953bf3" + "reference": "1e1c937094e30d16d3f29e924b0c18ec5d49d902" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/admin/zipball/94320edcd20fbd30db5b93c0ba43326d83953bf3", - "reference": "94320edcd20fbd30db5b93c0ba43326d83953bf3", + "url": "https://api.github.com/repos/filamentphp/admin/zipball/1e1c937094e30d16d3f29e924b0c18ec5d49d902", + "reference": "1e1c937094e30d16d3f29e924b0c18ec5d49d902", "shasum": "" }, "require": { @@ -817,20 +872,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2022-09-16T14:59:12+00:00" + "time": "2022-09-23T11:39:36+00:00" }, { "name": "filament/forms", - "version": "v2.16.5", + "version": "v2.16.14", "source": { "type": "git", "url": "https://github.com/filamentphp/forms.git", - "reference": "a9c3f8a0f5c6cefa1190f77ee48ddda98ba95649" + "reference": "037ef411663c4925c490b92bc4ebe6b948d57296" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/forms/zipball/a9c3f8a0f5c6cefa1190f77ee48ddda98ba95649", - "reference": "a9c3f8a0f5c6cefa1190f77ee48ddda98ba95649", + "url": "https://api.github.com/repos/filamentphp/forms/zipball/037ef411663c4925c490b92bc4ebe6b948d57296", + "reference": "037ef411663c4925c490b92bc4ebe6b948d57296", "shasum": "" }, "require": { @@ -875,20 +930,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2022-09-16T14:59:17+00:00" + "time": "2022-09-23T11:39:40+00:00" }, { "name": "filament/notifications", - "version": "v2.16.5", + "version": "v2.16.14", "source": { "type": "git", "url": "https://github.com/filamentphp/notifications.git", - "reference": "8bc1cbfb4aede05113d499677be870d71b87ddf1" + "reference": "559c821e44887058c168e7e883b23267df841e70" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/notifications/zipball/8bc1cbfb4aede05113d499677be870d71b87ddf1", - "reference": "8bc1cbfb4aede05113d499677be870d71b87ddf1", + "url": "https://api.github.com/repos/filamentphp/notifications/zipball/559c821e44887058c168e7e883b23267df841e70", + "reference": "559c821e44887058c168e7e883b23267df841e70", "shasum": "" }, "require": { @@ -925,20 +980,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2022-09-16T10:23:15+00:00" + "time": "2022-09-23T10:20:40+00:00" }, { "name": "filament/support", - "version": "v2.16.5", + "version": "v2.16.14", "source": { "type": "git", "url": "https://github.com/filamentphp/support.git", - "reference": "d4cb0588141371ed8a49aa472ca5c8ea3b732e96" + "reference": "c0cc59bd50d926b9f60cf1ea0762982ffd71cb06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/support/zipball/d4cb0588141371ed8a49aa472ca5c8ea3b732e96", - "reference": "d4cb0588141371ed8a49aa472ca5c8ea3b732e96", + "url": "https://api.github.com/repos/filamentphp/support/zipball/c0cc59bd50d926b9f60cf1ea0762982ffd71cb06", + "reference": "c0cc59bd50d926b9f60cf1ea0762982ffd71cb06", "shasum": "" }, "require": { @@ -975,20 +1030,20 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2022-09-16T10:23:06+00:00" + "time": "2022-09-22T19:57:32+00:00" }, { "name": "filament/tables", - "version": "v2.16.5", + "version": "v2.16.14", "source": { "type": "git", "url": "https://github.com/filamentphp/tables.git", - "reference": "def2615dc4a37dacd736ec3b1aa4041ac01e5e62" + "reference": "9690836dfcf378e907167ab2e9dd19dc483fed8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filamentphp/tables/zipball/def2615dc4a37dacd736ec3b1aa4041ac01e5e62", - "reference": "def2615dc4a37dacd736ec3b1aa4041ac01e5e62", + "url": "https://api.github.com/repos/filamentphp/tables/zipball/9690836dfcf378e907167ab2e9dd19dc483fed8f", + "reference": "9690836dfcf378e907167ab2e9dd19dc483fed8f", "shasum": "" }, "require": { @@ -1031,7 +1086,7 @@ "issues": "https://github.com/filamentphp/filament/issues", "source": "https://github.com/filamentphp/filament" }, - "time": "2022-09-16T10:23:07+00:00" + "time": "2022-09-23T11:39:54+00:00" }, { "name": "fruitcake/php-cors", @@ -1641,16 +1696,16 @@ }, { "name": "laravel/framework", - "version": "v9.30.1", + "version": "v9.31.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "9533f7926f31939f25a620fbbf545318c18c943f" + "reference": "75013d4fffe3b24748d313fbbea53206351214f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/9533f7926f31939f25a620fbbf545318c18c943f", - "reference": "9533f7926f31939f25a620fbbf545318c18c943f", + "url": "https://api.github.com/repos/laravel/framework/zipball/75013d4fffe3b24748d313fbbea53206351214f7", + "reference": "75013d4fffe3b24748d313fbbea53206351214f7", "shasum": "" }, "require": { @@ -1680,6 +1735,7 @@ "symfony/mime": "^6.0", "symfony/process": "^6.0", "symfony/routing": "^6.0", + "symfony/uid": "^6.0", "symfony/var-dumper": "^6.0", "tijsverkoyen/css-to-inline-styles": "^2.2.2", "vlucas/phpdotenv": "^5.4.1", @@ -1743,8 +1799,7 @@ "phpstan/phpstan": "^1.4.7", "phpunit/phpunit": "^9.5.8", "predis/predis": "^1.1.9|^2.0", - "symfony/cache": "^6.0", - "symfony/uid": "^6.0" + "symfony/cache": "^6.0" }, "suggest": { "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", @@ -1779,8 +1834,7 @@ "symfony/http-client": "Required to enable support for the Symfony API mail transports (^6.0).", "symfony/mailgun-mailer": "Required to enable support for the Mailgun mail transport (^6.0).", "symfony/postmark-mailer": "Required to enable support for the Postmark mail transport (^6.0).", - "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0).", - "symfony/uid": "Required to generate ULIDs for Eloquent (^6.0)." + "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0)." }, "type": "library", "extra": { @@ -1824,7 +1878,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-09-15T13:15:47+00:00" + "time": "2022-09-20T13:32:50+00:00" }, { "name": "laravel/sanctum", @@ -2209,16 +2263,16 @@ }, { "name": "league/flysystem", - "version": "3.4.0", + "version": "3.5.2", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "5972d2a966e236674286e3a2281139ce74e4415d" + "reference": "c73c4eb31f2e883b3897ab5591aa2dbc48112433" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/5972d2a966e236674286e3a2281139ce74e4415d", - "reference": "5972d2a966e236674286e3a2281139ce74e4415d", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/c73c4eb31f2e883b3897ab5591aa2dbc48112433", + "reference": "c73c4eb31f2e883b3897ab5591aa2dbc48112433", "shasum": "" }, "require": { @@ -2280,7 +2334,7 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.4.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.5.2" }, "funding": [ { @@ -2296,7 +2350,7 @@ "type": "tidelift" } ], - "time": "2022-09-16T20:57:23+00:00" + "time": "2022-09-23T18:59:16+00:00" }, { "name": "league/mime-type-detection", @@ -4002,16 +4056,16 @@ }, { "name": "spatie/laravel-activitylog", - "version": "4.5.3", + "version": "4.6.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-activitylog.git", - "reference": "feb1a37d649b03711e546807688fbea53469dfc3" + "reference": "7c08e6bd8fbd1cd2b57c0f6acf3708bcafc3f7e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-activitylog/zipball/feb1a37d649b03711e546807688fbea53469dfc3", - "reference": "feb1a37d649b03711e546807688fbea53469dfc3", + "url": "https://api.github.com/repos/spatie/laravel-activitylog/zipball/7c08e6bd8fbd1cd2b57c0f6acf3708bcafc3f7e1", + "reference": "7c08e6bd8fbd1cd2b57c0f6acf3708bcafc3f7e1", "shasum": "" }, "require": { @@ -4077,7 +4131,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-activitylog/issues", - "source": "https://github.com/spatie/laravel-activitylog/tree/4.5.3" + "source": "https://github.com/spatie/laravel-activitylog/tree/4.6.0" }, "funding": [ { @@ -4089,7 +4143,7 @@ "type": "github" } ], - "time": "2022-05-31T10:01:05+00:00" + "time": "2022-09-22T09:31:29+00:00" }, { "name": "spatie/laravel-package-tools", @@ -5670,6 +5724,88 @@ ], "time": "2022-05-24T11:49:31+00:00" }, + { + "name": "symfony/polyfill-uuid", + "version": "v1.26.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-uuid.git", + "reference": "a41886c1c81dc075a09c71fe6db5b9d68c79de23" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/a41886c1c81dc075a09c71fe6db5b9d68c79de23", + "reference": "a41886c1c81dc075a09c71fe6db5b9d68c79de23", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-uuid": "*" + }, + "suggest": { + "ext-uuid": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.26-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Uuid\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for uuid functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.26.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-05-24T11:49:31+00:00" + }, { "name": "symfony/process", "version": "v6.1.3", @@ -6166,6 +6302,80 @@ ], "time": "2022-06-27T17:24:16+00:00" }, + { + "name": "symfony/uid", + "version": "v6.1.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/uid.git", + "reference": "ea2ccf0fdb88c83e626105b68e5bab5c132d812b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/uid/zipball/ea2ccf0fdb88c83e626105b68e5bab5c132d812b", + "reference": "ea2ccf0fdb88c83e626105b68e5bab5c132d812b", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-uuid": "^1.15" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Uid\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Grégoire Pineau", + "email": "lyrixx@lyrixx.info" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to generate and represent UIDs", + "homepage": "https://symfony.com", + "keywords": [ + "UID", + "ulid", + "uuid" + ], + "support": { + "source": "https://github.com/symfony/uid/tree/v6.1.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-07-20T13:46:29+00:00" + }, { "name": "symfony/var-dumper", "version": "v6.1.3", diff --git a/config/filament-avatar.php b/config/filament-avatar.php new file mode 100644 index 00000000..0f37f76c --- /dev/null +++ b/config/filament-avatar.php @@ -0,0 +1,64 @@ + 'ui-avatar', + + /* + |-------------------------------------------------------------------------- + | PROVIDERS + |-------------------------------------------------------------------------- + | + | This value is the definition of the different avatar providers + | + */ + 'providers' => [ + // UI Avatar provider (https://ui-avatars.com/) + 'ui-avatar' => [ + // Class used to generate the user avatar + 'class' => \Devaslanphp\FilamentAvatar\Core\UiAvatarsProvider::class, + + // UI Avatar source url + 'url' => 'https://ui-avatars.com/api/', + + // User's field used to generate avatar + 'name_field' => 'name', + + // Color used in url text color + 'text_color' => 'FFFFFF', + + // Background color used if the 'dynamic_bg_color' flag is false + 'bg_color' => '111827', + + // If 'true' the provider will generate a dynamic 'bg_color' based on user's name + 'dynamic_bg_color' => true, + + // HSL ranges + // You can change them as you like to adapt the dynamic background color + 'hRange' => [0, 360], + 'sRange' => [50, 75], + 'lRange' => [25, 60], + ], + + // Gravatar provider (https://gravatar.com) + 'gravatar' => [ + // Class used to generate the user avatar + 'class' => \Devaslanphp\FilamentAvatar\Core\GravatarProvider::class, + + // Gravatar source url + 'url' => 'https://www.gravatar.com/avatar/', + + // User's field used to generate avatar + 'name_field' => 'email' + ], + ], + +]; diff --git a/config/system.php b/config/system.php index d40ae7e3..bd7807ed 100644 --- a/config/system.php +++ b/config/system.php @@ -24,6 +24,7 @@ | updating them, you can change it as you like | | 'text-color' and 'bg-color' are tailwindcss based css classes + | 'badge-color' uses the colors defined on 'tailwind.config.js' | 'permissions' contains the rights to access "pages" and "functions" | 'pages' contains the pages accessible by the role | -> Same declared in App\View\Components\MainMenu component) @@ -55,6 +56,7 @@ 'title' => 'Administrator', 'text-color' => 'bg-red-50', 'bg-color' => 'text-red-500', + 'badge-color' => 'danger', 'permissions' => [ 'pages' => ['analytics', 'tickets', 'kanban', 'administration'], 'functions' => [ @@ -67,6 +69,7 @@ 'title' => 'Employee', 'text-color' => 'bg-gray-50', 'bg-color' => 'text-gray-500', + 'badge-color' => 'warning', 'permissions' => [ 'pages' => ['analytics', 'tickets', 'kanban'], 'functions' => [ @@ -79,6 +82,7 @@ 'title' => 'Customer', 'text-color' => 'bg-blue-50', 'bg-color' => 'text-blue-500', + 'badge-color' => 'primary', 'permissions' => [ 'pages' => ['analytics', 'tickets', 'kanban'], 'functions' => [ diff --git a/config/tables.php b/config/tables.php new file mode 100644 index 00000000..51bb9eda --- /dev/null +++ b/config/tables.php @@ -0,0 +1,81 @@ + 'M j, Y', + 'date_time_format' => 'M j, Y H:i:s', + 'time_format' => 'H:i:s', + + /* + |-------------------------------------------------------------------------- + | Default Filesystem Disk + |-------------------------------------------------------------------------- + | + | This is the storage disk Filament will use to find media. You may use any + | of the disks defined in the `config/filesystems.php`. + | + */ + + 'default_filesystem_disk' => env('TABLES_FILESYSTEM_DRIVER', 'public'), + + /* + |-------------------------------------------------------------------------- + | Dark mode + |-------------------------------------------------------------------------- + | + | By enabling this setting, your tables will be ready for Tailwind's Dark + | Mode feature. + | + | https://tailwindcss.com/docs/dark-mode + | + */ + + 'dark_mode' => false, + + /* + |-------------------------------------------------------------------------- + | Pagination + |-------------------------------------------------------------------------- + | + | This is the configuration for the pagination of tables. + | + */ + + 'pagination' => [ + 'default_records_per_page' => 10, + 'records_per_page_select_options' => [5, 10, 25, 50, -1], + ], + + /* + |-------------------------------------------------------------------------- + | Layout + |-------------------------------------------------------------------------- + | + | This is the configuration for the general layout of tables. + | + */ + + 'layout' => [ + 'actions' => [ + 'cell' => [ + 'alignment' => 'right', + ], + 'modal' => [ + 'actions' => [ + 'alignment' => 'left', + ], + ], + ], + ], + +]; diff --git a/lang/fr.json b/lang/fr.json index 64566fc2..196af923 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -238,6 +238,8 @@ "Text color": "Couleur de texte", "Background color": "Couleur de fond", "Edit status": "Modifier le statut", + "Edit priority": "Modifier la priorité", + "Edit type": "Modifier le type", "No ticket statuses to show!": "Aucun statuts de ticket à afficher !", "Update user": "Modifier l'utilisateur", "Update status": "Modifier le statut", diff --git a/package-lock.json b/package-lock.json index ea2919a0..56dbd11e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "sass": "^1.54.9" }, "devDependencies": { + "@alpinejs/focus": "^3.10.3", "@awcodes/alpine-floating-ui": "^3.4.0", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/typography": "^0.5.7", @@ -23,6 +24,19 @@ "postcss": "^8.4.16", "tailwindcss": "^3.1.8", "vite": "^3.0.0" + }, + "engines": { + "node": "18.x", + "npm": "7.x" + } + }, + "node_modules/@alpinejs/focus": { + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/@alpinejs/focus/-/focus-3.10.3.tgz", + "integrity": "sha512-Q8hYP42Zdmj4VgrbKUmW2AAeXdQZdRU+NpHl2CRUgvBJTQ8UHTL50Q6ZCGY8P9BTnA+DSO+e8wRf7B4qGtak9g==", + "dev": true, + "dependencies": { + "focus-trap": "^6.6.1" } }, "node_modules/@awcodes/alpine-floating-ui": { @@ -861,6 +875,15 @@ "mini-svg-data-uri": "^1.4.3" } }, + "node_modules/focus-trap": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-6.9.4.tgz", + "integrity": "sha512-v2NTsZe2FF59Y+sDykKY+XjqZ0cPfhq/hikWVL88BqLivnNiEffAsac6rP6H45ff9wG9LL5ToiDqrLEP9GX9mw==", + "dev": true, + "dependencies": { + "tabbable": "^5.3.3" + } + }, "node_modules/follow-redirects": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", @@ -1480,6 +1503,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tabbable": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz", + "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==", + "dev": true + }, "node_modules/tailwindcss": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.8.tgz", @@ -1637,6 +1666,15 @@ } }, "dependencies": { + "@alpinejs/focus": { + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/@alpinejs/focus/-/focus-3.10.3.tgz", + "integrity": "sha512-Q8hYP42Zdmj4VgrbKUmW2AAeXdQZdRU+NpHl2CRUgvBJTQ8UHTL50Q6ZCGY8P9BTnA+DSO+e8wRf7B4qGtak9g==", + "dev": true, + "requires": { + "focus-trap": "^6.6.1" + } + }, "@awcodes/alpine-floating-ui": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/@awcodes/alpine-floating-ui/-/alpine-floating-ui-3.4.0.tgz", @@ -2148,6 +2186,15 @@ "mini-svg-data-uri": "^1.4.3" } }, + "focus-trap": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-6.9.4.tgz", + "integrity": "sha512-v2NTsZe2FF59Y+sDykKY+XjqZ0cPfhq/hikWVL88BqLivnNiEffAsac6rP6H45ff9wG9LL5ToiDqrLEP9GX9mw==", + "dev": true, + "requires": { + "tabbable": "^5.3.3" + } + }, "follow-redirects": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", @@ -2535,6 +2582,12 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "tabbable": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz", + "integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==", + "dev": true + }, "tailwindcss": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.1.8.tgz", diff --git a/package.json b/package.json index eaab2145..a8707604 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "npm": "7.x" }, "devDependencies": { + "@alpinejs/focus": "^3.10.3", "@awcodes/alpine-floating-ui": "^3.4.0", "@tailwindcss/forms": "^0.5.3", "@tailwindcss/typography": "^0.5.7", diff --git a/public/docs/index.html b/public/docs/index.html index df9e4f18..17767fac 100644 --- a/public/docs/index.html +++ b/public/docs/index.html @@ -54,7 +54,7 @@ - v1.3.1 + v1.3.2 @@ -91,6 +91,7 @@