diff --git a/app/Filament/Exports/ResultExporter.php b/app/Filament/Exports/ResultExporter.php index ab844ec99..ff4438586 100644 --- a/app/Filament/Exports/ResultExporter.php +++ b/app/Filament/Exports/ResultExporter.php @@ -83,6 +83,16 @@ public static function getColumns(): array return $record->ping_jitter; }) ->enabledByDefault(false), + ExportColumn::make('ping_low') + ->state(function (Result $record): ?string { + return $record->ping_low; + }) + ->enabledByDefault(false), + ExportColumn::make('ping_high') + ->state(function (Result $record): ?string { + return $record->ping_high; + }) + ->enabledByDefault(false), ExportColumn::make('upload_latency_high') ->state(function (Result $record): ?string { return $record->upload_latency_high; diff --git a/app/Filament/Resources/ResultResource.php b/app/Filament/Resources/ResultResource.php index 9e768b1bf..e4230f5a1 100644 --- a/app/Filament/Resources/ResultResource.php +++ b/app/Filament/Resources/ResultResource.php @@ -29,125 +29,108 @@ class ResultResource extends Resource public static function form(Form $form): Form { - return $form - ->schema([ - Forms\Components\Grid::make([ - 'default' => 2, - 'md' => 3, - ])->schema([ - Forms\Components\Grid::make([ - 'default' => 2, - 'md' => 3, - ]) + return $form->schema([ + Forms\Components\Grid::make(['default' => 2, 'md' => 3])->schema([ + Forms\Components\Grid::make()->schema([ + Forms\Components\Section::make('Result Overview')->schema([ + Forms\Components\TextInput::make('id') + ->label('ID'), + Forms\Components\TextInput::make('created_at') + ->label('Created') + ->afterStateHydrated(function (TextInput $component, $state) { + $component->state(Carbon::parse($state) + ->timezone(config('app.display_timezone')) + ->format(config('app.datetime_format'))); + }), + Forms\Components\TextInput::make('download') + ->label('Download') + ->afterStateHydrated(fn ($component, Result $record) => $component->state(! blank($record->download) ? Number::toBitRate(bits: $record->download_bits, precision: 2) : '')), + Forms\Components\TextInput::make('upload') + ->label('Upload') + ->afterStateHydrated(fn ($component, Result $record) => $component->state(! blank($record->upload) ? Number::toBitRate(bits: $record->upload_bits, precision: 2) : '')), + Forms\Components\TextInput::make('ping') + ->label('Ping') + ->formatStateUsing(fn ($state) => number_format((float) $state, 0, '.', '').' ms'), + Forms\Components\TextInput::make('data.packetLoss') + ->label('Packet Loss') + ->formatStateUsing(fn ($state) => number_format((float) $state, 2, '.', '').' %'), + ])->columns(2), + + Forms\Components\Section::make('Download Latency') ->schema([ - Forms\Components\TextInput::make('id') - ->label('ID'), - Forms\Components\TextInput::make('created_at') - ->label('Created') - ->afterStateHydrated(function (TextInput $component, $state) { - $component->state(Carbon::parse($state)->timezone(config('app.display_timezone'))->format(config('app.datetime_format'))); - }) - ->columnSpan(2), - Forms\Components\TextInput::make('download') - ->label('Download') - ->afterStateHydrated(function (TextInput $component, Result $record) { - $component->state(! blank($record->download) ? Number::toBitRate(bits: $record->download_bits, precision: 2) : ''); - }), - Forms\Components\TextInput::make('upload') - ->label('Upload') - ->afterStateHydrated(function (TextInput $component, Result $record) { - $component->state(! blank($record->upload) ? Number::toBitRate(bits: $record->upload_bits, precision: 2) : ''); - }), - Forms\Components\TextInput::make('ping') - ->label('Ping') - ->formatStateUsing(function ($state) { - return number_format((float) $state, 0, '.', '').' ms'; - }), - Forms\Components\TextInput::make('data.download.latency.jitter') - ->label('Download Jitter (ms)') - ->formatStateUsing(function ($state) { - return number_format((float) $state, 0, '.', '').' ms'; - }), - Forms\Components\TextInput::make('data.download.latency.high') - ->label('Download Latency High') - ->formatStateUsing(function ($state) { - return number_format((float) $state, 0, '.', '').' ms'; - }), - Forms\Components\TextInput::make('data.download.latency.low') - ->label('Download Latency low') - ->formatStateUsing(function ($state) { - return number_format((float) $state, 0, '.', '').' ms'; - }), - Forms\Components\TextInput::make('data.download.latency.iqm') - ->label('Download Latency iqm') - ->formatStateUsing(function ($state) { - return number_format((float) $state, 0, '.', '').' ms'; - }), - Forms\Components\TextInput::make('data.upload.latency.jitter') - ->label('Upload Jitter') - ->formatStateUsing(function ($state) { - return number_format((float) $state, 0, '.', '').' ms'; - }), - Forms\Components\TextInput::make('data.upload.latency.high') - ->label('Upload Latency High') - ->formatStateUsing(function ($state) { - return number_format((float) $state, 0, '.', '').' ms'; - }), - Forms\Components\TextInput::make('data.upload.latency.low') - ->label('Upload Latency low') - ->formatStateUsing(function ($state) { - return number_format((float) $state, 0, '.', '').' ms'; - }), - Forms\Components\TextInput::make('data.upload.latency.iqm') - ->label('Upload Latency iqm') - ->formatStateUsing(function ($state) { - return number_format((float) $state, 0, '.', '').' ms'; - }), - Forms\Components\TextInput::make('data.ping.jitter') - ->label('Ping Jitter') - ->formatStateUsing(function ($state) { - return number_format((float) $state, 0, '.', '').' ms'; - }), - Forms\Components\TextInput::make('data.packetLoss') - ->label('Packet Loss') - ->formatStateUsing(function ($state) { - return number_format((float) $state, 2, '.', '').' %'; - }), - Forms\Components\Textarea::make('data.message') - ->label('Message') - ->hint(new HtmlString('🔗Error Messages')) - ->columnSpanFull(), + Forms\Components\TextInput::make('data.download.latency.jitter')->label('Jitter') + ->formatStateUsing(fn ($state) => number_format((float) $state, 0, '.', '').' ms'), + Forms\Components\TextInput::make('data.download.latency.high')->label('High') + ->formatStateUsing(fn ($state) => number_format((float) $state, 0, '.', '').' ms'), + Forms\Components\TextInput::make('data.download.latency.low')->label('Low') + ->formatStateUsing(fn ($state) => number_format((float) $state, 0, '.', '').' ms'), + Forms\Components\TextInput::make('data.download.latency.iqm')->label('IQM') + ->formatStateUsing(fn ($state) => number_format((float) $state, 0, '.', '').' ms'), ]) - ->columnSpan(2), - Forms\Components\Section::make() + ->columns(2) + ->collapsed(), + + Forms\Components\Section::make('Upload Latency') ->schema([ - Forms\Components\Placeholder::make('service') - ->content(fn (Result $result): string => $result->service->getLabel()), - Forms\Components\Placeholder::make('server_name') - ->content(fn (Result $result): ?string => $result->server_name), - Forms\Components\Placeholder::make('server_id') - ->label('Server ID') - ->content(fn (Result $result): ?string => $result->server_id), - Forms\Components\Placeholder::make('isp') - ->label('ISP') - ->content(fn (Result $result): ?string => $result->isp), - Forms\Components\Placeholder::make('server_location') - ->label('Server Location') - ->content(fn (Result $result): ?string => $result->server_location), - Forms\Components\Placeholder::make('server_host') - ->content(fn (Result $result): ?string => $result->server_host), - Forms\Components\Placeholder::make('comment') - ->content(fn (Result $result): ?string => $result->comments), - Forms\Components\Checkbox::make('scheduled'), - Forms\Components\Checkbox::make('healthy'), + Forms\Components\TextInput::make('data.upload.latency.jitter')->label('Jitter') + ->formatStateUsing(fn ($state) => number_format((float) $state, 0, '.', '').' ms'), + Forms\Components\TextInput::make('data.upload.latency.high')->label('High') + ->formatStateUsing(fn ($state) => number_format((float) $state, 0, '.', '').' ms'), + Forms\Components\TextInput::make('data.upload.latency.low')->label('Low') + ->formatStateUsing(fn ($state) => number_format((float) $state, 0, '.', '').' ms'), + Forms\Components\TextInput::make('data.upload.latency.iqm')->label('IQM') + ->formatStateUsing(fn ($state) => number_format((float) $state, 0, '.', '').' ms'), ]) - ->columns(1) - ->columnSpan([ - 'default' => 2, - 'md' => 1, - ]), + ->columns(2) + ->collapsed(), + + Forms\Components\Section::make('Ping Details') + ->schema([ + Forms\Components\TextInput::make('data.ping.jitter')->label('Jitter') + ->formatStateUsing(fn ($state) => number_format((float) $state, 0, '.', '').' ms'), + Forms\Components\TextInput::make('data.ping.low')->label('Low') + ->formatStateUsing(fn ($state) => number_format((float) $state, 0, '.', '').' ms'), + Forms\Components\TextInput::make('data.ping.high')->label('High') + ->formatStateUsing(fn ($state) => number_format((float) $state, 0, '.', '').' ms'), + ]) + ->columns(2) + ->collapsed(), + + Forms\Components\Textarea::make('data.message') + ->label('Message') + ->hint(new HtmlString('🔗Error Messages')) + ->columnSpanFull(), + ])->columnSpan([ + 'default' => 2, + 'md' => 2, + ]), + + Forms\Components\Section::make('Server & Metadata')->schema([ + Forms\Components\Placeholder::make('service') + ->content(fn (Result $result): string => $result->service->getLabel()), + Forms\Components\Placeholder::make('server_name') + ->content(fn (Result $result): ?string => $result->server_name), + Forms\Components\Placeholder::make('server_id') + ->label('Server ID') + ->content(fn (Result $result): ?string => $result->server_id), + Forms\Components\Placeholder::make('isp') + ->label('ISP') + ->content(fn (Result $result): ?string => $result->isp), + Forms\Components\Placeholder::make('server_location') + ->label('Server Location') + ->content(fn (Result $result): ?string => $result->server_location), + Forms\Components\Placeholder::make('server_host') + ->content(fn (Result $result): ?string => $result->server_host), + Forms\Components\Placeholder::make('comment') + ->content(fn (Result $result): ?string => $result->comments), + Forms\Components\Checkbox::make('scheduled'), + Forms\Components\Checkbox::make('healthy'), + ])->columns(1)->columnSpan([ + 'default' => 2, + 'md' => 1, ]), - ]); + ]), + ]); } public static function table(Table $table): Table @@ -295,6 +278,26 @@ public static function table(Table $table): Table ->formatStateUsing(function ($state) { return number_format((float) $state, 0, '.', '').' ms'; }), + Tables\Columns\TextColumn::make('data.ping.low') + ->label('Ping low') + ->toggleable() + ->toggledHiddenByDefault() + ->sortable(query: function (Builder $query, string $direction): Builder { + return $query->orderBy('data->ping->low', $direction); + }) + ->formatStateUsing(function ($state) { + return number_format((float) $state, 0, '.', '').' ms'; + }), + Tables\Columns\TextColumn::make('data.ping.high') + ->label('Ping high') + ->toggleable() + ->toggledHiddenByDefault() + ->sortable(query: function (Builder $query, string $direction): Builder { + return $query->orderBy('data->ping->high', $direction); + }) + ->formatStateUsing(function ($state) { + return number_format((float) $state, 0, '.', '').' ms'; + }), Tables\Columns\TextColumn::make('packet_loss') ->toggleable() ->toggledHiddenByDefault() diff --git a/app/Models/Traits/ResultDataAttributes.php b/app/Models/Traits/ResultDataAttributes.php index c4fe9e26b..805ca9d29 100644 --- a/app/Models/Traits/ResultDataAttributes.php +++ b/app/Models/Traits/ResultDataAttributes.php @@ -207,4 +207,74 @@ protected function uploadlatencyiqm(): Attribute get: fn () => Arr::get($this->data, 'upload.latency.iqm'), ); } + + /** + * Get the result's ping low latency in milliseconds. + */ + protected function pingLow(): Attribute + { + return Attribute::make( + get: fn () => Arr::get($this->data, 'ping.low'), + ); + } + + /** + * Get the result's ping high latency in milliseconds. + */ + protected function pingHigh(): Attribute + { + return Attribute::make( + get: fn () => Arr::get($this->data, 'ping.high'), + ); + } + + /** + * Get the result's download elapsed time in milliseconds. + */ + protected function downloadElapsed(): Attribute + { + return Attribute::make( + get: fn () => Arr::get($this->data, 'download.elapsed'), + ); + } + + /** + * Get the result's upload elapsed time in milliseconds. + */ + protected function uploadElapsed(): Attribute + { + return Attribute::make( + get: fn () => Arr::get($this->data, 'upload.elapsed'), + ); + } + + /** + * Get the result's server port. + */ + protected function serverPort(): Attribute + { + return Attribute::make( + get: fn () => Arr::get($this->data, 'server.port'), + ); + } + + /** + * Get the result's server IP address. + */ + protected function serverIp(): Attribute + { + return Attribute::make( + get: fn () => Arr::get($this->data, 'server.ip'), + ); + } + + /** + * Get the result's server country. + */ + protected function serverCountry(): Attribute + { + return Attribute::make( + get: fn () => Arr::get($this->data, 'server.country'), + ); + } }