Skip to content

Commit 4bfbcec

Browse files
scott graysonscott grayson
authored andcommitted
add missing relation manager
1 parent 8a648e4 commit 4bfbcec

File tree

1 file changed

+134
-22
lines changed

1 file changed

+134
-22
lines changed

src/Resources/RelationManagers/LibraryItemPermissionsRelationManager.php

Lines changed: 134 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
use Filament\Schemas\Schema;
1313
use Filament\Tables;
1414
use Filament\Tables\Table;
15-
use Tapp\FilamentLibrary\Forms\Components\UserSearchSelect;
15+
use Illuminate\Database\Eloquent\Model;
16+
use Illuminate\Support\Facades\Schema as SchemaFacade;
17+
use Tapp\FilamentLibrary\Models\LibraryItemPermission;
18+
use App\Models\User;
1619

1720
class LibraryItemPermissionsRelationManager extends RelationManager
1821
{
@@ -24,66 +27,175 @@ class LibraryItemPermissionsRelationManager extends RelationManager
2427

2528
protected static ?string $pluralModelLabel = 'Permissions';
2629

30+
31+
public static function canAccess(): bool
32+
{
33+
$user = auth()->user();
34+
if (!$user) {
35+
return false;
36+
}
37+
38+
// Admins can always access
39+
if ($user->hasRole('Admin')) {
40+
return true;
41+
}
42+
43+
// For non-admins, check if they have share permission on the current record
44+
$record = static::getOwnerRecord();
45+
if ($record && $record->hasPermission($user, 'share')) {
46+
return true;
47+
}
48+
49+
return false;
50+
}
51+
52+
public static function canViewForRecord(Model $ownerRecord, string $pageClass): bool
53+
{
54+
return $ownerRecord->hasPermission(auth()->user(), 'share');
55+
}
56+
57+
/**
58+
* Get the display name for a user, supporting both 'name' and 'first_name/last_name' fields.
59+
*/
60+
private function getUserDisplayName($user): string
61+
{
62+
if (!$user) {
63+
return 'Unknown User';
64+
}
65+
66+
// Check if user has a name accessor or name field with a value
67+
if ($user->name) {
68+
return $user->name . ' (' . $user->email . ')';
69+
}
70+
71+
// Fall back to first_name/last_name if available
72+
if (SchemaFacade::hasColumn('users', 'first_name') && SchemaFacade::hasColumn('users', 'last_name')) {
73+
$firstName = $user->first_name ?? '';
74+
$lastName = $user->last_name ?? '';
75+
$fullName = trim($firstName . ' ' . $lastName);
76+
77+
if ($fullName) {
78+
return $fullName . ' (' . $user->email . ')';
79+
}
80+
}
81+
82+
// Fall back to email only
83+
return $user->email;
84+
}
85+
2786
public function form(Schema $schema): Schema
2887
{
2988
return $schema
3089
->components([
31-
UserSearchSelect::make('user_id')
90+
Forms\Components\Select::make('user_id')
3291
->label('User')
33-
->required()
3492
->searchable()
35-
->preload(),
93+
->preload()
94+
->getSearchResultsUsing(fn (string $search): array =>
95+
User::where(function ($query) use ($search) {
96+
// Search first_name and last_name fields if they exist
97+
if (SchemaFacade::hasColumn('users', 'first_name') && SchemaFacade::hasColumn('users', 'last_name')) {
98+
$query->orWhere('first_name', 'like', "%{$search}%")
99+
->orWhere('last_name', 'like', "%{$search}%");
100+
}
101+
// Search name field if it exists and first/last don't
102+
elseif (SchemaFacade::hasColumn('users', 'name')) {
103+
$query->orWhere('name', 'like', "%{$search}%");
104+
}
105+
// Always search email
106+
$query->orWhere('email', 'like', "%{$search}%");
107+
})
108+
->limit(50)
109+
->get()
110+
->mapWithKeys(fn ($user) => [
111+
$user->id => $this->getUserDisplayName($user)
112+
])
113+
->toArray()
114+
)
115+
->getOptionLabelUsing(fn ($value): ?string =>
116+
$this->getUserDisplayName(User::find($value))
117+
)
118+
->required(),
119+
36120
Forms\Components\Select::make('role')
37121
->label('Role')
38-
->options(\Tapp\FilamentLibrary\Models\LibraryItemPermission::getRoleOptions())
39-
->required()
40-
->default('viewer'),
122+
->options(LibraryItemPermission::getRoleOptions())
123+
->required(),
41124
]);
42125
}
43126

44127
public function table(Table $table): Table
45128
{
46129
return $table
47-
->recordTitleAttribute('user.name')
130+
->recordTitleAttribute('role')
48131
->columns([
49-
Tables\Columns\TextColumn::make('user.name')
132+
Tables\Columns\TextColumn::make('user')
50133
->label('User')
51-
->searchable()
52-
->sortable(),
134+
->formatStateUsing(fn ($record) => $this->getUserDisplayName($record->user))
135+
->searchable(function ($query, $search) {
136+
return $query->where(function ($query) use ($search) {
137+
// Search first_name and last_name fields if they exist
138+
if (SchemaFacade::hasColumn('users', 'first_name') && SchemaFacade::hasColumn('users', 'last_name')) {
139+
$query->orWhere('first_name', 'like', "%{$search}%")
140+
->orWhere('last_name', 'like', "%{$search}%");
141+
}
142+
// Search name field if it exists and first/last don't
143+
elseif (SchemaFacade::hasColumn('users', 'name')) {
144+
$query->orWhere('name', 'like', "%{$search}%");
145+
}
146+
// Always search email
147+
$query->orWhere('email', 'like', "%{$search}%");
148+
});
149+
}),
150+
53151
Tables\Columns\TextColumn::make('user.email')
54152
->label('Email')
55-
->searchable()
56-
->sortable(),
153+
->searchable(),
154+
57155
Tables\Columns\TextColumn::make('role')
58156
->label('Role')
59157
->badge()
60158
->color(fn (string $state): string => match ($state) {
61-
'viewer' => 'info',
62-
'editor' => 'success',
63-
'owner' => 'warning',
159+
'owner' => 'danger',
160+
'editor' => 'warning',
161+
'viewer' => 'success',
64162
default => 'gray',
65163
}),
164+
66165
Tables\Columns\TextColumn::make('created_at')
67-
->label('Granted')
166+
->label('Added')
68167
->dateTime()
69168
->sortable()
70169
->toggleable(isToggledHiddenByDefault: true),
71170
])
72171
->filters([
73172
Tables\Filters\SelectFilter::make('role')
74-
->options(\Tapp\FilamentLibrary\Models\LibraryItemPermission::getRoleOptions()),
173+
->options(LibraryItemPermission::getRoleOptions()),
75174
])
76175
->headerActions([
77-
CreateAction::make(),
176+
CreateAction::make()
177+
->visible(fn () => $this->ownerRecord->hasPermission(auth()->user(), 'share')),
78178
])
179+
->heading('User Permissions')
180+
->description('Owner: Share and edit. Editor/Viewer: Standard permissions.')
79181
->actions([
80-
EditAction::make(),
81-
DeleteAction::make(),
182+
EditAction::make()
183+
->visible(fn () => $this->ownerRecord->hasPermission(auth()->user(), 'share')),
184+
DeleteAction::make()
185+
->visible(fn () => $this->ownerRecord->hasPermission(auth()->user(), 'share')),
82186
])
83187
->bulkActions([
84188
BulkActionGroup::make([
85-
DeleteBulkAction::make(),
189+
DeleteBulkAction::make()
190+
->visible(fn () => $this->ownerRecord->hasPermission(auth()->user(), 'share')),
86191
]),
192+
])
193+
->emptyStateHeading('No permissions assigned')
194+
->emptyStateDescription('Add users to grant them specific permissions on this item.')
195+
->emptyStateActions([
196+
CreateAction::make()
197+
->label('Add Permission')
198+
->visible(fn () => $this->ownerRecord->hasPermission(auth()->user(), 'share')),
87199
]);
88200
}
89201
}

0 commit comments

Comments
 (0)