From a9e4022bf9f79b3044c458ac8123ec1bb4cb3703 Mon Sep 17 00:00:00 2001 From: EL OUFIR Hatim Date: Fri, 23 Sep 2022 22:24:07 +0100 Subject: [PATCH 1/7] Filament tables integration: Projects --- app/Http/Livewire/Projects.php | 115 ++++--- app/Models/User.php | 14 +- app/Tables/Columns/UserColumn.php | 10 + composer.json | 1 + composer.lock | 314 +++++++++++++++--- config/filament-avatar.php | 64 ++++ config/tables.php | 81 +++++ package-lock.json | 53 +++ package.json | 1 + resources/views/livewire/projects.blade.php | 87 +---- .../tables/columns/user-column.blade.php | 7 + 11 files changed, 558 insertions(+), 189 deletions(-) create mode 100644 app/Tables/Columns/UserColumn.php create mode 100644 config/filament-avatar.php create mode 100644 config/tables.php create mode 100644 resources/views/tables/columns/user-column.blade.php diff --git a/app/Http/Livewire/Projects.php b/app/Http/Livewire/Projects.php index 2189494c..ce5ec1c5 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,69 @@ 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 */ - public function search(): void + protected function getTableActions(): array { - $data = $this->form->getState(); - $this->search = $data['search'] ?? null; + return [ + Action::make('edit') + ->icon('heroicon-o-pencil') + ->link() + ->label(__('Edit project')) + ->action(fn(Project $record) => $this->updateProject($record->id)) + ]; } /** @@ -115,8 +150,8 @@ public function cancelProject() * * @return void */ - public function projectSaved() { - $this->search(); + public function projectSaved() + { $this->cancelProject(); } @@ -125,17 +160,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 +192,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..ea2b20dc 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'); 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 @@ +=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/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/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/resources/views/livewire/projects.blade.php b/resources/views/livewire/projects.blade.php index 37f6d462..8f9abbbc 100644 --- a/resources/views/livewire/projects.blade.php +++ b/resources/views/livewire/projects.blade.php @@ -46,93 +46,8 @@ @endif
-
-
- {{ $this->form }} - -
-
- - - - - - - - - - - - - @if($projects->count()) - @foreach($projects as $project) - - - - - - - - - @endforeach - @else - - - - @endif - -
- @lang('Project name') - - @lang('Description') - - @lang('Owner') - - @lang('Tickets') - - @lang('Created at') - - @lang('Actions') -
-
- - {{ $project->name }} -
-
- {{ Str::limit(htmlspecialchars(strip_tags($project->description)), 50) }} - - -
-
{{ $project->owner->name }}
-
{{ $project->owner->email }}
-
-
- {{ $project->tickets()->count() }} @lang($project->tickets()->count() > 1 ? 'Tickets' : 'Ticket') - -
- {{ $project->created_at->diffForHumans() }} - {{ $project->created_at->format(__('Y-m-d g:i A')) }} -
-
- @if(has_all_permissions(auth()->user(), 'update-all-projects') || (has_all_permissions(auth()->user(), 'update-own-projects') && $project->owner_id === auth()->user()->id)) - - @endif -
- @lang('No projects to show!') -
-
-
- {{ $projects->links('pagination::tailwind') }} + {{ $this->table }}
-
-
- {{ $this->form }} - -
-
- - - - - - - - - - - - @foreach($users as $user) - - - - - - - - @endforeach - -
- @lang('Full name') - - @lang('Role') - - @lang('Account activated') - - @lang('Created at') - - @lang('Actions') -
- -
-
{{ $user->name }}
-
{{ $user->email }}
-
-
- - - @if($user->register_token) -
- - -
- @else - - @endif -
-
- {{ $user->created_at->diffForHumans() }} - {{ $user->created_at->format(__('Y-m-d g:i A')) }} -
-
- @if($user->id !== auth()->user()->id) - - @endif -
-
-
- {{ $users->links('pagination::tailwind') }} +
+ {{ $this->table }} +
-
-
- {{ $this->form }} - -
-
- - - - - - - - - - - @if($statuses->count()) - @foreach($statuses as $status) - - - - - - - @endforeach - @else - - - - @endif - -
- @lang('Title') - - @lang('Default status') - - @lang('Created at') - - @lang('Actions') -
- {{ $status->title }} - - - -
- {{ $status->created_at->diffForHumans() }} - {{ $status->created_at->format(__('Y-m-d g:i A')) }} -
-
- -
- @lang('No ticket statuses to show!') -
-
-
- {{ $statuses->links('pagination::tailwind') }} + {{ $this->table }}
From 215b808db46e669fc3c52239f8bb931584f67983 Mon Sep 17 00:00:00 2001 From: EL OUFIR Hatim Date: Fri, 23 Sep 2022 22:54:40 +0100 Subject: [PATCH 5/7] Filament tables integration: Ticket types --- .../Livewire/Administration/TicketTypes.php | 98 +++++++++++++------ lang/fr.json | 2 + .../administration/ticket-types.blade.php | 60 +----------- 3 files changed, 70 insertions(+), 90 deletions(-) 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/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/resources/views/livewire/administration/ticket-types.blade.php b/resources/views/livewire/administration/ticket-types.blade.php index bbe1db10..3195299f 100644 --- a/resources/views/livewire/administration/ticket-types.blade.php +++ b/resources/views/livewire/administration/ticket-types.blade.php @@ -20,66 +20,8 @@
-
-
- {{ $this->form }} - -
-
- - - - - - - - - - @if($types->count()) - @foreach($types as $type) - - - - - - @endforeach - @else - - - - @endif - -
- @lang('Title') - - @lang('Created at') - - @lang('Actions') -
- - {{ $type->title }} - - -
- {{ $type->created_at->diffForHumans() }} - {{ $type->created_at->format(__('Y-m-d g:i A')) }} -
-
- -
- @lang('No ticket types to show!') -
-
-
- {{ $types->links('pagination::tailwind') }} + {{ $this->table }}
From 7e36ac4e45d04203bc2fec3eb1abf32c49847522 Mon Sep 17 00:00:00 2001 From: EL OUFIR Hatim Date: Fri, 23 Sep 2022 22:56:46 +0100 Subject: [PATCH 6/7] Filament tables integration: Ticket priorities --- .../Administration/TicketPriorities.php | 106 ++++++++++++------ .../ticket-priorities.blade.php | 60 +--------- 2 files changed, 70 insertions(+), 96 deletions(-) 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/resources/views/livewire/administration/ticket-priorities.blade.php b/resources/views/livewire/administration/ticket-priorities.blade.php index 36fa972f..eab76ef8 100644 --- a/resources/views/livewire/administration/ticket-priorities.blade.php +++ b/resources/views/livewire/administration/ticket-priorities.blade.php @@ -20,66 +20,8 @@
-
-
- {{ $this->form }} - -
-
- - - - - - - - - - @if($priorities->count()) - @foreach($priorities as $priority) - - - - - - @endforeach - @else - - - - @endif - -
- @lang('Title') - - @lang('Created at') - - @lang('Actions') -
- - {{ $priority->title }} - - -
- {{ $priority->created_at->diffForHumans() }} - {{ $priority->created_at->format(__('Y-m-d g:i A')) }} -
-
- -
- @lang('No ticket priorities to show!') -
-
-
- {{ $priorities->links('pagination::tailwind') }} + {{ $this->table }}
From cb13ccb8327a84b4fd49b92b004b1f073e1f20c5 Mon Sep 17 00:00:00 2001 From: EL OUFIR Hatim Date: Fri, 23 Sep 2022 22:57:37 +0100 Subject: [PATCH 7/7] Update docs --- public/docs/index.html | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/public/docs/index.html b/public/docs/index.html index 6a6b05fb..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 @@