Skip to content

Commit 5d7793b

Browse files
authored
Percent change on stats widgets (alexjustesen#247)
1 parent 93d7665 commit 5d7793b

File tree

5 files changed

+97
-5
lines changed

5 files changed

+97
-5
lines changed

app/Filament/Pages/Dashboard.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,37 @@
77
use App\Filament\Widgets\RecentSpeedChart;
88
use App\Filament\Widgets\StatsOverview;
99
use App\Jobs\ExecSpeedtest;
10+
use App\Models\Result;
1011
use App\Settings\GeneralSettings;
1112
use Filament\Notifications\Notification;
1213
use Filament\Pages\Actions\Action;
1314
use Filament\Pages\Dashboard as BasePage;
1415

1516
class Dashboard extends BasePage
1617
{
18+
public string $lastResult = 'never';
19+
20+
public int $resultsCount;
21+
1722
protected static string $view = 'filament.pages.dashboard';
1823

24+
public function mount()
25+
{
26+
$this->resultsCount = Result::count();
27+
28+
if ($this->resultsCount) {
29+
$result = Result::latest()
30+
->first();
31+
32+
$settings = new GeneralSettings();
33+
34+
$this->lastResult = $result->created_at
35+
->timezone($settings->timezone)
36+
->format($settings->time_format);
37+
}
38+
39+
}
40+
1941
protected function getActions(): array
2042
{
2143
return [
@@ -27,8 +49,22 @@ protected function getActions(): array
2749

2850
public function getHeaderWidgets(): array
2951
{
52+
if (! $this->resultsCount) {
53+
return [];
54+
}
55+
3056
return [
3157
StatsOverview::class,
58+
];
59+
}
60+
61+
public function getFooterWidgets(): array
62+
{
63+
if (! $this->resultsCount) {
64+
return [];
65+
}
66+
67+
return [
3268
RecentSpeedChart::class,
3369
RecentPingChart::class,
3470
RecentJitterChart::class,

app/Filament/Widgets/StatsOverview.php

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,43 @@ protected function getCards(): array
1515

1616
$settings = new GeneralSettings();
1717

18+
if (! $result) {
19+
return [];
20+
}
21+
22+
$previous = $result->previous();
23+
24+
if (! $previous) {
25+
return [
26+
Card::make('Latest download', fn (): string => ! blank($result) ? formatBits(formatBytesToBits($result->download)).'ps' : 'n/a')
27+
->icon('heroicon-o-download'),
28+
Card::make('Latest upload', fn (): string => ! blank($result) ? formatBits(formatBytesToBits($result->upload)).'ps' : 'n/a')
29+
->icon('heroicon-o-upload'),
30+
Card::make('Latest ping', fn (): string => ! blank($result) ? round($result->ping, 2).'ms' : 'n/a')
31+
->icon('heroicon-o-clock'),
32+
];
33+
}
34+
35+
$downloadChange = percentChange($result->download, $previous->download, 2);
36+
$uploadChange = percentChange($result->upload, $previous->upload, 2);
37+
$pingChange = percentChange($result->ping, $previous->ping, 2);
38+
1839
return [
1940
Card::make('Latest download', fn (): string => ! blank($result) ? formatBits(formatBytesToBits($result->download)).'ps' : 'n/a')
20-
->description(! blank($result) ? 'Tested at: '.$result->created_at->timezone($settings->timezone)->format($settings->time_format) : 'No tests')
21-
->icon('heroicon-o-download'),
41+
->icon('heroicon-o-download')
42+
->description($downloadChange > 0 ? $downloadChange.'% faster' : abs($downloadChange).'% slower')
43+
->descriptionIcon($downloadChange > 0 ? 'heroicon-s-trending-up' : 'heroicon-s-trending-down')
44+
->color($downloadChange > 0 ? 'success' : 'danger'),
2245
Card::make('Latest upload', fn (): string => ! blank($result) ? formatBits(formatBytesToBits($result->upload)).'ps' : 'n/a')
23-
->icon('heroicon-o-upload'),
46+
->icon('heroicon-o-upload')
47+
->description($uploadChange > 0 ? $uploadChange.'% faster' : abs($uploadChange).'% slower')
48+
->descriptionIcon($uploadChange > 0 ? 'heroicon-s-trending-up' : 'heroicon-s-trending-down')
49+
->color($uploadChange > 0 ? 'success' : 'danger'),
2450
Card::make('Latest ping', fn (): string => ! blank($result) ? round($result->ping, 2).'ms' : 'n/a')
25-
->icon('heroicon-o-clock'),
51+
->icon('heroicon-o-clock')
52+
->description($pingChange > 0 ? $pingChange.'% slower' : abs($pingChange).'% faster')
53+
->descriptionIcon($pingChange > 0 ? 'heroicon-s-trending-up' : 'heroicon-s-trending-down')
54+
->color($pingChange > 0 ? 'danger' : 'success'),
2655
];
2756
}
2857
}

app/Models/Result.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,16 @@ public function getJitterData(): array
8989
'ping' => $data['ping']['jitter'] ?? null,
9090
];
9191
}
92+
93+
/**
94+
* Return the previous test result .
95+
*
96+
* @return self|null
97+
*/
98+
public function previous()
99+
{
100+
return static::orderBy('id', 'desc')
101+
->where('id', '<', $this->id)
102+
->first();
103+
}
92104
}

app/helpers.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,15 @@ function formatBytestoBits(int $bytes)
4545
}
4646
}
4747

48+
if (! function_exists('percentChange')) {
49+
function percentChange(float $dividend, float $divisor, int $precision = 0): float
50+
{
51+
$quotient = ($dividend - $divisor) / $divisor;
52+
53+
return number_format(round($quotient * 100, $precision), $precision);
54+
}
55+
}
56+
4857
if (! function_exists('absoluteDownloadThresholdFailed')) {
4958
function absoluteDownloadThresholdFailed(float $threshold, float $download): bool
5059
{
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1-
<x-filament::page />
1+
<x-filament::page>
2+
3+
<div>
4+
<p class="text-center text-sm">Last speedtest run at: <strong>{{ $lastResult }}</strong></p>
5+
</div>
6+
7+
</x-filament::page>

0 commit comments

Comments
 (0)