Skip to content

Commit 59606bf

Browse files
Merge branch 'alexjustesen:main' into main
2 parents ef91541 + a758f32 commit 59606bf

File tree

7 files changed

+364
-147
lines changed

7 files changed

+364
-147
lines changed

app/Filament/Pages/ApiTokens.php

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<?php
2+
3+
namespace App\Filament\Pages;
4+
5+
use Carbon\Carbon;
6+
use Filament\Forms\Components\CheckboxList;
7+
use Filament\Forms\Components\DateTimePicker;
8+
use Filament\Forms\Components\TextInput;
9+
use Filament\Forms\Concerns\InteractsWithForms;
10+
use Filament\Forms\Contracts\HasForms;
11+
use Filament\Infolists\Components\Section;
12+
use Filament\Infolists\Components\TextEntry;
13+
use Filament\Infolists\Concerns\InteractsWithInfolists;
14+
use Filament\Infolists\Contracts\HasInfolists;
15+
use Filament\Infolists\Infolist;
16+
use Filament\Pages\Page;
17+
use Filament\Support\Enums\FontFamily;
18+
use Filament\Support\Enums\MaxWidth;
19+
use Filament\Tables\Actions\Action;
20+
use Filament\Tables\Actions\ActionGroup;
21+
use Filament\Tables\Actions\DeleteAction;
22+
use Filament\Tables\Columns\TextColumn;
23+
use Filament\Tables\Concerns\InteractsWithTable;
24+
use Filament\Tables\Contracts\HasTable;
25+
use Filament\Tables\Table;
26+
use Illuminate\Database\Eloquent\Relations\MorphMany;
27+
use Illuminate\Support\Facades\Auth;
28+
use Illuminate\Support\HtmlString;
29+
30+
class ApiTokens extends Page implements HasForms, HasInfolists, HasTable
31+
{
32+
use InteractsWithForms, InteractsWithInfolists, InteractsWithTable;
33+
34+
protected static ?string $navigationIcon = 'tabler-api';
35+
36+
protected static string $view = 'filament.pages.api-tokens';
37+
38+
protected static ?string $title = 'API Tokens';
39+
40+
protected static ?string $navigationGroup = 'Settings';
41+
42+
protected static ?int $navigationSort = 5;
43+
44+
public ?string $token = '';
45+
46+
/**
47+
* NOTE: This page is disabled until the api feature is ready.
48+
*/
49+
public static function canAccess(): bool
50+
{
51+
return false;
52+
}
53+
54+
public function tokenInfolist(Infolist $infolist): Infolist
55+
{
56+
return $infolist
57+
->state([
58+
'token' => $this->token,
59+
])
60+
->schema([
61+
Section::make()
62+
->columns(1)
63+
->schema([
64+
TextEntry::make('token')
65+
->label('API Token')
66+
->formatStateUsing(fn (string $state) => explode('|', $state)[1])
67+
->helperText('Copy and save the token above, this token will not be shown again!')
68+
->color('gray')
69+
->copyable()
70+
->copyableState(fn (string $state) => explode('|', $state)[1])
71+
->fontFamily(FontFamily::Mono),
72+
]),
73+
]);
74+
}
75+
76+
public function table(Table $table): Table
77+
{
78+
return $table
79+
->relationship(fn (): MorphMany => Auth::user()->tokens())
80+
->headerActions([
81+
Action::make('createToken')
82+
->form([
83+
TextInput::make('token_name')
84+
->label('Name')
85+
->maxLength('100')
86+
->required(),
87+
CheckboxList::make('token_abilities')
88+
->label('Abilities')
89+
->options([
90+
'result-read' => 'Read results',
91+
])
92+
->descriptions([
93+
'result-read' => new HtmlString('Allow the token to retrieve result data.'),
94+
])
95+
->required()
96+
->bulkToggleable(),
97+
DateTimePicker::make('token_expires_at')
98+
->label('Expires at')
99+
->nullable(),
100+
])
101+
->action(function (array $data) {
102+
$token = Auth::user()->createToken(
103+
name: $data['token_name'],
104+
abilities: $data['token_abilities'],
105+
expiresAt: $data['token_expires_at'] ? Carbon::parse($data['token_expires_at']) : null,
106+
);
107+
108+
$this->token = $token->plainTextToken;
109+
})
110+
->label('Create API Token')
111+
->modal('createToken')
112+
->modalWidth(MaxWidth::ExtraLarge),
113+
])
114+
->columns([
115+
TextColumn::make('id')
116+
->label('ID')
117+
->sortable(),
118+
TextColumn::make('name')
119+
->searchable(),
120+
TextColumn::make('last_used_at')
121+
->alignEnd()
122+
->dateTime()
123+
->sortable(),
124+
TextColumn::make('expires_at')
125+
->alignEnd()
126+
->dateTime()
127+
->sortable(),
128+
])
129+
->actions([
130+
ActionGroup::make([
131+
DeleteAction::make(),
132+
]),
133+
])
134+
->bulkActions([
135+
// ...
136+
]);
137+
}
138+
}

app/Helpers/Ookla.php

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,22 @@ class Ookla
1212
public static function getErrorMessage(ProcessFailedException $exception): string
1313
{
1414
$messages = explode(PHP_EOL, $exception->getMessage());
15+
$errorMessages = [];
1516

16-
// Extract only the "message" part from each JSON error message
17-
$errorMessages = array_map(function ($message) {
17+
foreach ($messages as $message) {
1818
$decoded = json_decode($message, true);
1919
if (json_last_error() === JSON_ERROR_NONE && isset($decoded['message'])) {
20-
return $decoded['message'];
20+
$errorMessages[] = $decoded['message'];
2121
}
22+
}
2223

23-
// Placeholder for invalid JSON or missing "message"
24-
return 'An unexpected error occurred while running the Ookla CLI.';
25-
}, $messages);
26-
27-
// Filter out empty messages and concatenate
28-
$errorMessage = implode(' | ', array_filter($errorMessages));
24+
// If no valid messages, use the placeholder
25+
if (empty($errorMessages)) {
26+
$errorMessages[] = 'An unexpected error occurred while running the Ookla CLI.';
27+
}
2928

30-
return $errorMessage;
29+
// Remove duplicates and concatenate
30+
return implode(' | ', array_unique($errorMessages));
3131
}
3232

3333
public static function getConfigServers(): ?array

app/Jobs/Ookla/RunSpeedtestJob.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ public function handle(): void
6464
'--accept-gdpr',
6565
'--format=json',
6666
$this->result->server_id ? '--server-id='.$this->result->server_id : null,
67+
config('speedtest.interface') ? '--interface='.config('speedtest.interface') : null,
6768
]);
6869

6970
$process = new Process($command);

composer.json

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,26 @@
2424
"guzzlehttp/guzzle": "^7.9.2",
2525
"influxdata/influxdb-client-php": "^3.6",
2626
"laravel-notification-channels/telegram": "^5.0",
27-
"laravel/framework": "^11.36.1",
27+
"laravel/framework": "^11.37",
2828
"laravel/prompts": "^0.3.2",
2929
"laravel/sanctum": "^4.0.7",
3030
"laravel/tinker": "^2.10.0",
31-
"livewire/livewire": "^3.5.17",
32-
"lorisleiva/laravel-actions": "^2.8.4",
31+
"livewire/livewire": "^3.5.18",
32+
"lorisleiva/laravel-actions": "^2.8.5",
3333
"maennchen/zipstream-php": "^2.4",
34+
"ryangjchandler/blade-tabler-icons": "^2.3",
3435
"spatie/laravel-settings": "^3.4",
3536
"spatie/laravel-webhook-server": "^3.8.2",
3637
"timokoerber/laravel-one-time-operations": "^1.4.4"
3738
},
3839
"require-dev": {
3940
"fakerphp/faker": "^1.24.1",
40-
"laravel/pint": "^1.18.3",
41+
"laravel/pint": "^1.19.0",
4142
"laravel/sail": "^1.39.1",
4243
"laravel/telescope": "^5.2.6",
4344
"mockery/mockery": "^1.6.12",
4445
"nunomaduro/collision": "^8.5.0",
45-
"phpunit/phpunit": "^11.5.1",
46+
"phpunit/phpunit": "^11.5.2",
4647
"spatie/laravel-ignition": "^2.9.0",
4748
"tightenco/duster": "^3.1.0"
4849
},

0 commit comments

Comments
 (0)