mirror of
https://github.com/alexjustesen/speedtest-tracker.git
synced 2026-06-23 07:40:08 +00:00
[Feature] Removed general settings page (BREAKING CHANGE) (#1464)
This commit is contained in:
+22
-33
@@ -14,7 +14,6 @@ namespace PHPSTORM_META {
|
||||
override(new \Illuminate\Contracts\Container\Container, map([
|
||||
'' => '@',
|
||||
'App\Settings\DataMigrationSettings' => \App\Settings\DataMigrationSettings::class,
|
||||
'App\Settings\GeneralSettings' => \App\Settings\GeneralSettings::class,
|
||||
'App\Settings\InfluxDbSettings' => \App\Settings\InfluxDbSettings::class,
|
||||
'App\Settings\NotificationSettings' => \App\Settings\NotificationSettings::class,
|
||||
'App\Settings\ThresholdSettings' => \App\Settings\ThresholdSettings::class,
|
||||
@@ -214,9 +213,9 @@ namespace PHPSTORM_META {
|
||||
'composer' => \Illuminate\Support\Composer::class,
|
||||
'cookie' => \Illuminate\Cookie\CookieJar::class,
|
||||
'db' => \Illuminate\Database\DatabaseManager::class,
|
||||
'db.connection' => \Illuminate\Database\MySqlConnection::class,
|
||||
'db.connection' => \Illuminate\Database\SQLiteConnection::class,
|
||||
'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\SQLiteBuilder::class,
|
||||
'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class,
|
||||
'encrypter' => \Illuminate\Encryption\Encrypter::class,
|
||||
'events' => \Illuminate\Events\Dispatcher::class,
|
||||
@@ -257,7 +256,6 @@ namespace PHPSTORM_META {
|
||||
override(\Illuminate\Container\Container::makeWith(0), map([
|
||||
'' => '@',
|
||||
'App\Settings\DataMigrationSettings' => \App\Settings\DataMigrationSettings::class,
|
||||
'App\Settings\GeneralSettings' => \App\Settings\GeneralSettings::class,
|
||||
'App\Settings\InfluxDbSettings' => \App\Settings\InfluxDbSettings::class,
|
||||
'App\Settings\NotificationSettings' => \App\Settings\NotificationSettings::class,
|
||||
'App\Settings\ThresholdSettings' => \App\Settings\ThresholdSettings::class,
|
||||
@@ -457,9 +455,9 @@ namespace PHPSTORM_META {
|
||||
'composer' => \Illuminate\Support\Composer::class,
|
||||
'cookie' => \Illuminate\Cookie\CookieJar::class,
|
||||
'db' => \Illuminate\Database\DatabaseManager::class,
|
||||
'db.connection' => \Illuminate\Database\MySqlConnection::class,
|
||||
'db.connection' => \Illuminate\Database\SQLiteConnection::class,
|
||||
'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\SQLiteBuilder::class,
|
||||
'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class,
|
||||
'encrypter' => \Illuminate\Encryption\Encrypter::class,
|
||||
'events' => \Illuminate\Events\Dispatcher::class,
|
||||
@@ -500,7 +498,6 @@ namespace PHPSTORM_META {
|
||||
override(\Illuminate\Contracts\Container\Container::get(0), map([
|
||||
'' => '@',
|
||||
'App\Settings\DataMigrationSettings' => \App\Settings\DataMigrationSettings::class,
|
||||
'App\Settings\GeneralSettings' => \App\Settings\GeneralSettings::class,
|
||||
'App\Settings\InfluxDbSettings' => \App\Settings\InfluxDbSettings::class,
|
||||
'App\Settings\NotificationSettings' => \App\Settings\NotificationSettings::class,
|
||||
'App\Settings\ThresholdSettings' => \App\Settings\ThresholdSettings::class,
|
||||
@@ -700,9 +697,9 @@ namespace PHPSTORM_META {
|
||||
'composer' => \Illuminate\Support\Composer::class,
|
||||
'cookie' => \Illuminate\Cookie\CookieJar::class,
|
||||
'db' => \Illuminate\Database\DatabaseManager::class,
|
||||
'db.connection' => \Illuminate\Database\MySqlConnection::class,
|
||||
'db.connection' => \Illuminate\Database\SQLiteConnection::class,
|
||||
'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\SQLiteBuilder::class,
|
||||
'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class,
|
||||
'encrypter' => \Illuminate\Encryption\Encrypter::class,
|
||||
'events' => \Illuminate\Events\Dispatcher::class,
|
||||
@@ -743,7 +740,6 @@ namespace PHPSTORM_META {
|
||||
override(\Illuminate\Contracts\Container\Container::make(0), map([
|
||||
'' => '@',
|
||||
'App\Settings\DataMigrationSettings' => \App\Settings\DataMigrationSettings::class,
|
||||
'App\Settings\GeneralSettings' => \App\Settings\GeneralSettings::class,
|
||||
'App\Settings\InfluxDbSettings' => \App\Settings\InfluxDbSettings::class,
|
||||
'App\Settings\NotificationSettings' => \App\Settings\NotificationSettings::class,
|
||||
'App\Settings\ThresholdSettings' => \App\Settings\ThresholdSettings::class,
|
||||
@@ -943,9 +939,9 @@ namespace PHPSTORM_META {
|
||||
'composer' => \Illuminate\Support\Composer::class,
|
||||
'cookie' => \Illuminate\Cookie\CookieJar::class,
|
||||
'db' => \Illuminate\Database\DatabaseManager::class,
|
||||
'db.connection' => \Illuminate\Database\MySqlConnection::class,
|
||||
'db.connection' => \Illuminate\Database\SQLiteConnection::class,
|
||||
'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\SQLiteBuilder::class,
|
||||
'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class,
|
||||
'encrypter' => \Illuminate\Encryption\Encrypter::class,
|
||||
'events' => \Illuminate\Events\Dispatcher::class,
|
||||
@@ -986,7 +982,6 @@ namespace PHPSTORM_META {
|
||||
override(\Illuminate\Contracts\Container\Container::makeWith(0), map([
|
||||
'' => '@',
|
||||
'App\Settings\DataMigrationSettings' => \App\Settings\DataMigrationSettings::class,
|
||||
'App\Settings\GeneralSettings' => \App\Settings\GeneralSettings::class,
|
||||
'App\Settings\InfluxDbSettings' => \App\Settings\InfluxDbSettings::class,
|
||||
'App\Settings\NotificationSettings' => \App\Settings\NotificationSettings::class,
|
||||
'App\Settings\ThresholdSettings' => \App\Settings\ThresholdSettings::class,
|
||||
@@ -1186,9 +1181,9 @@ namespace PHPSTORM_META {
|
||||
'composer' => \Illuminate\Support\Composer::class,
|
||||
'cookie' => \Illuminate\Cookie\CookieJar::class,
|
||||
'db' => \Illuminate\Database\DatabaseManager::class,
|
||||
'db.connection' => \Illuminate\Database\MySqlConnection::class,
|
||||
'db.connection' => \Illuminate\Database\SQLiteConnection::class,
|
||||
'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\SQLiteBuilder::class,
|
||||
'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class,
|
||||
'encrypter' => \Illuminate\Encryption\Encrypter::class,
|
||||
'events' => \Illuminate\Events\Dispatcher::class,
|
||||
@@ -1229,7 +1224,6 @@ namespace PHPSTORM_META {
|
||||
override(\App::get(0), map([
|
||||
'' => '@',
|
||||
'App\Settings\DataMigrationSettings' => \App\Settings\DataMigrationSettings::class,
|
||||
'App\Settings\GeneralSettings' => \App\Settings\GeneralSettings::class,
|
||||
'App\Settings\InfluxDbSettings' => \App\Settings\InfluxDbSettings::class,
|
||||
'App\Settings\NotificationSettings' => \App\Settings\NotificationSettings::class,
|
||||
'App\Settings\ThresholdSettings' => \App\Settings\ThresholdSettings::class,
|
||||
@@ -1429,9 +1423,9 @@ namespace PHPSTORM_META {
|
||||
'composer' => \Illuminate\Support\Composer::class,
|
||||
'cookie' => \Illuminate\Cookie\CookieJar::class,
|
||||
'db' => \Illuminate\Database\DatabaseManager::class,
|
||||
'db.connection' => \Illuminate\Database\MySqlConnection::class,
|
||||
'db.connection' => \Illuminate\Database\SQLiteConnection::class,
|
||||
'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\SQLiteBuilder::class,
|
||||
'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class,
|
||||
'encrypter' => \Illuminate\Encryption\Encrypter::class,
|
||||
'events' => \Illuminate\Events\Dispatcher::class,
|
||||
@@ -1472,7 +1466,6 @@ namespace PHPSTORM_META {
|
||||
override(\App::make(0), map([
|
||||
'' => '@',
|
||||
'App\Settings\DataMigrationSettings' => \App\Settings\DataMigrationSettings::class,
|
||||
'App\Settings\GeneralSettings' => \App\Settings\GeneralSettings::class,
|
||||
'App\Settings\InfluxDbSettings' => \App\Settings\InfluxDbSettings::class,
|
||||
'App\Settings\NotificationSettings' => \App\Settings\NotificationSettings::class,
|
||||
'App\Settings\ThresholdSettings' => \App\Settings\ThresholdSettings::class,
|
||||
@@ -1672,9 +1665,9 @@ namespace PHPSTORM_META {
|
||||
'composer' => \Illuminate\Support\Composer::class,
|
||||
'cookie' => \Illuminate\Cookie\CookieJar::class,
|
||||
'db' => \Illuminate\Database\DatabaseManager::class,
|
||||
'db.connection' => \Illuminate\Database\MySqlConnection::class,
|
||||
'db.connection' => \Illuminate\Database\SQLiteConnection::class,
|
||||
'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\SQLiteBuilder::class,
|
||||
'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class,
|
||||
'encrypter' => \Illuminate\Encryption\Encrypter::class,
|
||||
'events' => \Illuminate\Events\Dispatcher::class,
|
||||
@@ -1715,7 +1708,6 @@ namespace PHPSTORM_META {
|
||||
override(\App::makeWith(0), map([
|
||||
'' => '@',
|
||||
'App\Settings\DataMigrationSettings' => \App\Settings\DataMigrationSettings::class,
|
||||
'App\Settings\GeneralSettings' => \App\Settings\GeneralSettings::class,
|
||||
'App\Settings\InfluxDbSettings' => \App\Settings\InfluxDbSettings::class,
|
||||
'App\Settings\NotificationSettings' => \App\Settings\NotificationSettings::class,
|
||||
'App\Settings\ThresholdSettings' => \App\Settings\ThresholdSettings::class,
|
||||
@@ -1915,9 +1907,9 @@ namespace PHPSTORM_META {
|
||||
'composer' => \Illuminate\Support\Composer::class,
|
||||
'cookie' => \Illuminate\Cookie\CookieJar::class,
|
||||
'db' => \Illuminate\Database\DatabaseManager::class,
|
||||
'db.connection' => \Illuminate\Database\MySqlConnection::class,
|
||||
'db.connection' => \Illuminate\Database\SQLiteConnection::class,
|
||||
'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\SQLiteBuilder::class,
|
||||
'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class,
|
||||
'encrypter' => \Illuminate\Encryption\Encrypter::class,
|
||||
'events' => \Illuminate\Events\Dispatcher::class,
|
||||
@@ -1958,7 +1950,6 @@ namespace PHPSTORM_META {
|
||||
override(\app(0), map([
|
||||
'' => '@',
|
||||
'App\Settings\DataMigrationSettings' => \App\Settings\DataMigrationSettings::class,
|
||||
'App\Settings\GeneralSettings' => \App\Settings\GeneralSettings::class,
|
||||
'App\Settings\InfluxDbSettings' => \App\Settings\InfluxDbSettings::class,
|
||||
'App\Settings\NotificationSettings' => \App\Settings\NotificationSettings::class,
|
||||
'App\Settings\ThresholdSettings' => \App\Settings\ThresholdSettings::class,
|
||||
@@ -2158,9 +2149,9 @@ namespace PHPSTORM_META {
|
||||
'composer' => \Illuminate\Support\Composer::class,
|
||||
'cookie' => \Illuminate\Cookie\CookieJar::class,
|
||||
'db' => \Illuminate\Database\DatabaseManager::class,
|
||||
'db.connection' => \Illuminate\Database\MySqlConnection::class,
|
||||
'db.connection' => \Illuminate\Database\SQLiteConnection::class,
|
||||
'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\SQLiteBuilder::class,
|
||||
'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class,
|
||||
'encrypter' => \Illuminate\Encryption\Encrypter::class,
|
||||
'events' => \Illuminate\Events\Dispatcher::class,
|
||||
@@ -2201,7 +2192,6 @@ namespace PHPSTORM_META {
|
||||
override(\resolve(0), map([
|
||||
'' => '@',
|
||||
'App\Settings\DataMigrationSettings' => \App\Settings\DataMigrationSettings::class,
|
||||
'App\Settings\GeneralSettings' => \App\Settings\GeneralSettings::class,
|
||||
'App\Settings\InfluxDbSettings' => \App\Settings\InfluxDbSettings::class,
|
||||
'App\Settings\NotificationSettings' => \App\Settings\NotificationSettings::class,
|
||||
'App\Settings\ThresholdSettings' => \App\Settings\ThresholdSettings::class,
|
||||
@@ -2401,9 +2391,9 @@ namespace PHPSTORM_META {
|
||||
'composer' => \Illuminate\Support\Composer::class,
|
||||
'cookie' => \Illuminate\Cookie\CookieJar::class,
|
||||
'db' => \Illuminate\Database\DatabaseManager::class,
|
||||
'db.connection' => \Illuminate\Database\MySqlConnection::class,
|
||||
'db.connection' => \Illuminate\Database\SQLiteConnection::class,
|
||||
'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\SQLiteBuilder::class,
|
||||
'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class,
|
||||
'encrypter' => \Illuminate\Encryption\Encrypter::class,
|
||||
'events' => \Illuminate\Events\Dispatcher::class,
|
||||
@@ -2444,7 +2434,6 @@ namespace PHPSTORM_META {
|
||||
override(\Psr\Container\ContainerInterface::get(0), map([
|
||||
'' => '@',
|
||||
'App\Settings\DataMigrationSettings' => \App\Settings\DataMigrationSettings::class,
|
||||
'App\Settings\GeneralSettings' => \App\Settings\GeneralSettings::class,
|
||||
'App\Settings\InfluxDbSettings' => \App\Settings\InfluxDbSettings::class,
|
||||
'App\Settings\NotificationSettings' => \App\Settings\NotificationSettings::class,
|
||||
'App\Settings\ThresholdSettings' => \App\Settings\ThresholdSettings::class,
|
||||
@@ -2644,9 +2633,9 @@ namespace PHPSTORM_META {
|
||||
'composer' => \Illuminate\Support\Composer::class,
|
||||
'cookie' => \Illuminate\Cookie\CookieJar::class,
|
||||
'db' => \Illuminate\Database\DatabaseManager::class,
|
||||
'db.connection' => \Illuminate\Database\MySqlConnection::class,
|
||||
'db.connection' => \Illuminate\Database\SQLiteConnection::class,
|
||||
'db.factory' => \Illuminate\Database\Connectors\ConnectionFactory::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\MySqlBuilder::class,
|
||||
'db.schema' => \Illuminate\Database\Schema\SQLiteBuilder::class,
|
||||
'db.transactions' => \Illuminate\Database\DatabaseTransactionsManager::class,
|
||||
'encrypter' => \Illuminate\Encryption\Encrypter::class,
|
||||
'events' => \Illuminate\Events\Dispatcher::class,
|
||||
|
||||
+194
-194
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Actions\Speedtests;
|
||||
|
||||
use App\Settings\GeneralSettings;
|
||||
use Cron\CronExpression;
|
||||
use Illuminate\Support\Arr;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
@@ -11,23 +10,27 @@ class RunScheduledSpeedtests
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle()
|
||||
public function handle(): void
|
||||
{
|
||||
$settings = new GeneralSettings();
|
||||
$cronExpression = new CronExpression(config('speedtest.schedule'));
|
||||
|
||||
/**
|
||||
* Ookla service
|
||||
*/
|
||||
$cronExpression = new CronExpression($settings->speedtest_schedule);
|
||||
|
||||
if ($cronExpression->isDue(now()->timezone($settings->timezone ?? 'UTC'))) {
|
||||
$serverId = null;
|
||||
|
||||
if (is_array($settings->speedtest_server) && count($settings->speedtest_server)) {
|
||||
$serverId = Arr::random($settings->speedtest_server);
|
||||
}
|
||||
|
||||
RunOoklaSpeedtest::run(serverId: $serverId, scheduled: true);
|
||||
if (! $cronExpression->isDue(now()->timezone(config('app.timezone')))) {
|
||||
return;
|
||||
}
|
||||
|
||||
$servers = array_filter(
|
||||
explode(',', config('speedtest.servers'))
|
||||
);
|
||||
|
||||
$serverId = null;
|
||||
|
||||
if (count($servers)) {
|
||||
$serverId = Arr::random($servers);
|
||||
}
|
||||
|
||||
RunOoklaSpeedtest::run(
|
||||
serverId: $serverId,
|
||||
scheduled: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
use function Laravel\Prompts\table;
|
||||
|
||||
class OoklaListServers extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'app:ookla-list-servers
|
||||
{search? : Search for a server by name}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Get a list of local Ookla speedtest servers.';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
$response = Http::retry(3, 250)->get(
|
||||
url: 'https://www.speedtest.net/api/js/servers',
|
||||
query: [
|
||||
'engine' => 'js',
|
||||
'https_functional' => true,
|
||||
'search' => $this->argument('search'),
|
||||
'limit' => 20, // 20 is the max returned by the api
|
||||
],
|
||||
);
|
||||
|
||||
if ($response->failed()) {
|
||||
$this->fail('There was an issue retrieving a list of speedtest servers, check the logs.');
|
||||
}
|
||||
|
||||
$fields = ['id', 'sponsor', 'name', 'country', 'distance'];
|
||||
|
||||
table(
|
||||
headers: $fields,
|
||||
rows: $response->collect()->select($fields),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands\Maintenance;
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Enums\ResultStatus;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Helpers\TimeZoneHelper;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Cron\CronExpression;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
use function Laravel\Prompts\confirm;
|
||||
use function Laravel\Prompts\text;
|
||||
|
||||
class UpdateGeneralSettings extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'app:update-general-settings';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Update the application\'s general settings.';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
$this->updateTimeZone($settings);
|
||||
$this->updateSchedule($settings);
|
||||
$this->resetSevers($settings);
|
||||
|
||||
$this->line('✅ Settings updated!');
|
||||
}
|
||||
|
||||
protected function resetSevers($settings): void
|
||||
{
|
||||
$confirmed = confirm(
|
||||
label: 'Do you want to reset the server list?',
|
||||
default: false,
|
||||
yes: 'Yes, reset it',
|
||||
no: 'No, keep it'
|
||||
);
|
||||
|
||||
if ($confirmed) {
|
||||
$settings->speedtest_server = [];
|
||||
|
||||
$settings->save();
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateSchedule($settings): void
|
||||
{
|
||||
$cron = text(
|
||||
label: 'What is the schedule?',
|
||||
placeholder: '0 * * * *',
|
||||
default: $settings->speedtest_schedule ?? '0 * * * *',
|
||||
required: true,
|
||||
validate: fn (string $value) => match (true) {
|
||||
! CronExpression::isValidExpression($value) => 'The schedule expression is invalid.',
|
||||
default => null
|
||||
}
|
||||
);
|
||||
|
||||
if ($cron) {
|
||||
$settings->speedtest_schedule = $cron;
|
||||
|
||||
$settings->save();
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateTimeZone($settings): void
|
||||
{
|
||||
$timezone = text(
|
||||
label: 'What is the time zone?',
|
||||
placeholder: 'UTC',
|
||||
default: $settings->timezone,
|
||||
required: true,
|
||||
validate: fn (string $value) => match (true) {
|
||||
! TimeZoneHelper::validate($value) => 'The time zone must be a valid time zone.',
|
||||
default => null
|
||||
}
|
||||
);
|
||||
|
||||
if ($timezone) {
|
||||
$settings->timezone = $timezone;
|
||||
|
||||
$settings->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ use App\Filament\Widgets\RecentPingChartWidget;
|
||||
use App\Filament\Widgets\RecentUploadChartWidget;
|
||||
use App\Filament\Widgets\RecentUploadLatencyChartWidget;
|
||||
use App\Filament\Widgets\StatsOverviewWidget;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\ActionGroup;
|
||||
use Filament\Notifications\Notification;
|
||||
@@ -37,11 +36,15 @@ class Dashboard extends BasePage
|
||||
->url(shouldOpenInNewTab: true, url: '/'),
|
||||
ActionGroup::make([
|
||||
Action::make('ookla speedtest')
|
||||
->action(function (GeneralSettings $settings) {
|
||||
->action(function () {
|
||||
$servers = array_filter(
|
||||
explode(',', config('speedtest.servers'))
|
||||
);
|
||||
|
||||
$serverId = null;
|
||||
|
||||
if (is_array($settings->speedtest_server) && count($settings->speedtest_server)) {
|
||||
$serverId = Arr::random($settings->speedtest_server);
|
||||
if (count($servers)) {
|
||||
$serverId = Arr::random($servers);
|
||||
}
|
||||
|
||||
RunOoklaSpeedtest::run(serverId: $serverId);
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Pages\Settings;
|
||||
|
||||
use App\Actions\GetOoklaSpeedtestServers;
|
||||
use App\Helpers\TimeZoneHelper;
|
||||
use App\Rules\Cron;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Pages\SettingsPage;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\HtmlString;
|
||||
|
||||
class GeneralPage extends SettingsPage
|
||||
{
|
||||
protected static ?string $navigationIcon = 'heroicon-o-cog';
|
||||
|
||||
protected static ?string $navigationGroup = 'Settings';
|
||||
|
||||
protected static ?int $navigationSort = 1;
|
||||
|
||||
protected static ?string $title = 'General';
|
||||
|
||||
protected static ?string $navigationLabel = 'General';
|
||||
|
||||
protected static string $settings = GeneralSettings::class;
|
||||
|
||||
public static function canAccess(): bool
|
||||
{
|
||||
return auth()->user()->is_admin;
|
||||
}
|
||||
|
||||
public static function shouldRegisterNavigation(): bool
|
||||
{
|
||||
return auth()->user()->is_admin;
|
||||
}
|
||||
|
||||
public function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\Grid::make([
|
||||
'default' => 1,
|
||||
])
|
||||
->schema([
|
||||
Forms\Components\Section::make('Site Settings')
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('site_name')
|
||||
->disabled()
|
||||
->helperText(new HtmlString('⚠️ DEPRECATED: Use <code>APP_NAME</code> environment variable.'))
|
||||
->columnSpanFull(),
|
||||
Forms\Components\Toggle::make('public_dashboard_enabled')
|
||||
->label('Public dashboard')
|
||||
->disabled()
|
||||
->helperText(new HtmlString('⚠️ DEPRECATED: Use <code>PUBLIC_DASHBOARD</code> environment variable.')),
|
||||
])
|
||||
->compact()
|
||||
->columns([
|
||||
'default' => 1,
|
||||
'md' => 2,
|
||||
]),
|
||||
|
||||
Forms\Components\Section::make('Time Zone Settings')
|
||||
->schema([
|
||||
Forms\Components\Select::make('timezone')
|
||||
->label('Time zone')
|
||||
->hint(new HtmlString('🔗<a href="https://docs.speedtest-tracker.dev/" target="_blank" rel="nofollow">Docs</a>'))
|
||||
->options(TimeZoneHelper::list())
|
||||
->searchable()
|
||||
->required(),
|
||||
Forms\Components\TextInput::make('time_format')
|
||||
->hint(new HtmlString('🔗<a href="https://www.php.net/manual/en/datetime.format.php" target="_blank" rel="nofollow">DateTime Format</a>'))
|
||||
->placeholder('M j, Y G:i:s')
|
||||
->maxLength(25)
|
||||
->required(),
|
||||
Forms\Components\Toggle::make('db_has_timezone')
|
||||
->label('Database has time zone')
|
||||
->helperText(new HtmlString('Enable if your database <strong>has</strong> a time zone already set.')),
|
||||
])
|
||||
->compact()
|
||||
->columns([
|
||||
'default' => 1,
|
||||
'md' => 2,
|
||||
]),
|
||||
|
||||
Forms\Components\Section::make('Speedtest Settings')
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('speedtest_schedule')
|
||||
->rules([new Cron()])
|
||||
->helperText('Leave empty to disable scheduled tests.')
|
||||
->hint(new HtmlString('🔗<a href="https://crontab.guru" target="_blank" rel="nofollow">Cron Generator</a>'))
|
||||
->nullable()
|
||||
->columnSpan(1),
|
||||
Forms\Components\TextInput::make('prune_results_older_than')
|
||||
->helperText('Set to zero to disable pruning.')
|
||||
->suffix('days')
|
||||
->numeric()
|
||||
->required()
|
||||
->minValue(0)
|
||||
->maxValue(9999)
|
||||
->columnSpan(1),
|
||||
Forms\Components\Select::make('speedtest_server')
|
||||
->label('Speedtest servers')
|
||||
->helperText('Leave empty to let the system pick the best server.')
|
||||
->maxItems(10)
|
||||
->multiple()
|
||||
->nullable()
|
||||
->searchable()
|
||||
->options(GetOoklaSpeedtestServers::run())
|
||||
->getSearchResultsUsing(fn (string $search): array => $this->getServerSearchOptions($search))
|
||||
->getOptionLabelsUsing(fn (array $values): array => $this->getServerLabels($values))
|
||||
->columnSpanFull(),
|
||||
])
|
||||
->compact()
|
||||
->columns([
|
||||
'default' => 1,
|
||||
'md' => 2,
|
||||
]),
|
||||
])
|
||||
->columnSpan('full'),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function getServerLabels(array $values): array
|
||||
{
|
||||
if (count($values) && is_null($values[0])) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return collect($values)->mapWithKeys(function (string $item, int $key) {
|
||||
return [$item => $item];
|
||||
})->toArray();
|
||||
}
|
||||
|
||||
protected function getServerSearchOptions(string $search): array
|
||||
{
|
||||
$response = Http::get(
|
||||
url: 'https://www.speedtest.net/api/js/servers',
|
||||
query: [
|
||||
'engine' => 'js',
|
||||
'search' => $search,
|
||||
'https_functional' => true,
|
||||
'limit' => 20,
|
||||
]
|
||||
);
|
||||
|
||||
if ($response->failed()) {
|
||||
return [
|
||||
'' => 'There was an error retrieving Speedtest servers',
|
||||
];
|
||||
}
|
||||
|
||||
if (! $response->collect()->count() && is_numeric($search)) {
|
||||
return collect([
|
||||
[
|
||||
'id' => $search,
|
||||
'name' => $search.' (Manually entered server)',
|
||||
],
|
||||
])->pluck('name', 'id')->toArray();
|
||||
}
|
||||
|
||||
return $response->collect()->mapWithKeys(function (array $item, int $key) {
|
||||
return [$item['id'] => $item['id'].': '.$item['name'].' ('.$item['sponsor'].')'];
|
||||
})->toArray();
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,9 @@ use App\Enums\ResultStatus;
|
||||
use App\Filament\Exports\ResultExporter;
|
||||
use App\Filament\Resources\ResultResource\Pages;
|
||||
use App\Helpers\Number;
|
||||
use App\Helpers\TimeZoneHelper;
|
||||
use App\Jobs\TruncateResults;
|
||||
use App\Models\Result;
|
||||
use App\Settings\DataMigrationSettings;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Carbon\Carbon;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
@@ -34,8 +32,6 @@ class ResultResource extends Resource
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\Grid::make([
|
||||
@@ -51,8 +47,8 @@ class ResultResource extends Resource
|
||||
->label('ID'),
|
||||
Forms\Components\TextInput::make('created_at')
|
||||
->label('Created')
|
||||
->afterStateHydrated(function (TextInput $component, $state) use ($settings) {
|
||||
$component->state(Carbon::parse($state)->timezone(TimeZoneHelper::displayTimeZone($settings))->format($settings->time_format ?? 'M j, Y G:i:s'));
|
||||
->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')
|
||||
@@ -120,8 +116,6 @@ class ResultResource extends Resource
|
||||
{
|
||||
$dataSettings = new DataMigrationSettings();
|
||||
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
return $table
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('id')
|
||||
@@ -225,14 +219,14 @@ class ResultResource extends Resource
|
||||
->toggledHiddenByDefault()
|
||||
->alignment(Alignment::Center),
|
||||
Tables\Columns\TextColumn::make('created_at')
|
||||
->dateTime($settings->time_format ?? 'M j, Y G:i:s')
|
||||
->timezone(TimeZoneHelper::displayTimeZone($settings))
|
||||
->dateTime(config('app.datetime_format'))
|
||||
->timezone(config('app.display_timezone'))
|
||||
->toggleable()
|
||||
->sortable()
|
||||
->alignment(Alignment::End),
|
||||
Tables\Columns\TextColumn::make('updated_at')
|
||||
->dateTime($settings->time_format ?? 'M j, Y G:i:s')
|
||||
->timezone(TimeZoneHelper::displayTimeZone($settings))
|
||||
->dateTime(config('app.datetime_format'))
|
||||
->timezone(config('app.display_timezone'))
|
||||
->toggleable()
|
||||
->toggledHiddenByDefault()
|
||||
->sortable()
|
||||
|
||||
@@ -6,9 +6,7 @@ use App\Enums\UserRole;
|
||||
use App\Filament\Resources\UserResource\Pages;
|
||||
use App\Filament\Resources\UserResource\Pages\CreateUser;
|
||||
use App\Filament\Resources\UserResource\Pages\EditUser;
|
||||
use App\Helpers\TimeZoneHelper;
|
||||
use App\Models\User;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\Resource;
|
||||
@@ -106,8 +104,6 @@ class UserResource extends Resource
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
return $table
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('id')
|
||||
@@ -120,12 +116,12 @@ class UserResource extends Resource
|
||||
->badge(),
|
||||
Tables\Columns\TextColumn::make('created_at')
|
||||
->alignEnd()
|
||||
->dateTime($settings->time_format ?? 'M j, Y G:i:s')
|
||||
->timezone(TimeZoneHelper::displayTimeZone($settings)),
|
||||
->dateTime(config('app.datetime_format'))
|
||||
->timezone(config('app.display_timezone')),
|
||||
Tables\Columns\TextColumn::make('updated_at')
|
||||
->alignEnd()
|
||||
->dateTime($settings->time_format ?? 'M j, Y G:i:s')
|
||||
->timezone(TimeZoneHelper::displayTimeZone($settings))
|
||||
->dateTime(config('app.datetime_format'))
|
||||
->timezone(config('app.display_timezone'))
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
])
|
||||
->filters([
|
||||
|
||||
@@ -4,9 +4,7 @@ namespace App\Filament\Widgets;
|
||||
|
||||
use App\Enums\ResultStatus;
|
||||
use App\Helpers\Number;
|
||||
use App\Helpers\TimeZoneHelper;
|
||||
use App\Models\Result;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Filament\Widgets\ChartWidget;
|
||||
|
||||
class RecentDownloadChartWidget extends ChartWidget
|
||||
@@ -35,8 +33,6 @@ class RecentDownloadChartWidget extends ChartWidget
|
||||
|
||||
protected function getData(): array
|
||||
{
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
$results = Result::query()
|
||||
->select(['id', 'download', 'created_at'])
|
||||
->where('status', '=', ResultStatus::Completed)
|
||||
@@ -65,7 +61,7 @@ class RecentDownloadChartWidget extends ChartWidget
|
||||
'tension' => 0.4,
|
||||
],
|
||||
],
|
||||
'labels' => $results->map(fn ($item) => $item->created_at->timezone(TimeZoneHelper::displayTimeZone($settings))->format('M d - G:i')),
|
||||
'labels' => $results->map(fn ($item) => $item->created_at->timezone(config('app.display_timezone'))->format('M. j - g:ia')),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Enums\ResultStatus;
|
||||
use App\Helpers\TimeZoneHelper;
|
||||
use App\Models\Result;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Filament\Widgets\ChartWidget;
|
||||
|
||||
class RecentDownloadLatencyChartWidget extends ChartWidget
|
||||
@@ -34,8 +32,6 @@ class RecentDownloadLatencyChartWidget extends ChartWidget
|
||||
|
||||
protected function getData(): array
|
||||
{
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
$results = Result::query()
|
||||
->select(['id', 'data', 'created_at'])
|
||||
->where('status', '=', ResultStatus::Completed)
|
||||
@@ -84,7 +80,7 @@ class RecentDownloadLatencyChartWidget extends ChartWidget
|
||||
'tension' => 0.4,
|
||||
],
|
||||
],
|
||||
'labels' => $results->map(fn ($item) => $item->created_at->timezone(TimeZoneHelper::displayTimeZone($settings))->format('M d - G:i')),
|
||||
'labels' => $results->map(fn ($item) => $item->created_at->timezone(config('app.display_timezone'))->format('M. j - g:ia')),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Enums\ResultStatus;
|
||||
use App\Helpers\TimeZoneHelper;
|
||||
use App\Models\Result;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Filament\Widgets\ChartWidget;
|
||||
|
||||
class RecentJitterChartWidget extends ChartWidget
|
||||
@@ -34,8 +32,6 @@ class RecentJitterChartWidget extends ChartWidget
|
||||
|
||||
protected function getData(): array
|
||||
{
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
$results = Result::query()
|
||||
->select(['id', 'data', 'created_at'])
|
||||
->where('status', '=', ResultStatus::Completed)
|
||||
@@ -84,7 +80,7 @@ class RecentJitterChartWidget extends ChartWidget
|
||||
'tension' => 0.4,
|
||||
],
|
||||
],
|
||||
'labels' => $results->map(fn ($item) => $item->created_at->timezone(TimeZoneHelper::displayTimeZone($settings))->format('M d - G:i')),
|
||||
'labels' => $results->map(fn ($item) => $item->created_at->timezone(config('app.display_timezone'))->format('M. j - g:ia')),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Enums\ResultStatus;
|
||||
use App\Helpers\TimeZoneHelper;
|
||||
use App\Models\Result;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Filament\Widgets\ChartWidget;
|
||||
|
||||
class RecentPingChartWidget extends ChartWidget
|
||||
@@ -34,8 +32,6 @@ class RecentPingChartWidget extends ChartWidget
|
||||
|
||||
protected function getData(): array
|
||||
{
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
$results = Result::query()
|
||||
->select(['id', 'ping', 'created_at'])
|
||||
->where('status', '=', ResultStatus::Completed)
|
||||
@@ -64,7 +60,7 @@ class RecentPingChartWidget extends ChartWidget
|
||||
'tension' => 0.4,
|
||||
],
|
||||
],
|
||||
'labels' => $results->map(fn ($item) => $item->created_at->timezone(TimeZoneHelper::displayTimeZone($settings))->format('M d - G:i')),
|
||||
'labels' => $results->map(fn ($item) => $item->created_at->timezone(config('app.display_timezone'))->format('M. j - g:ia')),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,7 @@ namespace App\Filament\Widgets;
|
||||
|
||||
use App\Enums\ResultStatus;
|
||||
use App\Helpers\Number;
|
||||
use App\Helpers\TimeZoneHelper;
|
||||
use App\Models\Result;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Filament\Widgets\ChartWidget;
|
||||
|
||||
class RecentUploadChartWidget extends ChartWidget
|
||||
@@ -35,8 +33,6 @@ class RecentUploadChartWidget extends ChartWidget
|
||||
|
||||
protected function getData(): array
|
||||
{
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
$results = Result::query()
|
||||
->select(['id', 'upload', 'created_at'])
|
||||
->where('status', '=', ResultStatus::Completed)
|
||||
@@ -65,7 +61,7 @@ class RecentUploadChartWidget extends ChartWidget
|
||||
'tension' => 0.4,
|
||||
],
|
||||
],
|
||||
'labels' => $results->map(fn ($item) => $item->created_at->timezone(TimeZoneHelper::displayTimeZone($settings))->format('M d - G:i')),
|
||||
'labels' => $results->map(fn ($item) => $item->created_at->timezone(config('app.display_timezone'))->format('M. j - g:ia')),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
namespace App\Filament\Widgets;
|
||||
|
||||
use App\Enums\ResultStatus;
|
||||
use App\Helpers\TimeZoneHelper;
|
||||
use App\Models\Result;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Filament\Widgets\ChartWidget;
|
||||
|
||||
class RecentUploadLatencyChartWidget extends ChartWidget
|
||||
@@ -34,8 +32,6 @@ class RecentUploadLatencyChartWidget extends ChartWidget
|
||||
|
||||
protected function getData(): array
|
||||
{
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
$results = Result::query()
|
||||
->select(['id', 'data', 'created_at'])
|
||||
->where('status', '=', ResultStatus::Completed)
|
||||
@@ -84,7 +80,7 @@ class RecentUploadLatencyChartWidget extends ChartWidget
|
||||
'tension' => 0.4,
|
||||
],
|
||||
],
|
||||
'labels' => $results->map(fn ($item) => $item->created_at->timezone(TimeZoneHelper::displayTimeZone($settings))->format('M d - G:i')),
|
||||
'labels' => $results->map(fn ($item) => $item->created_at->timezone(config('app.display_timezone'))->format('M. j - g:ia')),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Settings\GeneralSettings;
|
||||
use DateTimeZone;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class TimeZoneHelper
|
||||
{
|
||||
/**
|
||||
* Returns the display timezone
|
||||
*/
|
||||
public static function displayTimeZone(GeneralSettings $settings): string
|
||||
{
|
||||
// Don't translate to local time if the database already returns it.
|
||||
if ($settings->db_has_timezone) {
|
||||
return 'UTC';
|
||||
}
|
||||
|
||||
return $settings->timezone
|
||||
?? 'UTC';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of time zones with their offset from UTC.
|
||||
*/
|
||||
public static function list()
|
||||
{
|
||||
$seconds = 3600; // 1hr
|
||||
|
||||
return Cache::remember('timezones_list_collection', $seconds, function () {
|
||||
$timestamp = time();
|
||||
|
||||
foreach (timezone_identifiers_list() as $key => $value) {
|
||||
date_default_timezone_set($value);
|
||||
|
||||
$timezone[$value] = $value.' (UTC '.date('P', $timestamp).')';
|
||||
}
|
||||
|
||||
return collect($timezone)->sortKeys();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the time zone string provided.
|
||||
*
|
||||
* Ref: https://github.com/laravel/framework/blob/10.x/src/Illuminate/Validation/Concerns/ValidatesAttributes.php#L2406-L2420
|
||||
*/
|
||||
public static function validate($value, $parameters = [])
|
||||
{
|
||||
return in_array($value, timezone_identifiers_list(
|
||||
constant(DateTimeZone::class.'::'.Str::upper($parameters[0] ?? 'ALL')),
|
||||
isset($parameters[1]) ? Str::upper($parameters[1]) : null,
|
||||
), true);
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,8 @@ namespace App\Http\Controllers\API\Speedtest;
|
||||
|
||||
use App\Enums\ResultStatus;
|
||||
use App\Helpers\Number;
|
||||
use App\Helpers\TimeZoneHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Result;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class GetLatestController extends Controller
|
||||
@@ -28,8 +26,6 @@ class GetLatestController extends Controller
|
||||
], 404);
|
||||
}
|
||||
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
return response()->json([
|
||||
'message' => 'ok',
|
||||
'data' => [
|
||||
@@ -43,8 +39,8 @@ class GetLatestController extends Controller
|
||||
'url' => $latest->result_url,
|
||||
'scheduled' => $latest->scheduled,
|
||||
'failed' => $latest->status === ResultStatus::Failed,
|
||||
'created_at' => $latest->created_at->timezone(TimeZoneHelper::displayTimeZone($settings))->toISOString(true),
|
||||
'updated_at' => $latest->updated_at->timezone(TimeZoneHelper::displayTimeZone($settings))->toISOString(true),
|
||||
'created_at' => $latest->created_at->timezone(config('app.display_timezone'))->toISOString(true),
|
||||
'updated_at' => $latest->updated_at->timezone(config('app.display_timezone'))->toISOString(true),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\ResultStatus;
|
||||
use App\Models\Result;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class HomeController extends Controller
|
||||
@@ -14,8 +13,6 @@ class HomeController extends Controller
|
||||
*/
|
||||
public function __invoke(Request $request)
|
||||
{
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
if (! config('speedtest.public_dashboard')) {
|
||||
return redirect()->route('filament.admin.auth.login');
|
||||
}
|
||||
@@ -30,19 +27,7 @@ class HomeController extends Controller
|
||||
return view('get-started');
|
||||
}
|
||||
|
||||
/**
|
||||
* This jank needs to happen because some people like
|
||||
* to watch the world burn by setting a time zone
|
||||
* in their database instances.
|
||||
*/
|
||||
if ($settings->db_has_timezone) {
|
||||
date_default_timezone_set($settings->timezone ?? 'UTC');
|
||||
}
|
||||
|
||||
$diff = $latestResult->created_at->diffForHumans();
|
||||
|
||||
return view('dashboard', [
|
||||
'diff' => $diff,
|
||||
'latestResult' => $latestResult,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Debug;
|
||||
|
||||
use App\Models\Result;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Component;
|
||||
|
||||
#[Layout('layouts.debug')]
|
||||
class Timezone extends Component
|
||||
{
|
||||
public $settings;
|
||||
|
||||
public ?Result $latest;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
$this->settings = $settings->toArray();
|
||||
|
||||
$this->latest = Result::query()
|
||||
->latest()
|
||||
->first();
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.debug.timezone');
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\ResultStatus;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
@@ -83,9 +82,7 @@ class Result extends Model
|
||||
*/
|
||||
public function prunable(): Builder
|
||||
{
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
return static::where('created_at', '<=', now()->subDays($settings->prune_results_older_than));
|
||||
return static::where('created_at', '<=', now()->subDays(config('speedtest.prune_results_older_than')));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Settings;
|
||||
|
||||
use Spatie\LaravelSettings\Settings;
|
||||
|
||||
class GeneralSettings extends Settings
|
||||
{
|
||||
public bool $auth_enabled;
|
||||
|
||||
public int $prune_results_older_than;
|
||||
|
||||
public ?string $speedtest_schedule;
|
||||
|
||||
/** @var string[] */
|
||||
public $speedtest_server;
|
||||
|
||||
/**
|
||||
* @deprecated Use APP_NAME environment variable.
|
||||
*/
|
||||
public string $site_name;
|
||||
|
||||
public string $time_format;
|
||||
|
||||
public string $timezone;
|
||||
|
||||
public bool $db_has_timezone;
|
||||
|
||||
/**
|
||||
* @deprecated Use PUBLIC_DASHBOARD environment variable.
|
||||
*/
|
||||
public bool $public_dashboard_enabled;
|
||||
|
||||
public static function group(): string
|
||||
{
|
||||
return 'general';
|
||||
}
|
||||
}
|
||||
+1
-30
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
use App\Providers\AppServiceProvider;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Application;
|
||||
use Illuminate\Foundation\Configuration\Exceptions;
|
||||
use Illuminate\Foundation\Configuration\Middleware;
|
||||
@@ -12,6 +11,7 @@ return Application::configure(basePath: dirname(__DIR__))
|
||||
->withRouting(
|
||||
web: __DIR__.'/../routes/web.php',
|
||||
api: __DIR__.'/../routes/api.php',
|
||||
commands: __DIR__.'/../routes/console.php',
|
||||
)
|
||||
->withMiddleware(function (Middleware $middleware) {
|
||||
$middleware->redirectGuestsTo(fn () => route('admin/login'));
|
||||
@@ -30,33 +30,4 @@ return Application::configure(basePath: dirname(__DIR__))
|
||||
})
|
||||
->withExceptions(function (Exceptions $exceptions) {
|
||||
//
|
||||
})
|
||||
->withSchedule(function (Schedule $schedule) {
|
||||
$settings = app(\App\Settings\GeneralSettings::class);
|
||||
|
||||
/**
|
||||
* Checks if Result model records should be pruned.
|
||||
*/
|
||||
if ($settings->prune_results_older_than > 0) {
|
||||
$schedule->command('model:prune', [
|
||||
'--model' => [\App\Models\Result::class],
|
||||
])->daily();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checked for new versions weekly on Thursday because
|
||||
* I usually do releases on Thursday or Friday.
|
||||
*/
|
||||
$schedule->command(\App\Console\Commands\VersionChecker::class)->weeklyOn(5)
|
||||
->timezone($settings->timezone ?? 'UTC');
|
||||
|
||||
/**
|
||||
* Action to run scheduled speedtests.
|
||||
*/
|
||||
$schedule->call(function () {
|
||||
\App\Actions\Speedtests\RunScheduledSpeedtests::run();
|
||||
})
|
||||
->name('Run scheduled speedtests')
|
||||
->everyMinute()
|
||||
->when(! blank($settings->speedtest_schedule));
|
||||
})->create();
|
||||
|
||||
+1
-2
@@ -42,8 +42,7 @@
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"app/helpers.php",
|
||||
"app/Helpers/TimeZoneHelper.php"
|
||||
"app/helpers.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"App\\": "app/",
|
||||
|
||||
+4
-6
@@ -1,17 +1,15 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
return [
|
||||
|
||||
'name' => env('APP_NAME', 'Speedtest Tracker'),
|
||||
|
||||
'env' => env('APP_ENV', 'production'),
|
||||
|
||||
'datetime_format' => env('DATETIME_FORMAT', 'M. jS, Y g:ia'),
|
||||
|
||||
'display_timezone' => env('DISPLAY_TIMEZONE'),
|
||||
|
||||
'force_https' => env('FORCE_HTTPS', false),
|
||||
|
||||
'aliases' => Facade::defaultAliases()->merge([
|
||||
'TimeZoneHelper' => App\Helpers\TimeZoneHelper::class,
|
||||
])->toArray(),
|
||||
|
||||
];
|
||||
|
||||
@@ -13,6 +13,8 @@ return [
|
||||
*/
|
||||
'content_width' => env('CONTENT_WIDTH', '7xl'),
|
||||
|
||||
'prune_results_older_than' => env('PRUNE_RESULTS_OLDER_THAN', 0),
|
||||
|
||||
'public_dashboard' => env('PUBLIC_DASHBOARD', false),
|
||||
|
||||
/**
|
||||
@@ -24,4 +26,11 @@ return [
|
||||
|
||||
'results_polling' => env('RESULTS_POLLING', null),
|
||||
|
||||
/**
|
||||
* Speedtest settings.
|
||||
*/
|
||||
'schedule' => env('SPEEDTEST_SCHEDULE'),
|
||||
|
||||
'servers' => env('SPEEDTEST_SERVERS', ''),
|
||||
|
||||
];
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
use App\Settings\GeneralSettings;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
try {
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
$settings->speedtest_server = [$settings->speedtest_server];
|
||||
$settings->save();
|
||||
} catch (Throwable $th) {
|
||||
// This code is short lived as it'll be replaced with a jobs table...
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\UserRole;
|
||||
use App\Models\User;
|
||||
use App\Settings\DataMigrationSettings;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Filament\Notifications\Actions\Action;
|
||||
use Filament\Notifications\Notification;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
@@ -57,15 +57,7 @@ return new class extends Migration
|
||||
return;
|
||||
}
|
||||
|
||||
$settings = new GeneralSettings();
|
||||
|
||||
$settings->speedtest_schedule = '';
|
||||
|
||||
$settings->save();
|
||||
|
||||
$admins = User::select(['id', 'name', 'email', 'role'])
|
||||
->where('role', 'admin')
|
||||
->get();
|
||||
$admins = User::where('role', '=', UserRole::Admin)->get();
|
||||
|
||||
foreach ($admins as $user) {
|
||||
Notification::make()
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Spatie\LaravelSettings\Migrations\SettingsMigration;
|
||||
|
||||
class CreateGeneralSettings extends SettingsMigration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$this->migrator->add('general.auth_enabled', true);
|
||||
$this->migrator->add('general.site_name', 'Speedtest Tracker');
|
||||
$this->migrator->add('general.speedtest_schedule', '');
|
||||
$this->migrator->add('general.speedtest_server', null);
|
||||
$this->migrator->add('general.timezone', 'UTC');
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Spatie\LaravelSettings\Migrations\SettingsMigration;
|
||||
|
||||
class AddTimeFormatToGeneralSettings extends SettingsMigration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$this->migrator->add('general.time_format', 'M j, Y G:i:s');
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Spatie\LaravelSettings\Migrations\SettingsMigration;
|
||||
|
||||
return new class extends SettingsMigration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$this->migrator->add('general.content_width', '7xl');
|
||||
}
|
||||
};
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Spatie\LaravelSettings\Migrations\SettingsMigration;
|
||||
|
||||
return new class extends SettingsMigration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$this->migrator->add('general.public_dashboard_enabled', true);
|
||||
}
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Spatie\LaravelSettings\Migrations\SettingsMigration;
|
||||
|
||||
return new class extends SettingsMigration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$this->migrator->add('general.db_has_timezone', false);
|
||||
}
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Spatie\LaravelSettings\Migrations\SettingsMigration;
|
||||
|
||||
return new class extends SettingsMigration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$this->migrator->add('general.prune_results_older_than', 0);
|
||||
}
|
||||
};
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
@isset($latestResult)
|
||||
<div class="text-sm font-semibold leading-6 text-center col-span-full sm:text-base">
|
||||
Latest result: <time datetime="{{ $latestResult->created_at }}">{{ $diff }}</time>
|
||||
Latest result: <time title="{{ $latestResult->created_at->timezone(config('app.display_timezone'))->format(config('app.datetime_format')) }}" datetime="{{ $latestResult->created_at->timezone(config('app.display_timezone')) }}">{{ $latestResult->created_at->diffForHumans() }}</time>
|
||||
</div>
|
||||
@endisset
|
||||
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
<div wire:poll.1s>
|
||||
<x-slot name="header">
|
||||
<header>
|
||||
<div>
|
||||
<h1 class="text-xl font-bold tracking-tight text-gray-950 sm:text-2xl">Debug Time Zone - {{ config('app.name') }}</h1>
|
||||
|
||||
<p class="mt-1 text-sm font-medium">
|
||||
The purpose of this page is to help debut the current issues around time zones and local time. The table below displays an output of the applications current configuration.
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
</x-slot>
|
||||
|
||||
<div class="space-y-6">
|
||||
<div class="overflow-hidden bg-white shadow sm:rounded-md">
|
||||
<div class="p-4 bg-white border-b border-gray-200 sm:px-6">
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900">Timezone</h3>
|
||||
</div>
|
||||
|
||||
<ul role="list" class="divide-y divide-gray-200">
|
||||
<li class="px-4 py-4 sm:px-6">
|
||||
<p class="text-sm font-medium text-gray-900">PHP time zone</p>
|
||||
<p class="text-sm text-gray-500 truncate">{{ date_default_timezone_get() }}</p>
|
||||
</li>
|
||||
|
||||
<li class="px-4 py-4 sm:px-6">
|
||||
<p class="text-sm font-medium text-gray-900">App time zone</p>
|
||||
<p class="text-sm text-gray-500 truncate">{{ config('app.timezone') }}</p>
|
||||
</li>
|
||||
|
||||
<li class="px-4 py-4 sm:px-6">
|
||||
<p class="text-sm font-medium text-gray-900">Settings time zone</p>
|
||||
<p class="text-sm text-gray-500 truncate">{{ $settings['timezone'] }} ({{ \Carbon\Carbon::create($settings['timezone'])->format('P') }})</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="overflow-hidden bg-white shadow sm:rounded-md">
|
||||
<div class="p-4 bg-white border-b border-gray-200 sm:px-6">
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900">Time</h3>
|
||||
</div>
|
||||
|
||||
<ul role="list" class="divide-y divide-gray-200">
|
||||
<li class="px-4 py-4 sm:px-6">
|
||||
<p class="text-sm font-medium text-gray-900">UTC time</p>
|
||||
<p class="text-sm text-gray-500 truncate">{{ \Carbon\Carbon::now() }}</p>
|
||||
</li>
|
||||
|
||||
<li class="px-4 py-4 sm:px-6">
|
||||
<p class="text-sm font-medium text-gray-900">Local time</p>
|
||||
<p class="text-sm text-gray-500 truncate">{{ \Carbon\Carbon::now()->timezone($settings['timezone'] ?? 'UTC') }}</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@isset($latest)
|
||||
<div class="overflow-hidden bg-white shadow sm:rounded-md">
|
||||
<div class="p-4 bg-white border-b border-gray-200 sm:px-6">
|
||||
<h3 class="text-base font-semibold leading-6 text-gray-900">Latest result</h3>
|
||||
</div>
|
||||
|
||||
<ul role="list" class="divide-y divide-gray-200">
|
||||
<li class="px-4 py-4 sm:px-6">
|
||||
<p class="text-sm font-medium text-gray-900">Latest result ran at</p>
|
||||
<p class="text-sm text-gray-500 truncate">{{ $latest->created_at->timezone($settings['db_has_timezone'] ? null : $settings['timezone'] ?? 'UTC')->format('M. jS, Y h:i:s') }}</p>
|
||||
</li>
|
||||
|
||||
<li class="px-4 py-4 sm:px-6">
|
||||
<p class="text-sm font-medium text-gray-900">Diff for humans</p>
|
||||
<p class="text-sm text-gray-500 truncate">{{ $latest->created_at->diffForHumans() }}</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@endisset
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
use App\Actions\Speedtests\RunScheduledSpeedtests;
|
||||
use Illuminate\Support\Facades\Schedule;
|
||||
|
||||
/**
|
||||
* Checks if Result model records should be pruned.
|
||||
*/
|
||||
if (config('speedtest.prune_results_older_than') > 0) {
|
||||
Schedule::command('model:prune', [
|
||||
'--model' => [\App\Models\Result::class],
|
||||
])->daily();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checked for new versions weekly on Thursday because
|
||||
* I usually do releases on Thursday or Friday.
|
||||
*/
|
||||
Schedule::command('app:version')
|
||||
->weeklyOn(5);
|
||||
|
||||
/**
|
||||
* Action to run scheduled speedtests.
|
||||
*/
|
||||
Schedule::call(fn () => RunScheduledSpeedtests::run())
|
||||
->everyMinute()
|
||||
->when(! blank(config('speedtest.schedule')));
|
||||
Reference in New Issue
Block a user