Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 4 additions & 76 deletions app/Filament/Pages/Dashboard.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,17 @@
use Cron\CronExpression;
use Filament\Actions\Action;
use Filament\Actions\ActionGroup;
use Filament\Forms;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Form;
use Filament\Notifications\Notification;
use Filament\Pages\Dashboard as BaseDashboard;
use Filament\Pages\Dashboard\Concerns\HasFiltersForm;
use Filament\Pages\Dashboard as BasePage;
use Filament\Support\Enums\IconPosition;
use Illuminate\Support\Arr;

class Dashboard extends BaseDashboard
class Dashboard extends BasePage
{
use HasFiltersForm;

protected static ?string $navigationIcon = 'heroicon-o-chart-bar';

protected static string $view = 'filament.pages.dashboard';

public function getSubheading(): ?string
{
if (blank(config('speedtest.schedule'))) {
Expand All @@ -43,67 +38,6 @@ public function getSubheading(): ?string
return 'Next speedtest at: '.$nextRunDate;
}

public function filtersForm(Form $form): Form
{
// Retrieve the default number of days from the configuration
$defaultRangeDays = config('app.chart_default_date_range');

// Calculate the start and end dates based on the configuration value
$defaultEndDate = now(); // Today
$defaultStartDate = now()->subDays($defaultRangeDays); // Start date for the range

return $form
->schema([
Forms\Components\Section::make()
->schema([
Select::make('predefinedRange')
->label('Time Range')
->options([
'24_hours' => 'Last 24 Hours',
'1_week' => 'Last 1 Week',
'1_month' => 'Last 1 Month',
'custom' => 'Custom Range',
])
->reactive()
->afterStateUpdated(function ($state, callable $set) {
switch ($state) {
case '24_hours':
$set('startDate', now()->subDay()->toDateString());
$set('endDate', now()->toDateString());
break;
case '1_week':
$set('startDate', now()->subWeek()->toDateString());
$set('endDate', now()->toDateString());
break;
case '1_month':
$set('startDate', now()->subMonth()->toDateString());
$set('endDate', now()->toDateString());
break;
case 'custom':
break;
}
})
->default('custom'),

DatePicker::make('startDate')
->label('Start Date')
->default($defaultStartDate->toDateString())
->reactive()
->hidden(fn ($get) => $get('predefinedRange') !== 'custom'),

DatePicker::make('endDate')
->label('End Date')
->default($defaultEndDate->toDateString())
->reactive()
->hidden(fn ($get) => $get('predefinedRange') !== 'custom'),
])
->columns([
'default' => 1,
'sm' => 3,
]),
]);
}

protected function getHeaderActions(): array
{
return [
Expand Down Expand Up @@ -149,12 +83,6 @@ protected function getHeaderWidgets(): array
{
return [
StatsOverviewWidget::make(),
];
}

public function getWidgets(): array
{
return [
RecentDownloadChartWidget::make(),
RecentUploadChartWidget::make(),
RecentPingChartWidget::make(),
Expand Down
57 changes: 26 additions & 31 deletions app/Filament/Widgets/RecentDownloadChartWidget.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,64 +6,59 @@
use App\Helpers\Number;
use App\Models\Result;
use Filament\Widgets\ChartWidget;
use Filament\Widgets\Concerns\InteractsWithPageFilters;
use Illuminate\Database\Eloquent\Builder;

class RecentDownloadChartWidget extends ChartWidget
{
use InteractsWithPageFilters;

protected static ?string $heading = 'Download (Mbps)';

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

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

public ?string $filter = '24h';

protected function getPollingInterval(): ?string
{
return config('speedtest.dashboard_polling');
}

protected function getData(): array
protected function getFilters(): ?array
{
return [
'24h' => 'Last 24h',
'week' => 'Last week',
'month' => 'Last month',
];
}

$startDate = $this->filters['startDate'] ?? now()->subWeek();
$endDate = $this->filters['endDate'] ?? now();

protected function getData(): array
{
$results = Result::query()
->select(['id', 'download', 'created_at'])
->where('status', '=', ResultStatus::Completed)
->when($startDate, fn (Builder $query) => $query->whereDate('created_at', '>=', $startDate))
->when($endDate, fn (Builder $query) => $query->whereDate('created_at', '<=', $endDate))
->when($this->filter == '24h', function ($query) {
$query->where('created_at', '>=', now()->subDay());
})
->when($this->filter == 'week', function ($query) {
$query->where('created_at', '>=', now()->subWeek());
})
->when($this->filter == 'month', function ($query) {
$query->where('created_at', '>=', now()->subMonth());
})
->orderBy('created_at')
->get();

$downloads = $results->map(fn ($item) => ! blank($item->download) ? Number::bitsToMagnitude(bits: $item->download_bits, precision: 2, magnitude: 'mbit') : 0);
$averageDownload = $downloads->avg();

return [
'datasets' => [
[
'label' => 'Download',
'data' => $downloads,
'borderColor' => 'rgba(14, 165, 233)',
'backgroundColor' => 'rgba(14, 165, 233, 0.1)', // 10% opacity
'pointBackgroundColor' => 'rgba(14, 165, 233)',
'fill' => true,
'cubicInterpolationMode' => 'monotone',
'tension' => 0.4,
'pointRadius' => count($downloads) <= 5 ? 3 : 0,
],
[
'label' => 'Average',
'data' => array_fill(0, count($downloads), $averageDownload),
'borderColor' => 'rgb(255, 165, 0)',
'pointBackgroundColor' => 'rgb(255, 165, 0)',
'data' => $results->map(fn ($item) => ! blank($item->download) ? Number::bitsToMagnitude(bits: $item->download_bits, precision: 2, magnitude: 'mbit') : 0),
'borderColor' => '#0ea5e9',
'backgroundColor' => '#0ea5e9',
'pointBackgroundColor' => '#0ea5e9',
'fill' => false,
'cubicInterpolationMode' => 'monotone',
'tension' => 0.4,
'borderDash' => [5, 5],
'pointRadius' => 0,
],
],
'labels' => $results->map(fn ($item) => $item->created_at->timezone(config('app.display_timezone'))->format(config('app.chart_datetime_format'))),
Expand All @@ -75,12 +70,12 @@ protected function getOptions(): array
return [
'plugins' => [
'legend' => [
'display' => true,
'display' => false,
],
],
'scales' => [
'y' => [
'beginAtZero' => config('app.chart_begin_at_zero'),
'beginAtZero' => true,
],
],
];
Expand Down
65 changes: 36 additions & 29 deletions app/Filament/Widgets/RecentDownloadLatencyChartWidget.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,72 +5,79 @@
use App\Enums\ResultStatus;
use App\Models\Result;
use Filament\Widgets\ChartWidget;
use Filament\Widgets\Concerns\InteractsWithPageFilters;
use Illuminate\Database\Eloquent\Builder;

class RecentDownloadLatencyChartWidget extends ChartWidget
{
use InteractsWithPageFilters;

protected static ?string $heading = 'Download Latency';

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

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

public ?string $filter = '24h';

protected function getPollingInterval(): ?string
{
return config('speedtest.dashboard_polling');
}

protected function getData(): array
protected function getFilters(): ?array
{
return [
'24h' => 'Last 24h',
'week' => 'Last week',
'month' => 'Last month',
];
}

$startDate = $this->filters['startDate'] ?? now()->subWeek();
$endDate = $this->filters['endDate'] ?? now();

protected function getData(): array
{
$results = Result::query()
->select(['id', 'data', 'created_at'])
->where('status', '=', ResultStatus::Completed)
->when($startDate, fn (Builder $query) => $query->whereDate('created_at', '>=', $startDate))
->when($endDate, fn (Builder $query) => $query->whereDate('created_at', '<=', $endDate))
->when($this->filter == '24h', function ($query) {
$query->where('created_at', '>=', now()->subDay());
})
->when($this->filter == 'week', function ($query) {
$query->where('created_at', '>=', now()->subWeek());
})
->when($this->filter == 'month', function ($query) {
$query->where('created_at', '>=', now()->subMonth());
})
->orderBy('created_at')
->get();

return [
'datasets' => [
[
'label' => 'Average (ms)',
'data' => $averageData = $results->map(fn ($item) => $item->download_latency_iqm ? number_format($item->download_latency_iqm, 2) : 0),
'borderColor' => 'rgba(16, 185, 129)',
'backgroundColor' => 'rgba(16, 185, 129, 0.1)',
'pointBackgroundColor' => 'rgba(16, 185, 129)',
'fill' => true,
'data' => $results->map(fn ($item) => $item->download_latency_iqm ? number_format($item->download_latency_iqm, 2) : 0),
'borderColor' => '#10b981',
'backgroundColor' => '#10b981',
'pointBackgroundColor' => '#10b981',
'fill' => false,
'cubicInterpolationMode' => 'monotone',
'tension' => 0.4,
'pointRadius' => $averageData->count() <= 5 ? 3 : 0,
],
[
'label' => 'High (ms)',
'data' => $highData = $results->map(fn ($item) => $item->download_latency_high ? number_format($item->download_latency_high, 2) : 0),
'borderColor' => 'rgba(14, 165, 233)',
'backgroundColor' => 'rgba(14, 165, 233, 0.1)',
'pointBackgroundColor' => 'rgba(14, 165, 233)',
'fill' => true,
'data' => $results->map(fn ($item) => $item->download_latency_high ? number_format($item->download_latency_high, 2) : 0),
'borderColor' => '#0ea5e9',
'backgroundColor' => '#0ea5e9',
'pointBackgroundColor' => '#0ea5e9',
'fill' => false,
'cubicInterpolationMode' => 'monotone',
'tension' => 0.4,
'pointRadius' => $highData->count() <= 5 ? 3 : 0,
],
[
'label' => 'Low (ms)',
'data' => $lowData = $results->map(fn ($item) => $item->download_latency_low ? number_format($item->download_latency_low, 2) : 0),
'borderColor' => 'rgba(139, 92, 246)',
'backgroundColor' => 'rgba(139, 92, 246, 0.1)',
'pointBackgroundColor' => 'rgba(139, 92, 246)',
'fill' => true,
'data' => $results->map(fn ($item) => $item->download_latency_low ? number_format($item->download_latency_low, 2) : 0),
'borderColor' => '#8b5cf6',
'backgroundColor' => '#8b5cf6',
'pointBackgroundColor' => '#8b5cf6',
'fill' => false,
'cubicInterpolationMode' => 'monotone',
'tension' => 0.4,
'pointRadius' => $lowData->count() <= 5 ? 3 : 0,
],
],
'labels' => $results->map(fn ($item) => $item->created_at->timezone(config('app.display_timezone'))->format(config('app.chart_datetime_format'))),
Expand All @@ -82,7 +89,7 @@ protected function getOptions(): array
return [
'scales' => [
'y' => [
'beginAtZero' => config('app.chart_begin_at_zero'),
'beginAtZero' => true,
],
],
];
Expand Down
Loading