Skip to content

Commit 26833b1

Browse files
authored
Filament improvements (#45)
* Move Filament form and table definitions into models * Create Filament resource for Organisation * Create Filament relationship for User organisations * Update Organisation.php * Update User.php * Install `althinect/filament-spatie-roles-permissions` for managing roles and permissions via Filament * Update User.php * Update User.php * Move Filament form and table definitions to stop affecting code coverage
1 parent 6c72404 commit 26833b1

File tree

12 files changed

+375
-56
lines changed

12 files changed

+375
-56
lines changed
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
3+
namespace App\Filament\Resources;
4+
5+
use App\Filament\Resources\OrganisationResource\Pages;
6+
use App\Filament\Resources\OrganisationResource\RelationManagers\UsersRelationManager;
7+
use App\Models\Organisation;
8+
use App\Models\User;
9+
use Filament\Forms;
10+
use Filament\Forms\Form;
11+
use Filament\Resources\Resource;
12+
use Filament\Tables;
13+
use Filament\Tables\Table;
14+
15+
class OrganisationResource extends Resource
16+
{
17+
protected static ?string $model = Organisation::class;
18+
19+
protected static ?string $navigationIcon = 'heroicon-o-building-office';
20+
21+
public static function form(Form $form): Form
22+
{
23+
return $form
24+
->schema(self::formSchema());
25+
}
26+
27+
public static function table(Table $table): Table
28+
{
29+
return $table
30+
->columns(self::tableSchema())
31+
->actions([
32+
Tables\Actions\EditAction::make(),
33+
])
34+
->bulkActions([
35+
Tables\Actions\BulkActionGroup::make([
36+
Tables\Actions\DeleteBulkAction::make(),
37+
]),
38+
]);
39+
}
40+
41+
public static function getRelations(): array
42+
{
43+
return [
44+
UsersRelationManager::class,
45+
];
46+
}
47+
48+
public static function getPages(): array
49+
{
50+
return [
51+
'index' => Pages\ListOrganisations::route('/'),
52+
'create' => Pages\CreateOrganisation::route('/create'),
53+
'edit' => Pages\EditOrganisation::route('/{record}/edit'),
54+
];
55+
}
56+
57+
public static function formSchema()
58+
{
59+
return [
60+
Forms\Components\TextInput::make('name')
61+
->required()
62+
->maxLength(255),
63+
64+
Forms\Components\Select::make('user_id')
65+
->label('Owner')
66+
->required()
67+
->options(User::all()->pluck('full_name', 'id')->toArray())
68+
->default(fn (): int => \auth()->id() ?: null),
69+
];
70+
}
71+
72+
public static function tableSchema()
73+
{
74+
return [
75+
Tables\Columns\TextColumn::make('name')
76+
->sortable()
77+
->searchable(),
78+
79+
Tables\Columns\TextColumn::make('user_id')
80+
->label('Owner')
81+
->numeric()
82+
->sortable()
83+
->getStateUsing(fn (Organisation $organisation): string => $organisation->user->full_name),
84+
85+
Tables\Columns\TextColumn::make('users')
86+
->numeric()
87+
->sortable()
88+
->getStateUsing(fn (Organisation $organisation): int => $organisation->users->count()),
89+
90+
Tables\Columns\TextColumn::make('created_at')
91+
->dateTime()
92+
->sortable()
93+
->toggleable(isToggledHiddenByDefault: true),
94+
95+
Tables\Columns\TextColumn::make('updated_at')
96+
->dateTime()
97+
->sortable()
98+
->toggleable(isToggledHiddenByDefault: true),
99+
];
100+
}
101+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace App\Filament\Resources\OrganisationResource\Pages;
4+
5+
use App\Filament\Resources\OrganisationResource;
6+
use Filament\Resources\Pages\CreateRecord;
7+
8+
class CreateOrganisation extends CreateRecord
9+
{
10+
protected static string $resource = OrganisationResource::class;
11+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace App\Filament\Resources\OrganisationResource\Pages;
4+
5+
use App\Filament\Resources\OrganisationResource;
6+
use Filament\Actions;
7+
use Filament\Resources\Pages\EditRecord;
8+
9+
class EditOrganisation extends EditRecord
10+
{
11+
protected static string $resource = OrganisationResource::class;
12+
13+
protected function getHeaderActions(): array
14+
{
15+
return [
16+
Actions\DeleteAction::make(),
17+
];
18+
}
19+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace App\Filament\Resources\OrganisationResource\Pages;
4+
5+
use App\Filament\Resources\OrganisationResource;
6+
use Filament\Actions;
7+
use Filament\Resources\Pages\ListRecords;
8+
9+
class ListOrganisations extends ListRecords
10+
{
11+
protected static string $resource = OrganisationResource::class;
12+
13+
protected function getHeaderActions(): array
14+
{
15+
return [
16+
Actions\CreateAction::make(),
17+
];
18+
}
19+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
namespace App\Filament\Resources\OrganisationResource\RelationManagers;
4+
5+
use App\Filament\Resources\UserResource;
6+
use App\Models\User;
7+
use Filament\Forms\Form;
8+
use Filament\Resources\RelationManagers\RelationManager;
9+
use Filament\Tables;
10+
use Filament\Tables\Table;
11+
12+
class UsersRelationManager extends RelationManager
13+
{
14+
protected static string $relationship = 'users';
15+
16+
public function form(Form $form): Form
17+
{
18+
return $form
19+
->schema(User::filamentForm());
20+
}
21+
22+
public function table(Table $table): Table
23+
{
24+
return $table
25+
->recordTitle(fn (User $record): string => $record->full_name)
26+
->columns(UserResource::tableSchema())
27+
->headerActions([
28+
Tables\Actions\AttachAction::make()
29+
->preloadRecordSelect(),
30+
])
31+
->actions([
32+
Tables\Actions\DetachAction::make(),
33+
])
34+
->bulkActions([
35+
Tables\Actions\DetachBulkAction::make(),
36+
]);
37+
}
38+
}

app/Filament/Resources/UserResource.php

Lines changed: 73 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace App\Filament\Resources;
44

55
use App\Filament\Resources\UserResource\Pages;
6+
use App\Filament\Resources\UserResource\RelationManagers\OrganisationsRelationManager;
67
use App\Models\User;
78
use Filament\Forms;
89
use Filament\Forms\Form;
@@ -19,61 +20,13 @@ class UserResource extends Resource
1920
public static function form(Form $form): Form
2021
{
2122
return $form
22-
->schema([
23-
Forms\Components\TextInput::make('first_name')
24-
->autofocus()
25-
->required()
26-
->maxLength(255),
27-
28-
Forms\Components\TextInput::make('last_name')
29-
->required()
30-
->maxLength(255),
31-
32-
Forms\Components\TextInput::make('email')
33-
->required()
34-
->email()
35-
->maxLength(255),
36-
37-
Forms\Components\TextInput::make('password')
38-
->password()
39-
->maxLength(255),
40-
41-
Forms\Components\DateTimePicker::make('email_verified_at'),
42-
]);
23+
->schema(self::formSchema());
4324
}
4425

4526
public static function table(Table $table): Table
4627
{
4728
return $table
48-
->columns([
49-
Tables\Columns\TextColumn::make('name')
50-
->getStateUsing(fn ($record) => $record->fullName)
51-
->searchable()
52-
->sortable(),
53-
54-
Tables\Columns\TextColumn::make('email')
55-
->searchable()
56-
->sortable(),
57-
58-
Tables\Columns\IconColumn::make('email_verified')
59-
->getStateUsing(fn ($record) => $record->email_verified_at)
60-
->boolean()
61-
->sortable(),
62-
63-
Tables\Columns\TextColumn::make('roles')
64-
->getStateUsing(fn ($record) => $record->roles->pluck('name')->join(', '))
65-
->searchable()
66-
->sortable(),
67-
68-
Tables\Columns\TextColumn::make('created_at')
69-
->sortable(),
70-
71-
Tables\Columns\TextColumn::make('updated_at')
72-
->sortable(),
73-
])
74-
->filters([
75-
//
76-
])
29+
->columns(self::tableSchema())
7730
->actions([
7831
Tables\Actions\EditAction::make(),
7932
])
@@ -87,7 +40,7 @@ public static function table(Table $table): Table
8740
public static function getRelations(): array
8841
{
8942
return [
90-
//
43+
OrganisationsRelationManager::class,
9144
];
9245
}
9346

@@ -99,4 +52,73 @@ public static function getPages(): array
9952
'edit' => Pages\EditUser::route('/{record}/edit'),
10053
];
10154
}
55+
56+
public static function formSchema()
57+
{
58+
return [
59+
Forms\Components\TextInput::make('first_name')
60+
->autofocus()
61+
->required()
62+
->maxLength(255),
63+
64+
Forms\Components\TextInput::make('last_name')
65+
->required()
66+
->maxLength(255),
67+
68+
Forms\Components\TextInput::make('email')
69+
->required()
70+
->email()
71+
->maxLength(255),
72+
73+
Forms\Components\TextInput::make('password')
74+
->password()
75+
->maxLength(255),
76+
77+
Forms\Components\DateTimePicker::make('email_verified_at'),
78+
79+
Forms\Components\Select::make('roles')
80+
->preload()
81+
->multiple()
82+
->relationship('roles', 'name'),
83+
];
84+
}
85+
86+
public static function tableSchema()
87+
{
88+
return [
89+
Tables\Columns\TextColumn::make('name')
90+
->getStateUsing(fn ($record) => $record->fullName)
91+
->searchable()
92+
->sortable(),
93+
94+
Tables\Columns\TextColumn::make('email')
95+
->searchable()
96+
->sortable(),
97+
98+
Tables\Columns\IconColumn::make('email_verified')
99+
->getStateUsing(fn ($record) => $record->email_verified_at)
100+
->boolean()
101+
->sortable(),
102+
103+
Tables\Columns\TextColumn::make('organisations')
104+
->numeric()
105+
->sortable()
106+
->getStateUsing(fn (User $user): int => $user->organisations->count()),
107+
108+
Tables\Columns\TextColumn::make('roles')
109+
->getStateUsing(fn ($record) => $record->roles->pluck('name')->join(', '))
110+
->searchable()
111+
->sortable(),
112+
113+
Tables\Columns\TextColumn::make('created_at')
114+
->dateTime()
115+
->sortable()
116+
->toggleable(isToggledHiddenByDefault: true),
117+
118+
Tables\Columns\TextColumn::make('updated_at')
119+
->dateTime()
120+
->sortable()
121+
->toggleable(isToggledHiddenByDefault: true),
122+
];
123+
}
102124
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
namespace App\Filament\Resources\UserResource\RelationManagers;
4+
5+
use App\Filament\Resources\OrganisationResource;
6+
use Filament\Forms;
7+
use Filament\Forms\Form;
8+
use Filament\Resources\RelationManagers\RelationManager;
9+
use Filament\Tables;
10+
use Filament\Tables\Table;
11+
12+
class OrganisationsRelationManager extends RelationManager
13+
{
14+
protected static string $relationship = 'organisations';
15+
16+
public function form(Form $form): Form
17+
{
18+
return $form
19+
->schema([
20+
Forms\Components\TextInput::make('id')
21+
->required()
22+
->maxLength(255),
23+
]);
24+
}
25+
26+
public function table(Table $table): Table
27+
{
28+
return $table
29+
->recordTitleAttribute('name')
30+
->columns(OrganisationResource::tableSchema())
31+
->headerActions([
32+
Tables\Actions\AttachAction::make()
33+
->preloadRecordSelect(),
34+
])
35+
->actions([
36+
Tables\Actions\DetachAction::make(),
37+
])
38+
->bulkActions([
39+
Tables\Actions\DetachBulkAction::make(),
40+
]);
41+
}
42+
}

0 commit comments

Comments
 (0)