diff --git a/app/Filament/Pages/Dashboard.php b/app/Filament/Pages/Dashboard.php index 620a8745a..de28c014b 100644 --- a/app/Filament/Pages/Dashboard.php +++ b/app/Filament/Pages/Dashboard.php @@ -7,6 +7,7 @@ use App\Filament\Widgets\RecentSpeedChart; use App\Filament\Widgets\StatsOverview; use App\Jobs\ExecSpeedtest; +use App\Models\Result; use App\Settings\GeneralSettings; use Filament\Notifications\Notification; use Filament\Pages\Actions\Action; @@ -14,8 +15,29 @@ class Dashboard extends BasePage { + public string $lastResult = 'never'; + + public int $resultsCount; + protected static string $view = 'filament.pages.dashboard'; + public function mount() + { + $this->resultsCount = Result::count(); + + if ($this->resultsCount) { + $result = Result::latest() + ->first(); + + $settings = new GeneralSettings(); + + $this->lastResult = $result->created_at + ->timezone($settings->timezone) + ->format($settings->time_format); + } + + } + protected function getActions(): array { return [ @@ -27,8 +49,22 @@ protected function getActions(): array public function getHeaderWidgets(): array { + if (! $this->resultsCount) { + return []; + } + return [ StatsOverview::class, + ]; + } + + public function getFooterWidgets(): array + { + if (! $this->resultsCount) { + return []; + } + + return [ RecentSpeedChart::class, RecentPingChart::class, RecentJitterChart::class, diff --git a/app/Filament/Widgets/StatsOverview.php b/app/Filament/Widgets/StatsOverview.php index de69f70e9..1f1eaf7e0 100644 --- a/app/Filament/Widgets/StatsOverview.php +++ b/app/Filament/Widgets/StatsOverview.php @@ -15,14 +15,43 @@ protected function getCards(): array $settings = new GeneralSettings(); + if (! $result) { + return []; + } + + $previous = $result->previous(); + + if (! $previous) { + return [ + Card::make('Latest download', fn (): string => ! blank($result) ? formatBits(formatBytesToBits($result->download)).'ps' : 'n/a') + ->icon('heroicon-o-download'), + Card::make('Latest upload', fn (): string => ! blank($result) ? formatBits(formatBytesToBits($result->upload)).'ps' : 'n/a') + ->icon('heroicon-o-upload'), + Card::make('Latest ping', fn (): string => ! blank($result) ? round($result->ping, 2).'ms' : 'n/a') + ->icon('heroicon-o-clock'), + ]; + } + + $downloadChange = percentChange($result->download, $previous->download, 2); + $uploadChange = percentChange($result->upload, $previous->upload, 2); + $pingChange = percentChange($result->ping, $previous->ping, 2); + return [ Card::make('Latest download', fn (): string => ! blank($result) ? formatBits(formatBytesToBits($result->download)).'ps' : 'n/a') - ->description(! blank($result) ? 'Tested at: '.$result->created_at->timezone($settings->timezone)->format($settings->time_format) : 'No tests') - ->icon('heroicon-o-download'), + ->icon('heroicon-o-download') + ->description($downloadChange > 0 ? $downloadChange.'% faster' : abs($downloadChange).'% slower') + ->descriptionIcon($downloadChange > 0 ? 'heroicon-s-trending-up' : 'heroicon-s-trending-down') + ->color($downloadChange > 0 ? 'success' : 'danger'), Card::make('Latest upload', fn (): string => ! blank($result) ? formatBits(formatBytesToBits($result->upload)).'ps' : 'n/a') - ->icon('heroicon-o-upload'), + ->icon('heroicon-o-upload') + ->description($uploadChange > 0 ? $uploadChange.'% faster' : abs($uploadChange).'% slower') + ->descriptionIcon($uploadChange > 0 ? 'heroicon-s-trending-up' : 'heroicon-s-trending-down') + ->color($uploadChange > 0 ? 'success' : 'danger'), Card::make('Latest ping', fn (): string => ! blank($result) ? round($result->ping, 2).'ms' : 'n/a') - ->icon('heroicon-o-clock'), + ->icon('heroicon-o-clock') + ->description($pingChange > 0 ? $pingChange.'% slower' : abs($pingChange).'% faster') + ->descriptionIcon($pingChange > 0 ? 'heroicon-s-trending-up' : 'heroicon-s-trending-down') + ->color($pingChange > 0 ? 'danger' : 'success'), ]; } } diff --git a/app/Models/Result.php b/app/Models/Result.php index 6bc25dbbf..b4ac8ddcd 100644 --- a/app/Models/Result.php +++ b/app/Models/Result.php @@ -89,4 +89,16 @@ public function getJitterData(): array 'ping' => $data['ping']['jitter'] ?? null, ]; } + + /** + * Return the previous test result . + * + * @return self|null + */ + public function previous() + { + return static::orderBy('id', 'desc') + ->where('id', '<', $this->id) + ->first(); + } } diff --git a/app/helpers.php b/app/helpers.php index a019e1d7d..1fb916fd7 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -45,6 +45,15 @@ function formatBytestoBits(int $bytes) } } +if (! function_exists('percentChange')) { + function percentChange(float $dividend, float $divisor, int $precision = 0): float + { + $quotient = ($dividend - $divisor) / $divisor; + + return number_format(round($quotient * 100, $precision), $precision); + } +} + if (! function_exists('absoluteDownloadThresholdFailed')) { function absoluteDownloadThresholdFailed(float $threshold, float $download): bool { diff --git a/resources/views/filament/pages/dashboard.blade.php b/resources/views/filament/pages/dashboard.blade.php index cda924d8a..e65afff54 100644 --- a/resources/views/filament/pages/dashboard.blade.php +++ b/resources/views/filament/pages/dashboard.blade.php @@ -1 +1,7 @@ - + + + + Last speedtest run at: {{ $lastResult }} + + +
Last speedtest run at: {{ $lastResult }}