Merge pull request #157 from henrywhitaker3/speedtest-error

Notification settings
This commit is contained in:
Henry Whitaker
2020-07-07 21:01:15 +01:00
committed by GitHub
32 changed files with 733 additions and 142748 deletions

View File

@@ -1,6 +1,6 @@
# Speedtest Tracker
[![Docker pulls](https://img.shields.io/docker/pulls/henrywhitaker3/speedtest-tracker?style=flat-square)](https://hub.docker.com/r/henrywhitaker3/speedtest-tracker) [![last_commit](https://img.shields.io/github/last-commit/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) [![issues](https://img.shields.io/github/issues/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/issues) [![commit_freq](https://img.shields.io/github/commit-activity/m/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) ![version](https://img.shields.io/badge/version-v1.7.4-success?style=flat-square) [![license](https://img.shields.io/github/license/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/blob/master/LICENSE)
[![Docker pulls](https://img.shields.io/docker/pulls/henrywhitaker3/speedtest-tracker?style=flat-square)](https://hub.docker.com/r/henrywhitaker3/speedtest-tracker) [![last_commit](https://img.shields.io/github/last-commit/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) [![issues](https://img.shields.io/github/issues/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/issues) [![commit_freq](https://img.shields.io/github/commit-activity/m/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) ![version](https://img.shields.io/badge/version-v1.7.5-success?style=flat-square) [![license](https://img.shields.io/github/license/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/blob/master/LICENSE)
This program runs a speedtest check every hour and graphs the results. The back-end is written in [Laravel](https://laravel.com/) and the front-end uses [React](https://reactjs.org/). It uses the [Ookla's speedtest cli](https://www.speedtest.net/apps/cli) package to get the data and uses [Chart.js](https://www.chartjs.org/) to plot the results.

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Console\Commands;
use App\Helpers\SettingsHelper;
use Illuminate\Console\Command;
class GetConfig extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'speedtest:config';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Get the application configuration';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$this->info(json_encode(SettingsHelper::getConfig(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
}
}

View File

@@ -0,0 +1,47 @@
<?php
namespace App\Console\Commands;
use App\Helpers\SettingsHelper;
use Illuminate\Console\Command;
class SetSlackWebhook extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'speedtest:slack {webhook : The slack webhook to store}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Set the slack webhook setting';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$webhook = $this->argument('webhook');
SettingsHelper::set('slack_webhook', $webhook);
$this->info('Slack webhook updated');
}
}

View File

@@ -0,0 +1,51 @@
<?php
namespace App\Console\Commands;
use App\Helpers\SettingsHelper;
use Illuminate\Console\Command;
class SetTelegramOptions extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'speedtest:telegram
{--bot= : The telegram bot token}
{--chat= : The telegram chat ID}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Set the telegram settings';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
$bot = $this->option('bot');
$chat = $this->option('chat');
SettingsHelper::set('telegram_bot_token', $bot);
SettingsHelper::set('telegram_chat_id', $chat);
$this->info('Telegram options updated');
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Console\Commands;
use App\Helpers\SettingsHelper;
use Illuminate\Console\Command;
class TestNotification extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'speedtest:notification';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Send test notifications to all notification agents';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return int
*/
public function handle()
{
SettingsHelper::testNotification();
}
}

View File

@@ -0,0 +1,38 @@
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class TestNotificationEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $agents;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($agents)
{
$this->agents = $agents;
}
/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Helpers;
use App\Events\TestNotificationEvent;
use App\Setting;
use Carbon\Carbon;
@@ -38,10 +39,11 @@ class SettingsHelper {
{
$setting = SettingsHelper::get($name);
if($value == false) {
$value = "0";
}
if($setting !== false) {
if($value == false) {
$value = "0";
}
$setting->value = $value;
$setting->save();
} else {
@@ -74,4 +76,75 @@ class SettingsHelper {
}
return $base;
}
/**
* Check whether a setting is defined in ENV vars or through DB
*
* @param string $key
* @return boolean
*/
public static function settingIsEditable(string $key)
{
// Try exact key
$val = exec('echo $' . $key);
if($val == "") {
return true;
}
// Try key all caps
$val = exec('echo $' . strtoupper($key));
if($val == "") {
return true;
}
return false;
}
/**
* Get the application config
*
* @return array
*/
public static function getConfig()
{
return [
'base' => SettingsHelper::getBase(),
'graphs' => [
'download_upload_graph_enabled' => SettingsHelper::get('download_upload_graph_enabled'),
'download_upload_graph_width' => SettingsHelper::get('download_upload_graph_width'),
'ping_graph_enabled' => SettingsHelper::get('ping_graph_enabled'),
'ping_graph_width' => SettingsHelper::get('ping_graph_width'),
'failure_graph_enabled' => SettingsHelper::get('failure_graph_enabled'),
'failure_graph_width' => SettingsHelper::get('failure_graph_width'),
],
'editable' => [
'slack_webhook' => SettingsHelper::settingIsEditable('slack_webhook'),
'telegram_bot_token' => SettingsHelper::settingIsEditable('telegram_bot_token'),
'telegram_chat_id' => SettingsHelper::settingIsEditable('telegram_chat_id'),
]
];
}
/**
* Send test notification to agents
*
* @param boolean|string $agent
* @return void
*/
public static function testNotification($agent = true)
{
$agents = [ 'slack', 'telegram' ];
if($agent === true) {
event(new TestNotificationEvent($agents));
return true;
}
if(in_array($agent, $agents)) {
event(new TestNotificationEvent([ $agent ]));
return true;
}
}
}

View File

@@ -6,6 +6,7 @@ use App\Helpers\SettingsHelper;
use App\Rules\Cron;
use App\Setting;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
class SettingsController extends Controller
@@ -100,7 +101,17 @@ class SettingsController extends Controller
], 422);
}
}
$setting = SettingsHelper::set($d['name'], $d['value']);
$setting = SettingsHelper::get($d['name']);
if($setting == false) {
$setting = SettingsHelper::set($d['name'], $d['value']);
} else if($setting->editable == true) {
$setting = SettingsHelper::set($d['name'], $d['value']);
} else {
continue;
}
array_push($settings, $setting);
}
@@ -117,18 +128,15 @@ class SettingsController extends Controller
*/
public function config()
{
return SettingsHelper::getConfig();
}
public function testNotification()
{
SettingsHelper::testNotification();
$config = [
'base' => SettingsHelper::getBase(),
'download_upload_graph_enabled' => SettingsHelper::get('download_upload_graph_enabled'),
'download_upload_graph_width' => SettingsHelper::get('download_upload_graph_width'),
'ping_graph_enabled' => SettingsHelper::get('ping_graph_enabled'),
'ping_graph_width' => SettingsHelper::get('ping_graph_width'),
'failure_graph_enabled' => SettingsHelper::get('failure_graph_enabled'),
'failure_graph_width' => SettingsHelper::get('failure_graph_width'),
];
return $config;
return response()->json([
'method' => 'test notificaiton agents'
], 200);
}
}

View File

@@ -37,9 +37,7 @@ class SpeedtestJob implements ShouldQueue
{
$output = SpeedtestHelper::output();
$speedtest = SpeedtestHelper::runSpeedtest($output, $this->scheduled);
Log::info($speedtest);
if($speedtest == false) {
Log::info('speedtest == false');
event(new SpeedtestFailedEvent());
} else {
event(new SpeedtestCompleteEvent($speedtest));

View File

@@ -34,9 +34,9 @@ class SpeedtestCompleteListener
{
if(SettingsHelper::get('speedtest_notifications')->value == true) {
$data = $event->speedtest;
if(env('SLACK_WEBHOOK')) {
if(SettingsHelper::get('slack_webhook')) {
try {
Notification::route('slack', env('SLACK_WEBHOOK'))
Notification::route('slack', SettingsHelper::get('slack_webhook')->value)
->notify(new SpeedtestCompleteSlack($data));
} catch(Exception $e) {
Log::notice('Your sleck webhook is invalid');
@@ -44,9 +44,10 @@ class SpeedtestCompleteListener
}
}
if(env('TELEGRAM_BOT_TOKEN') && env('TELEGRAM_CHAT_ID')) {
if(SettingsHelper::get('telegram_bot_token') && SettingsHelper::get('telegram_chat_id')) {
try {
Notification::route(TelegramChannel::class, env('TELEGRAM_CHAT_ID'))
config([ 'services.telegram-bot-api' => [ 'token' => SettingsHelper::get('telegram_bot_token')->value ] ]);
Notification::route(TelegramChannel::class, SettingsHelper::get('telegram_chat_id')->value)
->notify(new SpeedtestCompleteTelegram($data));
} catch(Exception $e) {
Log::notice('Your telegram settings are invalid');

View File

@@ -31,9 +31,9 @@ class SpeedtestFailedListener
*/
public function handle($event)
{
if(env('SLACK_WEBHOOK')) {
if(SettingsHelper::get('slack_webhook')) {
try {
Notification::route('slack', env('SLACK_WEBHOOK'))
Notification::route('slack', SettingsHelper::get('slack_webhook')->value)
->notify(new SpeedtestFailedSlack());
} catch(Exception $e) {
Log::notice('Your sleck webhook is invalid');
@@ -41,9 +41,10 @@ class SpeedtestFailedListener
}
}
if(env('TELEGRAM_BOT_TOKEN') && env('TELEGRAM_CHAT_ID')) {
if(SettingsHelper::get('telegram_bot_token') && SettingsHelper::get('telegram_chat_id')) {
try {
Notification::route(TelegramChannel::class, env('TELEGRAM_CHAT_ID'))
config([ 'services.telegram-bot-api' => [ 'token' => SettingsHelper::get('telegram_bot_token')->value ] ]);
Notification::route(TelegramChannel::class, SettingsHelper::get('telegram_chat_id')->value)
->notify(new SpeedtestFailedTelegram());
} catch(Exception $e) {
Log::notice('Your telegram settings are invalid');

View File

@@ -35,9 +35,9 @@ class SpeedtestOverviewListener
{
if(SettingsHelper::get('speedtest_overview_notification')->value == true) {
$data = SpeedtestHelper::last24Hours();
if(env('SLACK_WEBHOOK')) {
if(SettingsHelper::get('slack_webhook')) {
try {
Notification::route('slack', env('SLACK_WEBHOOK'))
Notification::route('slack', SettingsHelper::get('slack_webhook')->value)
->notify(new SpeedtestOverviewSlack($data));
} catch(Exception $e) {
Log::notice('Your sleck webhook is invalid');
@@ -45,9 +45,10 @@ class SpeedtestOverviewListener
}
}
if(env('TELEGRAM_BOT_TOKEN') && env('TELEGRAM_CHAT_ID')) {
if(SettingsHelper::get('telegram_bot_token') && SettingsHelper::get('telegram_chat_id')) {
try {
Notification::route(TelegramChannel::class, env('TELEGRAM_CHAT_ID'))
config([ 'services.telegram-bot-api' => [ 'token' => SettingsHelper::get('telegram_bot_token')->value ] ]);
Notification::route(TelegramChannel::class, SettingsHelper::get('telegram_chat_id')->value)
->notify(new SpeedtestOverviewTelegram($data));
} catch(Exception $e) {
Log::notice('Your telegram settings are invalid');

View File

@@ -0,0 +1,84 @@
<?php
namespace App\Listeners;
use App\Helpers\SettingsHelper;
use App\Notifications\TestSlackNotification;
use App\Notifications\TestTelegramNotification;
use Exception;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
use NotificationChannels\Telegram\TelegramChannel;
class TestNotificationListener
{
private $agents;
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param object $event
* @return void
*/
public function handle($event)
{
foreach($event->agents as $agent) {
if($agent == 'slack') {
$this->slackNotification();
}
if($agent == 'telegram') {
$this->telegramNotification();
}
}
}
/**
* Send a slack notification
*
* @return void
*/
private function slackNotification()
{
if(SettingsHelper::get('slack_webhook')) {
try {
Notification::route('slack', SettingsHelper::get('slack_webhook')->value)
->notify(new TestSlackNotification());
} catch(Exception $e) {
Log::notice('Your sleck webhook is invalid');
Log::notice($e);
}
}
}
/**
* Send a telegram notification
*
* @return void
*/
private function telegramNotification()
{
if(SettingsHelper::get('telegram_bot_token') && SettingsHelper::get('telegram_chat_id')) {
try {
config([ 'services.telegram-bot-api' => [ 'token' => SettingsHelper::get('telegram_bot_token')->value ] ]);
Notification::route(TelegramChannel::class, SettingsHelper::get('telegram_bot_token')->value)
->notify(new TestTelegramNotification());
} catch(Exception $e) {
Log::notice('Your telegram settings are invalid');
Log::notice($e);
}
}
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Notifications;
use App\Helpers\SettingsHelper;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
@@ -40,7 +41,7 @@ class SpeedtestCompleteTelegram extends Notification
}
/**
* Format tekegram notification
* Format telegram notification
*
* @param mixed $notifiable
* @return TelegramMessage
@@ -53,7 +54,7 @@ Ping: *$speedtest->ping*
Download: *$speedtest->download*
Upload: *$speedtest->upload*";
return TelegramMessage::create()
->to(env('TELEGRAM_CHAT_ID'))
->to(SettingsHelper::get('telegram_chat_id')->value)
->content($msg)
->options(['parse_mode' => 'Markdown']);
}

View File

@@ -2,6 +2,7 @@
namespace App\Notifications;
use App\Helpers\SettingsHelper;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
@@ -40,7 +41,7 @@ class SpeedtestFailedTelegram extends Notification implements ShouldQueue
{
$msg = "Error: something went wrong running your speedtest";
return TelegramMessage::create()
->to(env('TELEGRAM_CHAT_ID'))
->to(SettingsHelper::get('telegram_chat_id')->value)
->content($msg)
->options(['parse_mode' => 'Markdown']);
}

View File

@@ -2,6 +2,7 @@
namespace App\Notifications;
use App\Helpers\SettingsHelper;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
@@ -53,7 +54,7 @@ Average ping: *".$data["ping"]."*
Average download: *".$data["download"]."*
Average upload: *".$data["upload"]."*";
return TelegramMessage::create()
->to(env('TELEGRAM_CHAT_ID'))
->to(SettingsHelper::get('telegram_chat_id')->value)
->content($msg)
->options(['parse_mode' => 'Markdown']);
}

View File

@@ -0,0 +1,65 @@
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
class TestSlackNotification extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return [
'slack'
];
}
/**
* Format slack notification
*
* @param mixed $notifiable
* @return SlackMessage
*/
public function toSlack($notifiable)
{
return (new SlackMessage)
->warning()
->attachment(function ($attachment) {
$attachment->title('Test notification');
});
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View File

@@ -0,0 +1,67 @@
<?php
namespace App\Notifications;
use App\Helpers\SettingsHelper;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use NotificationChannels\Telegram\TelegramChannel;
use NotificationChannels\Telegram\TelegramMessage;
class TestTelegramNotification extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return [
TelegramChannel::class
];
}
/**
* Format tekegram notification
*
* @param mixed $notifiable
* @return TelegramMessage
*/
public function toTelegram($notifiable)
{
$msg = "Test notification";
return TelegramMessage::create()
->to(SettingsHelper::get('telegram_chat_id')->value)
->content($msg)
->options(['parse_mode' => 'Markdown']);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View File

@@ -5,9 +5,11 @@ namespace App\Providers;
use App\Events\SpeedtestCompleteEvent;
use App\Events\SpeedtestFailedEvent;
use App\Events\SpeedtestOverviewEvent;
use App\Events\TestNotificationEvent;
use App\Listeners\SpeedtestCompleteListener;
use App\Listeners\SpeedtestFailedListener;
use App\Listeners\SpeedtestOverviewListener;
use App\Listeners\TestNotificationListener;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
@@ -33,6 +35,9 @@ class EventServiceProvider extends ServiceProvider
SpeedtestFailedEvent::class => [
SpeedtestFailedListener::class
],
TestNotificationEvent::class => [
TestNotificationListener::class
]
];
/**

View File

@@ -2,6 +2,7 @@
namespace App;
use App\Helpers\SettingsHelper;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model
@@ -16,4 +17,11 @@ class Setting extends Model
];
protected $table = 'settings';
protected $attributes = [ 'editable' ];
public function getEditableAttribute()
{
return SettingsHelper::settingIsEditable($this->name);
}
}

View File

@@ -1,4 +1,14 @@
{
"1.7.5": [
{
"description": "Moved notification agent settings to DB",
"link": ""
},
{
"description": "Updated dependencies",
"link": ""
}
],
"1.7.4": [
{
"description": "Stopped failed tests appearing in graphs",

12
composer.lock generated
View File

@@ -1023,21 +1023,21 @@
},
{
"name": "laravel-notification-channels/telegram",
"version": "0.4.0",
"version": "0.4.1",
"source": {
"type": "git",
"url": "https://github.com/laravel-notification-channels/telegram.git",
"reference": "9e4bb2fbf1a7a06e8849fa2d50bf57fa7c4483e3"
"reference": "55a9d8bce07f456e0c675909dba9b21acda376d6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel-notification-channels/telegram/zipball/9e4bb2fbf1a7a06e8849fa2d50bf57fa7c4483e3",
"reference": "9e4bb2fbf1a7a06e8849fa2d50bf57fa7c4483e3",
"url": "https://api.github.com/repos/laravel-notification-channels/telegram/zipball/55a9d8bce07f456e0c675909dba9b21acda376d6",
"reference": "55a9d8bce07f456e0c675909dba9b21acda376d6",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/guzzle": "^6.2",
"guzzlehttp/guzzle": "^6.2 || ^7.0",
"illuminate/notifications": "^5.5 || ^6.0 || ^7.0",
"illuminate/support": "^5.5 || ^6.0 || ^7.0",
"php": ">=7.1"
@@ -1080,7 +1080,7 @@
"telegram notification",
"telegram notifications channel"
],
"time": "2020-06-02T06:05:27+00:00"
"time": "2020-07-06T19:01:02+00:00"
},
{
"name": "laravel/framework",

View File

@@ -7,7 +7,7 @@ return [
|--------------------------------------------------------------------------
*/
'version' => '1.7.4',
'version' => '1.7.5',
/*
|--------------------------------------------------------------------------

6
package-lock.json generated
View File

@@ -8917,9 +8917,9 @@
"dev": true
},
"sass": {
"version": "1.26.9",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.26.9.tgz",
"integrity": "sha512-t8AkRVi+xvba4yZiLWkJdgJHBFCB3Dh4johniQkPy9ywkgFHNasXFEFP+RG/F6LhQ+aoE4aX+IorIWQjS0esVw==",
"version": "1.26.10",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.26.10.tgz",
"integrity": "sha512-bzN0uvmzfsTvjz0qwccN1sPm2HxxpNI/Xa+7PlUEMS+nQvbyuEK7Y0qFqxlPHhiNHb1Ze8WQJtU31olMObkAMw==",
"dev": true,
"requires": {
"chokidar": ">=2.0.0 <4.0.0"

View File

@@ -21,7 +21,7 @@
"react": "^16.2.0",
"react-dom": "^16.2.0",
"resolve-url-loader": "^3.1.0",
"sass": "^1.26.9",
"sass": "^1.26.10",
"sass-loader": "^9.0.1"
},
"dependencies": {

10931
public/css/app.css vendored

File diff suppressed because one or more lines are too long

4
public/css/main.css vendored
View File

@@ -59,3 +59,7 @@
.home-graph {
height: 480px;
}
.form-control:disabled {
cursor: not-allowed;
}

131746
public/js/app.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -225,8 +225,7 @@ export default class HistoryGraph extends Component {
getData = (days = this.state.days) => {
Axios.get('api/settings/config')
.then((resp) => {
var data = resp.data;
console.log(data)
var data = resp.data.graphs;
this.setState({
graph_ul_dl_enabled: Boolean(Number(data.download_upload_graph_enabled.value)),
graph_ul_dl_width: data.download_upload_graph_width.value,
@@ -274,11 +273,6 @@ export default class HistoryGraph extends Component {
var failOptions = this.state.failOptions;
var days = this.state.days;
console.log(failData);
console.log(failOptions);
console.log(pingData);
console.log(pingOptions);
var graph_ul_dl_enabled = this.state.graph_ul_dl_enabled;
var graph_ul_dl_width = this.state.graph_ul_dl_width;
var graph_ping_enabled = this.state.graph_ping_enabled;

View File

@@ -12,7 +12,8 @@ export default class SettingWithModal extends Component {
title: this.props.title,
description: this.props.description,
settings: this.props.settings,
show: false
show: false,
autoClose: this.props.autoClose
}
}
@@ -40,7 +41,9 @@ export default class SettingWithModal extends Component {
Axios.post(url, data)
.then((resp) => {
toast.success(this.state.title + ' updated');
this.toggleShow();
if(this.state.autoClose) {
this.toggleShow();
}
})
.catch((err) => {
if(err.response.status == 422) {
@@ -111,51 +114,135 @@ export default class SettingWithModal extends Component {
var name = e.obj.name.split('_');
name[0] = this.ucfirst(name[0]);
name = name.join(' ');
if(e.obj.description == null) {
var sm = { span: 12 };
var md = { span: 12 };
} else {
var sm = { span: 12 };
var md = { span: 6 };
}
var readonly = false;
if(window.config.editable[e.obj.name] == false) {
readonly = true;
}
if(e.type == 'checkbox') {
return (
<Row key={e.obj.id} className="d-flex align-items-center">
<Col md={{ span: 6 }} sm={{ span: 12 }}>
<Col md={md} sm={sm}>
<Form.Group controlId={e.obj.name}>
<Form.Check type="checkbox" label={name} defaultChecked={Boolean(Number(e.obj.value))} onInput={this.updateValue} />
{readonly ?
<>
<Form.Check type="checkbox" disabled label={name} defaultChecked={Boolean(Number(e.obj.value))} onInput={this.updateValue} />
<Form.Text className="text-muted">This setting is defined as an env variable and is not editable.</Form.Text>
</>
:
<Form.Check type="checkbox" label={name} defaultChecked={Boolean(Number(e.obj.value))} onInput={this.updateValue} />
}
</Form.Group>
</Col>
<Col md={{ span: 6 }} sm={{ span: 12 }}>
<p>{e.obj.description}</p>
</Col>
{e.description == null &&
<Col md={md} sm={sm}>
<p>{e.obj.description}</p>
</Col>
}
</Row>
);
} else if(e.type == 'number') {
return (
<Row key={e.obj.id}>
<Col md={{ span: 6 }} sm={{ span: 12 }}>
<Col md={md} sm={sm}>
<Form.Group controlId={e.obj.name}>
<Form.Label>{name}</Form.Label>
<Form.Control type="number" min={e.min} max={e.max} defaultValue={e.obj.value} onInput={this.updateValue} />
{readonly ?
<>
<Form.Control type="number" disabled min={e.min} max={e.max} defaultValue={e.obj.value} onInput={this.updateValue} />
<Form.Text className="text-muted">This setting is defined as an env variable and is not editable.</Form.Text>
</>
:
<Form.Control type="number" min={e.min} max={e.max} defaultValue={e.obj.value} onInput={this.updateValue} />
}
</Form.Group>
</Col>
<Col md={{ span: 6 }} sm={{ span: 12 }}>
<p>{e.obj.description}</p>
{e.description == null &&
<Col md={md} sm={sm}>
<p>{e.obj.description}</p>
</Col>
}
</Row>
);
} else if(e.type == 'text') {
return (
<Row key={e.obj.id}>
<Col md={md} sm={sm}>
<Form.Group controlId={e.obj.name}>
<Form.Label>{name}</Form.Label>
{readonly ?
<>
<Form.Control type="text" disabled defaultValue={e.obj.value} onInput={this.updateValue} />
<Form.Text className="text-muted">This setting is defined as an env variable and is not editable.</Form.Text>
</>
:
<Form.Control type="text" defaultValue={e.obj.value} onInput={this.updateValue} />
}
</Form.Group>
</Col>
{e.description == null &&
<Col md={md} sm={sm}>
<p>{e.obj.description}</p>
</Col>
}
</Row>
);
} else if(e.type == 'select') {
return (
<Row key={e.obj.id}>
<Col md={{ span: 6 }} sm={{ span: 12 }}>
<Col md={md} sm={sm}>
<Form.Group controlId={e.obj.name}>
<Form.Label>{name}</Form.Label>
<Form.Control as="select" defaultValue={e.obj.value} onInput={this.updateValue}>
{e.options.map((e,i) => {
return (
<option key={i} value={e.value}>{e.name}</option>
)
})}
</Form.Control>
{readonly ?
<>
<Form.Control as="select" disabled defaultValue={e.obj.value} onInput={this.updateValue}>
{e.options.map((e,i) => {
return (
<option key={i} value={e.value}>{e.name}</option>
)
})}
</Form.Control>
<Form.Text className="text-muted">This setting is defined as an env variable and is not editable.</Form.Text>
</>
:
<Form.Control as="select" defaultValue={e.obj.value} onInput={this.updateValue}>
{e.options.map((e,i) => {
return (
<option key={i} value={e.value}>{e.name}</option>
)
})}
</Form.Control>
}
</Form.Group>
</Col>
<Col md={{ span: 6 }} sm={{ span: 12 }}>
<p>{e.obj.description}</p>
{e.description == null &&
<Col md={md} sm={sm}>
<p>{e.obj.description}</p>
</Col>
}
</Row>
)
} else if(e.type == 'button-get') {
return (
<Row key={e.obj.id}>
<Col md={md} sm={sm}>
<p>{name}</p>
<Button onClick={() => { Axios.get(e.url) }} >{name}</Button>
</Col>
{e.description == null &&
<Col md={md} sm={sm}>
<p>{e.obj.description}</p>
</Col>
}
</Row>
)
}

View File

@@ -61,7 +61,7 @@ export default class Settings extends Component {
<Setting name={e.server.name} value={e.server.value} description={e.server.description} />
</Col>
<Col lg={{ span: 4 }} md={{ span: 6 }} sm={{ span: 12 }}>
<SettingWithModal title="Graph settings" description="Control settings for the graphs." settings={[
<SettingWithModal title="Graph settings" description="Control settings for the graphs." autoClose={true} settings={[
{
obj: e.download_upload_graph_enabled,
type: 'checkbox'
@@ -119,7 +119,28 @@ export default class Settings extends Component {
]} />
</Col>
<Col lg={{ span: 4 }} md={{ span: 6 }} sm={{ span: 12 }}>
<SettingWithModal title="Notification settings" description="Control which types of notifications the server sends." settings={[
<SettingWithModal title="Notification settings" description="Control which types of notifications the server sends." autoClose={false} settings={[
{
obj: e.slack_webhook,
type: 'text'
},
{
obj: e.telegram_bot_token,
type: 'text'
},
{
obj: e.telegram_chat_id,
type: 'text'
},
{
obj: {
id: (Math.floor(Math.random() * 10000) + 1),
name: "Test notifications",
description: "After saving your updated notification settings, use this to check your settings are correct."
},
type: 'button-get',
url: 'api/settings/test-notification'
},
{
obj: e.speedtest_notifications,
type: 'checkbox'

View File

@@ -62,6 +62,8 @@ Route::group([
], function () {
Route::get('/config', 'SettingsController@config')
->name('settings.config');
Route::get('/test-notification', 'SettingsController@testNotification')
->name('settings.test_notification');
Route::get('/', 'SettingsController@index')
->name('settings.index');
Route::put('/', 'SettingsController@store')