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'),
+ );
+ }
}