Skip to content

Commit b2ff25b

Browse files
authored
Merge pull request #2 from svenvg93/add-failed-and-thresholds
Add failed and thresholds
2 parents c8bb0c0 + 249340e commit b2ff25b

File tree

9 files changed

+264
-192
lines changed

9 files changed

+264
-192
lines changed

app/Filament/Pages/Dashboard.php

Lines changed: 76 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,21 @@
1414
use Cron\CronExpression;
1515
use Filament\Actions\Action;
1616
use Filament\Actions\ActionGroup;
17+
use Filament\Forms;
18+
use Filament\Forms\Components\DatePicker;
19+
use Filament\Forms\Components\Select;
20+
use Filament\Forms\Form;
1721
use Filament\Notifications\Notification;
18-
use Filament\Pages\Dashboard as BasePage;
22+
use Filament\Pages\Dashboard as BaseDashboard;
23+
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
1924
use Filament\Support\Enums\IconPosition;
2025
use Illuminate\Support\Arr;
2126

22-
class Dashboard extends BasePage
27+
class Dashboard extends BaseDashboard
2328
{
24-
protected static ?string $navigationIcon = 'heroicon-o-chart-bar';
29+
use HasFiltersForm;
2530

26-
protected static string $view = 'filament.pages.dashboard';
31+
protected static ?string $navigationIcon = 'heroicon-o-chart-bar';
2732

2833
public function getSubheading(): ?string
2934
{
@@ -38,6 +43,67 @@ public function getSubheading(): ?string
3843
return 'Next speedtest at: '.$nextRunDate;
3944
}
4045

46+
public function filtersForm(Form $form): Form
47+
{
48+
// Retrieve the default number of days from the configuration
49+
$defaultRangeDays = config('app.chart_default_date_range');
50+
51+
// Calculate the start and end dates based on the configuration value
52+
$defaultEndDate = now(); // Today
53+
$defaultStartDate = now()->subDays($defaultRangeDays); // Start date for the range
54+
55+
return $form
56+
->schema([
57+
Forms\Components\Section::make()
58+
->schema([
59+
Select::make('predefinedRange')
60+
->label('Time Range')
61+
->options([
62+
'24_hours' => 'Last 24 Hours',
63+
'1_week' => 'Last 1 Week',
64+
'1_month' => 'Last 1 Month',
65+
'custom' => 'Custom Range',
66+
])
67+
->reactive()
68+
->afterStateUpdated(function ($state, callable $set) {
69+
switch ($state) {
70+
case '24_hours':
71+
$set('startDate', now()->subDay()->toDateString());
72+
$set('endDate', now()->toDateString());
73+
break;
74+
case '1_week':
75+
$set('startDate', now()->subWeek()->toDateString());
76+
$set('endDate', now()->toDateString());
77+
break;
78+
case '1_month':
79+
$set('startDate', now()->subMonth()->toDateString());
80+
$set('endDate', now()->toDateString());
81+
break;
82+
case 'custom':
83+
break;
84+
}
85+
})
86+
->default('custom'),
87+
88+
DatePicker::make('startDate')
89+
->label('Start Date')
90+
->default($defaultStartDate->toDateString())
91+
->reactive()
92+
->hidden(fn ($get) => $get('predefinedRange') !== 'custom'),
93+
94+
DatePicker::make('endDate')
95+
->label('End Date')
96+
->default($defaultEndDate->toDateString())
97+
->reactive()
98+
->hidden(fn ($get) => $get('predefinedRange') !== 'custom'),
99+
])
100+
->columns([
101+
'default' => 1,
102+
'sm' => 3,
103+
]),
104+
]);
105+
}
106+
41107
protected function getHeaderActions(): array
42108
{
43109
return [
@@ -83,6 +149,12 @@ protected function getHeaderWidgets(): array
83149
{
84150
return [
85151
StatsOverviewWidget::make(),
152+
];
153+
}
154+
155+
public function getWidgets(): array
156+
{
157+
return [
86158
RecentDownloadChartWidget::make(),
87159
RecentUploadChartWidget::make(),
88160
RecentPingChartWidget::make(),

app/Filament/Widgets/RecentDownloadChartWidget.php

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,59 +6,64 @@
66
use App\Helpers\Number;
77
use App\Models\Result;
88
use Filament\Widgets\ChartWidget;
9+
use Filament\Widgets\Concerns\InteractsWithPageFilters;
10+
use Illuminate\Database\Eloquent\Builder;
911

1012
class RecentDownloadChartWidget extends ChartWidget
1113
{
14+
use InteractsWithPageFilters;
15+
1216
protected static ?string $heading = 'Download (Mbps)';
1317

1418
protected int|string|array $columnSpan = 'full';
1519

1620
protected static ?string $maxHeight = '250px';
1721

18-
public ?string $filter = '24h';
19-
2022
protected function getPollingInterval(): ?string
2123
{
2224
return config('speedtest.dashboard_polling');
2325
}
2426

25-
protected function getFilters(): ?array
26-
{
27-
return [
28-
'24h' => 'Last 24h',
29-
'week' => 'Last week',
30-
'month' => 'Last month',
31-
];
32-
}
33-
3427
protected function getData(): array
3528
{
29+
30+
$startDate = $this->filters['startDate'] ?? now()->subWeek();
31+
$endDate = $this->filters['endDate'] ?? now();
32+
3633
$results = Result::query()
3734
->select(['id', 'download', 'created_at'])
3835
->where('status', '=', ResultStatus::Completed)
39-
->when($this->filter == '24h', function ($query) {
40-
$query->where('created_at', '>=', now()->subDay());
41-
})
42-
->when($this->filter == 'week', function ($query) {
43-
$query->where('created_at', '>=', now()->subWeek());
44-
})
45-
->when($this->filter == 'month', function ($query) {
46-
$query->where('created_at', '>=', now()->subMonth());
47-
})
36+
->when($startDate, fn (Builder $query) => $query->whereDate('created_at', '>=', $startDate))
37+
->when($endDate, fn (Builder $query) => $query->whereDate('created_at', '<=', $endDate))
4838
->orderBy('created_at')
4939
->get();
5040

41+
$downloads = $results->map(fn ($item) => ! blank($item->download) ? Number::bitsToMagnitude(bits: $item->download_bits, precision: 2, magnitude: 'mbit') : 0);
42+
$averageDownload = $downloads->avg();
43+
5144
return [
5245
'datasets' => [
5346
[
5447
'label' => 'Download',
55-
'data' => $results->map(fn ($item) => ! blank($item->download) ? Number::bitsToMagnitude(bits: $item->download_bits, precision: 2, magnitude: 'mbit') : 0),
56-
'borderColor' => '#0ea5e9',
57-
'backgroundColor' => '#0ea5e9',
58-
'pointBackgroundColor' => '#0ea5e9',
48+
'data' => $downloads,
49+
'borderColor' => 'rgba(14, 165, 233)',
50+
'backgroundColor' => 'rgba(14, 165, 233, 0.1)', // 10% opacity
51+
'pointBackgroundColor' => 'rgba(14, 165, 233)',
52+
'fill' => true,
53+
'cubicInterpolationMode' => 'monotone',
54+
'tension' => 0.4,
55+
'pointRadius' => count($downloads) <= 5 ? 3 : 0,
56+
],
57+
[
58+
'label' => 'Average',
59+
'data' => array_fill(0, count($downloads), $averageDownload),
60+
'borderColor' => 'rgb(255, 165, 0)',
61+
'pointBackgroundColor' => 'rgb(255, 165, 0)',
5962
'fill' => false,
6063
'cubicInterpolationMode' => 'monotone',
6164
'tension' => 0.4,
65+
'borderDash' => [5, 5],
66+
'pointRadius' => 0,
6267
],
6368
],
6469
'labels' => $results->map(fn ($item) => $item->created_at->timezone(config('app.display_timezone'))->format(config('app.chart_datetime_format'))),
@@ -70,12 +75,12 @@ protected function getOptions(): array
7075
return [
7176
'plugins' => [
7277
'legend' => [
73-
'display' => false,
78+
'display' => true,
7479
],
7580
],
7681
'scales' => [
7782
'y' => [
78-
'beginAtZero' => true,
83+
'beginAtZero' => config('app.chart_begin_at_zero'),
7984
],
8085
],
8186
];

app/Filament/Widgets/RecentDownloadLatencyChartWidget.php

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,79 +5,72 @@
55
use App\Enums\ResultStatus;
66
use App\Models\Result;
77
use Filament\Widgets\ChartWidget;
8+
use Filament\Widgets\Concerns\InteractsWithPageFilters;
9+
use Illuminate\Database\Eloquent\Builder;
810

911
class RecentDownloadLatencyChartWidget extends ChartWidget
1012
{
13+
use InteractsWithPageFilters;
14+
1115
protected static ?string $heading = 'Download Latency';
1216

1317
protected int|string|array $columnSpan = 'full';
1418

1519
protected static ?string $maxHeight = '250px';
1620

17-
public ?string $filter = '24h';
18-
1921
protected function getPollingInterval(): ?string
2022
{
2123
return config('speedtest.dashboard_polling');
2224
}
2325

24-
protected function getFilters(): ?array
25-
{
26-
return [
27-
'24h' => 'Last 24h',
28-
'week' => 'Last week',
29-
'month' => 'Last month',
30-
];
31-
}
32-
3326
protected function getData(): array
3427
{
28+
29+
$startDate = $this->filters['startDate'] ?? now()->subWeek();
30+
$endDate = $this->filters['endDate'] ?? now();
31+
3532
$results = Result::query()
3633
->select(['id', 'data', 'created_at'])
3734
->where('status', '=', ResultStatus::Completed)
38-
->when($this->filter == '24h', function ($query) {
39-
$query->where('created_at', '>=', now()->subDay());
40-
})
41-
->when($this->filter == 'week', function ($query) {
42-
$query->where('created_at', '>=', now()->subWeek());
43-
})
44-
->when($this->filter == 'month', function ($query) {
45-
$query->where('created_at', '>=', now()->subMonth());
46-
})
35+
->when($startDate, fn (Builder $query) => $query->whereDate('created_at', '>=', $startDate))
36+
->when($endDate, fn (Builder $query) => $query->whereDate('created_at', '<=', $endDate))
4737
->orderBy('created_at')
4838
->get();
4939

5040
return [
5141
'datasets' => [
5242
[
5343
'label' => 'Average (ms)',
54-
'data' => $results->map(fn ($item) => $item->download_latency_iqm ? number_format($item->download_latency_iqm, 2) : 0),
55-
'borderColor' => '#10b981',
56-
'backgroundColor' => '#10b981',
57-
'pointBackgroundColor' => '#10b981',
58-
'fill' => false,
44+
'data' => $averageData = $results->map(fn ($item) => $item->download_latency_iqm ? number_format($item->download_latency_iqm, 2) : 0),
45+
'borderColor' => 'rgba(16, 185, 129)',
46+
'backgroundColor' => 'rgba(16, 185, 129, 0.1)',
47+
'pointBackgroundColor' => 'rgba(16, 185, 129)',
48+
'fill' => true,
5949
'cubicInterpolationMode' => 'monotone',
6050
'tension' => 0.4,
51+
'pointRadius' => $averageData->count() <= 5 ? 3 : 0,
6152
],
6253
[
6354
'label' => 'High (ms)',
64-
'data' => $results->map(fn ($item) => $item->download_latency_high ? number_format($item->download_latency_high, 2) : 0),
65-
'borderColor' => '#0ea5e9',
66-
'backgroundColor' => '#0ea5e9',
67-
'pointBackgroundColor' => '#0ea5e9',
68-
'fill' => false,
55+
'data' => $highData = $results->map(fn ($item) => $item->download_latency_high ? number_format($item->download_latency_high, 2) : 0),
56+
'borderColor' => 'rgba(14, 165, 233)',
57+
'backgroundColor' => 'rgba(14, 165, 233, 0.1)',
58+
'pointBackgroundColor' => 'rgba(14, 165, 233)',
59+
'fill' => true,
6960
'cubicInterpolationMode' => 'monotone',
7061
'tension' => 0.4,
62+
'pointRadius' => $highData->count() <= 5 ? 3 : 0,
7163
],
7264
[
7365
'label' => 'Low (ms)',
74-
'data' => $results->map(fn ($item) => $item->download_latency_low ? number_format($item->download_latency_low, 2) : 0),
75-
'borderColor' => '#8b5cf6',
76-
'backgroundColor' => '#8b5cf6',
77-
'pointBackgroundColor' => '#8b5cf6',
78-
'fill' => false,
66+
'data' => $lowData = $results->map(fn ($item) => $item->download_latency_low ? number_format($item->download_latency_low, 2) : 0),
67+
'borderColor' => 'rgba(139, 92, 246)',
68+
'backgroundColor' => 'rgba(139, 92, 246, 0.1)',
69+
'pointBackgroundColor' => 'rgba(139, 92, 246)',
70+
'fill' => true,
7971
'cubicInterpolationMode' => 'monotone',
8072
'tension' => 0.4,
73+
'pointRadius' => $lowData->count() <= 5 ? 3 : 0,
8174
],
8275
],
8376
'labels' => $results->map(fn ($item) => $item->created_at->timezone(config('app.display_timezone'))->format(config('app.chart_datetime_format'))),
@@ -89,7 +82,7 @@ protected function getOptions(): array
8982
return [
9083
'scales' => [
9184
'y' => [
92-
'beginAtZero' => true,
85+
'beginAtZero' => config('app.chart_begin_at_zero'),
9386
],
9487
],
9588
];

0 commit comments

Comments
 (0)