Skip to content

Commit c7fc406

Browse files
authored
[Feature] Convert API page to Resource (alexjustesen#2214)
1 parent 8ebbfab commit c7fc406

File tree

4 files changed

+196
-145
lines changed

4 files changed

+196
-145
lines changed

app/Filament/Pages/ApiTokens.php

Lines changed: 0 additions & 134 deletions
This file was deleted.
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
<?php
2+
3+
namespace App\Filament\Resources;
4+
5+
use App\Filament\Resources\ApiTokenResource\Pages;
6+
use Filament\Forms\Components\CheckboxList;
7+
use Filament\Forms\Components\DateTimePicker;
8+
use Filament\Forms\Components\Grid;
9+
use Filament\Forms\Components\TextInput;
10+
use Filament\Forms\Form;
11+
use Filament\Resources\Resource;
12+
use Filament\Tables\Actions\ActionGroup;
13+
use Filament\Tables\Actions\DeleteAction;
14+
use Filament\Tables\Actions\DeleteBulkAction;
15+
use Filament\Tables\Actions\EditAction;
16+
use Filament\Tables\Columns\TextColumn;
17+
use Filament\Tables\Filters\SelectFilter;
18+
use Filament\Tables\Filters\TernaryFilter;
19+
use Filament\Tables\Table;
20+
use Illuminate\Database\Eloquent\Builder;
21+
use Illuminate\Support\Facades\Auth;
22+
use Laravel\Sanctum\PersonalAccessToken;
23+
24+
class ApiTokenResource extends Resource
25+
{
26+
protected static ?string $model = PersonalAccessToken::class;
27+
28+
protected static ?string $navigationIcon = 'tabler-api';
29+
30+
protected static ?string $navigationGroup = 'Settings';
31+
32+
protected static ?string $label = 'API Token';
33+
34+
protected static ?string $pluralLabel = 'API Tokens';
35+
36+
public static function getTokenFormSchema(): array
37+
{
38+
return [
39+
Grid::make()
40+
->schema([
41+
TextInput::make('name')
42+
->label('Name')
43+
->unique(ignoreRecord: true)
44+
->maxLength(100)
45+
->required(),
46+
CheckboxList::make('abilities')
47+
->label('Abilities')
48+
->options([
49+
'results:read' => 'Read results',
50+
'speedtests:run' => 'Run speedtest',
51+
'ookla:list-servers' => 'List servers',
52+
])
53+
->required()
54+
->bulkToggleable()
55+
->descriptions([
56+
'results:read' => 'Allow this token to read results.',
57+
'speedtests:run' => 'Allow this token to run speedtests.',
58+
'ookla:list-servers' => 'Allow this token to list servers.',
59+
]),
60+
DateTimePicker::make('expires_at')
61+
->label('Expires at')
62+
->nullable()
63+
->native(false)
64+
->helperText('Leave empty for no expiration'),
65+
])
66+
->columns([
67+
'lg' => 1,
68+
]),
69+
];
70+
}
71+
72+
public static function form(Form $form): Form
73+
{
74+
return $form->schema(static::getTokenFormSchema());
75+
}
76+
77+
public static function table(Table $table): Table
78+
{
79+
return $table
80+
->query(PersonalAccessToken::query()->where('tokenable_id', Auth::id()))
81+
->columns([
82+
TextColumn::make('name')->searchable(),
83+
TextColumn::make('abilities')->badge(),
84+
TextColumn::make('created_at')
85+
->dateTime(config('app.datetime_format'))
86+
->timezone(config('app.display_timezone'))
87+
->toggleable()
88+
->sortable()
89+
->alignEnd(),
90+
TextColumn::make('last_used_at')
91+
->dateTime(config('app.datetime_format'))
92+
->timezone(config('app.display_timezone'))
93+
->toggleable()
94+
->toggledHiddenByDefault()
95+
->sortable()
96+
->alignEnd(),
97+
TextColumn::make('expires_at')
98+
->dateTime(config('app.datetime_format'))
99+
->timezone(config('app.display_timezone'))
100+
->toggleable()
101+
->sortable()
102+
->alignEnd(),
103+
])
104+
->filters([
105+
TernaryFilter::make('expired')
106+
->label('Token Status')
107+
->placeholder('All tokens')
108+
->falseLabel('Active tokens')
109+
->trueLabel('Expired tokens')
110+
->native(false)
111+
->queries(
112+
true: fn (Builder $query) => $query
113+
->where('expires_at', '<=', now()),
114+
115+
false: fn (Builder $query) => $query
116+
->where(function (Builder $q) {
117+
$q->whereNull('expires_at')
118+
->orWhere('expires_at', '>', now());
119+
}),
120+
121+
blank: fn (Builder $query) => $query,
122+
),
123+
SelectFilter::make('abilities')
124+
->label('Abilities')
125+
->multiple()
126+
->options([
127+
'results:read' => 'Read results',
128+
'speedtests:run' => 'Run speedtest',
129+
'ookla:list-servers' => 'List servers',
130+
])
131+
->query(function (Builder $query, array $data): Builder {
132+
foreach ($data['values'] ?? [] as $value) {
133+
$query->whereJsonContains('abilities', $value);
134+
}
135+
136+
return $query;
137+
}),
138+
])
139+
->actions([
140+
ActionGroup::make([
141+
EditAction::make()
142+
->disabled(fn ($record) => $record->expires_at !== null && $record->expires_at->isPast())
143+
->modalWidth('xl'),
144+
DeleteAction::make(),
145+
]),
146+
])
147+
->bulkActions([
148+
DeleteBulkAction::make(),
149+
]);
150+
}
151+
152+
public static function getPages(): array
153+
{
154+
return [
155+
'index' => Pages\ListApiTokens::route('/'),
156+
];
157+
}
158+
}
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\ApiTokenResource\Pages;
4+
5+
use App\Filament\Resources\ApiTokenResource;
6+
use Carbon\Carbon;
7+
use Filament\Actions\Action;
8+
use Filament\Notifications\Notification;
9+
use Filament\Resources\Pages\ListRecords;
10+
11+
class ListApiTokens extends ListRecords
12+
{
13+
protected static string $resource = ApiTokenResource::class;
14+
15+
protected function getHeaderActions(): array
16+
{
17+
return [
18+
Action::make('createToken')
19+
->label('Create API Token')
20+
->form(ApiTokenResource::getTokenFormSchema())
21+
->action(function (array $data): void {
22+
$token = auth()->user()->createToken(
23+
$data['name'],
24+
$data['abilities'],
25+
$data['expires_at'] ? Carbon::parse($data['expires_at']) : null
26+
);
27+
28+
Notification::make()
29+
->title('Token Created')
30+
->body('Your token: `'.explode('|', $token->plainTextToken)[1].'`')
31+
->success()
32+
->persistent()
33+
->send();
34+
})
35+
->modalWidth('xl'),
36+
];
37+
}
38+
}

resources/views/filament/pages/api-tokens.blade.php

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)