From 4ef0303dff34df0712ff34bac8b7096dcce2bb73 Mon Sep 17 00:00:00 2001 From: Henry Whitaker Date: Tue, 7 Jul 2020 20:51:57 +0100 Subject: [PATCH] Moved notification settings to DB --- app/Console/Commands/GetConfig.php | 43 +++++ app/Console/Commands/SetSlackWebhook.php | 47 +++++ app/Console/Commands/SetTelegramOptions.php | 51 +++++ app/Console/Commands/TestNotification.php | 43 +++++ app/Events/TestNotificationEvent.php | 38 ++++ app/Helpers/SettingsHelper.php | 79 +++++++- app/Http/Controllers/SettingsController.php | 32 ++-- app/Jobs/SpeedtestJob.php | 2 - app/Listeners/SpeedtestCompleteListener.php | 9 +- app/Listeners/SpeedtestFailedListener.php | 9 +- app/Listeners/SpeedtestOverviewListener.php | 9 +- app/Listeners/TestNotificationListener.php | 84 ++++++++ .../SpeedtestCompleteTelegram.php | 5 +- app/Notifications/SpeedtestFailedTelegram.php | 3 +- .../SpeedtestOverviewTelegram.php | 3 +- app/Notifications/TestSlackNotification.php | 65 +++++++ .../TestTelegramNotification.php | 67 +++++++ app/Providers/EventServiceProvider.php | 5 + app/Setting.php | 8 + public/css/main.css | 4 + public/js/app.js | 179 +++++++++++++----- .../js/components/Graphics/HistoryGraph.js | 8 +- .../js/components/Home/SettingWithModal.js | 129 +++++++++++-- resources/js/components/Home/Settings.js | 25 ++- routes/api.php | 2 + 25 files changed, 837 insertions(+), 112 deletions(-) create mode 100644 app/Console/Commands/GetConfig.php create mode 100644 app/Console/Commands/SetSlackWebhook.php create mode 100644 app/Console/Commands/SetTelegramOptions.php create mode 100644 app/Console/Commands/TestNotification.php create mode 100644 app/Events/TestNotificationEvent.php create mode 100644 app/Listeners/TestNotificationListener.php create mode 100644 app/Notifications/TestSlackNotification.php create mode 100644 app/Notifications/TestTelegramNotification.php diff --git a/app/Console/Commands/GetConfig.php b/app/Console/Commands/GetConfig.php new file mode 100644 index 00000000..dbfbbf7b --- /dev/null +++ b/app/Console/Commands/GetConfig.php @@ -0,0 +1,43 @@ +info(json_encode(SettingsHelper::getConfig(), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)); + } +} diff --git a/app/Console/Commands/SetSlackWebhook.php b/app/Console/Commands/SetSlackWebhook.php new file mode 100644 index 00000000..f1fe25de --- /dev/null +++ b/app/Console/Commands/SetSlackWebhook.php @@ -0,0 +1,47 @@ +argument('webhook'); + + SettingsHelper::set('slack_webhook', $webhook); + + $this->info('Slack webhook updated'); + } +} diff --git a/app/Console/Commands/SetTelegramOptions.php b/app/Console/Commands/SetTelegramOptions.php new file mode 100644 index 00000000..c32715d1 --- /dev/null +++ b/app/Console/Commands/SetTelegramOptions.php @@ -0,0 +1,51 @@ +option('bot'); + $chat = $this->option('chat'); + + SettingsHelper::set('telegram_bot_token', $bot); + SettingsHelper::set('telegram_chat_id', $chat); + + $this->info('Telegram options updated'); + } +} diff --git a/app/Console/Commands/TestNotification.php b/app/Console/Commands/TestNotification.php new file mode 100644 index 00000000..c1796762 --- /dev/null +++ b/app/Console/Commands/TestNotification.php @@ -0,0 +1,43 @@ +agents = $agents; + } + + /** + * Get the channels the event should broadcast on. + * + * @return \Illuminate\Broadcasting\Channel|array + */ + public function broadcastOn() + { + return new PrivateChannel('channel-name'); + } +} diff --git a/app/Helpers/SettingsHelper.php b/app/Helpers/SettingsHelper.php index 801622f2..67803b53 100644 --- a/app/Helpers/SettingsHelper.php +++ b/app/Helpers/SettingsHelper.php @@ -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; + } + } } diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index bcfd9a72..7ac38c97 100644 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -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); } } diff --git a/app/Jobs/SpeedtestJob.php b/app/Jobs/SpeedtestJob.php index b1669ff7..8ed0e1bf 100644 --- a/app/Jobs/SpeedtestJob.php +++ b/app/Jobs/SpeedtestJob.php @@ -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)); diff --git a/app/Listeners/SpeedtestCompleteListener.php b/app/Listeners/SpeedtestCompleteListener.php index fddcdd65..47323746 100644 --- a/app/Listeners/SpeedtestCompleteListener.php +++ b/app/Listeners/SpeedtestCompleteListener.php @@ -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'); diff --git a/app/Listeners/SpeedtestFailedListener.php b/app/Listeners/SpeedtestFailedListener.php index 0a0ae6cc..8175d7b0 100644 --- a/app/Listeners/SpeedtestFailedListener.php +++ b/app/Listeners/SpeedtestFailedListener.php @@ -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'); diff --git a/app/Listeners/SpeedtestOverviewListener.php b/app/Listeners/SpeedtestOverviewListener.php index cd293d2e..7a67857b 100644 --- a/app/Listeners/SpeedtestOverviewListener.php +++ b/app/Listeners/SpeedtestOverviewListener.php @@ -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'); diff --git a/app/Listeners/TestNotificationListener.php b/app/Listeners/TestNotificationListener.php new file mode 100644 index 00000000..ba5a1f02 --- /dev/null +++ b/app/Listeners/TestNotificationListener.php @@ -0,0 +1,84 @@ +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); + } + } + } +} diff --git a/app/Notifications/SpeedtestCompleteTelegram.php b/app/Notifications/SpeedtestCompleteTelegram.php index b7cff04c..591d1117 100644 --- a/app/Notifications/SpeedtestCompleteTelegram.php +++ b/app/Notifications/SpeedtestCompleteTelegram.php @@ -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']); } diff --git a/app/Notifications/SpeedtestFailedTelegram.php b/app/Notifications/SpeedtestFailedTelegram.php index a521e28e..46443345 100644 --- a/app/Notifications/SpeedtestFailedTelegram.php +++ b/app/Notifications/SpeedtestFailedTelegram.php @@ -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']); } diff --git a/app/Notifications/SpeedtestOverviewTelegram.php b/app/Notifications/SpeedtestOverviewTelegram.php index c0d51298..3a8a2964 100644 --- a/app/Notifications/SpeedtestOverviewTelegram.php +++ b/app/Notifications/SpeedtestOverviewTelegram.php @@ -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']); } diff --git a/app/Notifications/TestSlackNotification.php b/app/Notifications/TestSlackNotification.php new file mode 100644 index 00000000..808f178a --- /dev/null +++ b/app/Notifications/TestSlackNotification.php @@ -0,0 +1,65 @@ +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 [ + // + ]; + } +} diff --git a/app/Notifications/TestTelegramNotification.php b/app/Notifications/TestTelegramNotification.php new file mode 100644 index 00000000..59980543 --- /dev/null +++ b/app/Notifications/TestTelegramNotification.php @@ -0,0 +1,67 @@ +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 [ + // + ]; + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index e34e5a20..b33e65d5 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -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 + ] ]; /** diff --git a/app/Setting.php b/app/Setting.php index 259965fc..d3ceb8db 100644 --- a/app/Setting.php +++ b/app/Setting.php @@ -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); + } } diff --git a/public/css/main.css b/public/css/main.css index 686715a4..433574e4 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -59,3 +59,7 @@ .home-graph { height: 480px; } + +.form-control:disabled { + cursor: not-allowed; +} diff --git a/public/js/app.js b/public/js/app.js index d55e7ffa..6b9d12a0 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -129337,8 +129337,7 @@ var HistoryGraph = /*#__PURE__*/function (_Component) { _defineProperty(_assertThisInitialized(_this), "getData", function () { var days = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this.state.days; axios__WEBPACK_IMPORTED_MODULE_2___default.a.get('api/settings/config').then(function (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)), @@ -129412,10 +129411,6 @@ var HistoryGraph = /*#__PURE__*/function (_Component) { var failData = this.state.failData; 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; @@ -130629,7 +130624,9 @@ var SettingWithModal = /*#__PURE__*/function (_Component) { axios__WEBPACK_IMPORTED_MODULE_3___default.a.post(url, data).then(function (resp) { react_toastify__WEBPACK_IMPORTED_MODULE_4__["toast"].success(_this.state.title + ' updated'); - _this.toggleShow(); + if (_this.state.autoClose) { + _this.toggleShow(); + } })["catch"](function (err) { if (err.response.status == 422) { react_toastify__WEBPACK_IMPORTED_MODULE_4__["toast"].error('Your input was invalid'); @@ -130682,7 +130679,8 @@ var SettingWithModal = /*#__PURE__*/function (_Component) { title: _this.props.title, description: _this.props.description, settings: _this.props.settings, - show: false + show: false, + autoClose: _this.props.autoClose }; return _this; } @@ -130716,71 +130714,125 @@ var SettingWithModal = /*#__PURE__*/function (_Component) { name[0] = _this2.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 /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Row"], { key: e.obj.id, className: "d-flex align-items-center" }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Col"], { - md: { - span: 6 - }, - sm: { - span: 12 - } + md: md, + sm: sm }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Group, { controlId: e.obj.name - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Check, { + }, readonly ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react__WEBPACK_IMPORTED_MODULE_0___default.a.Fragment, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Check, { + type: "checkbox", + disabled: true, + label: name, + defaultChecked: Boolean(Number(e.obj.value)), + onInput: _this2.updateValue + }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Text, { + className: "text-muted" + }, "This setting is defined as an env variable and is not editable.")) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Check, { type: "checkbox", label: name, defaultChecked: Boolean(Number(e.obj.value)), onInput: _this2.updateValue - }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Col"], { - md: { - span: 6 - }, - sm: { - span: 12 - } + }))), e.description == null && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Col"], { + md: md, + sm: sm }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", null, e.obj.description))); } else if (e.type == 'number') { return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Row"], { key: e.obj.id }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Col"], { - md: { - span: 6 - }, - sm: { - span: 12 - } + md: md, + sm: sm }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Group, { controlId: e.obj.name - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Label, null, name), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Control, { + }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Label, null, name), readonly ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react__WEBPACK_IMPORTED_MODULE_0___default.a.Fragment, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Control, { + type: "number", + disabled: true, + min: e.min, + max: e.max, + defaultValue: e.obj.value, + onInput: _this2.updateValue + }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Text, { + className: "text-muted" + }, "This setting is defined as an env variable and is not editable.")) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Control, { type: "number", min: e.min, max: e.max, defaultValue: e.obj.value, onInput: _this2.updateValue - }))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Col"], { - md: { - span: 6 - }, - sm: { - span: 12 - } + }))), e.description == null && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Col"], { + md: md, + sm: sm + }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", null, e.obj.description))); + } else if (e.type == 'text') { + return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Row"], { + key: e.obj.id + }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Col"], { + md: md, + sm: sm + }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Group, { + controlId: e.obj.name + }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Label, null, name), readonly ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react__WEBPACK_IMPORTED_MODULE_0___default.a.Fragment, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Control, { + type: "text", + disabled: true, + defaultValue: e.obj.value, + onInput: _this2.updateValue + }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Text, { + className: "text-muted" + }, "This setting is defined as an env variable and is not editable.")) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Control, { + type: "text", + defaultValue: e.obj.value, + onInput: _this2.updateValue + }))), e.description == null && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Col"], { + md: md, + sm: sm }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", null, e.obj.description))); } else if (e.type == 'select') { return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Row"], { key: e.obj.id }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Col"], { - md: { - span: 6 - }, - sm: { - span: 12 - } + md: md, + sm: sm }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Group, { controlId: e.obj.name - }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Label, null, name), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Control, { + }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Label, null, name), readonly ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react__WEBPACK_IMPORTED_MODULE_0___default.a.Fragment, null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Control, { + as: "select", + disabled: true, + defaultValue: e.obj.value, + onInput: _this2.updateValue + }, e.options.map(function (e, i) { + return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("option", { + key: i, + value: e.value + }, e.name); + })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Text, { + className: "text-muted" + }, "This setting is defined as an env variable and is not editable.")) : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Form"].Control, { as: "select", defaultValue: e.obj.value, onInput: _this2.updateValue @@ -130789,13 +130841,23 @@ var SettingWithModal = /*#__PURE__*/function (_Component) { key: i, value: e.value }, e.name); - })))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Col"], { - md: { - span: 6 - }, - sm: { - span: 12 + })))), e.description == null && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Col"], { + md: md, + sm: sm + }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", null, e.obj.description))); + } else if (e.type == 'button-get') { + return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Row"], { + key: e.obj.id + }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Col"], { + md: md, + sm: sm + }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", null, name), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Button"], { + onClick: function onClick() { + axios__WEBPACK_IMPORTED_MODULE_3___default.a.get(e.url); } + }, name)), e.description == null && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Col"], { + md: md, + sm: sm }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("p", null, e.obj.description))); } }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(react_bootstrap__WEBPACK_IMPORTED_MODULE_2__["Button"], { @@ -130952,6 +131014,7 @@ var Settings = /*#__PURE__*/function (_Component) { }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_SettingWithModal__WEBPACK_IMPORTED_MODULE_6__["default"], { title: "Graph settings", description: "Control settings for the graphs.", + autoClose: true, settings: [{ obj: e.download_upload_graph_enabled, type: 'checkbox' @@ -131005,7 +131068,25 @@ var Settings = /*#__PURE__*/function (_Component) { }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_SettingWithModal__WEBPACK_IMPORTED_MODULE_6__["default"], { 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' }, { diff --git a/resources/js/components/Graphics/HistoryGraph.js b/resources/js/components/Graphics/HistoryGraph.js index 2762a8f7..0893f02e 100644 --- a/resources/js/components/Graphics/HistoryGraph.js +++ b/resources/js/components/Graphics/HistoryGraph.js @@ -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; diff --git a/resources/js/components/Home/SettingWithModal.js b/resources/js/components/Home/SettingWithModal.js index 28ba5b0a..891cda6c 100644 --- a/resources/js/components/Home/SettingWithModal.js +++ b/resources/js/components/Home/SettingWithModal.js @@ -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 ( - + - + {readonly ? + <> + + This setting is defined as an env variable and is not editable. + + : + + } - -

{e.obj.description}

- + {e.description == null && + +

{e.obj.description}

+ + }
); } else if(e.type == 'number') { return ( - + {name} - + {readonly ? + <> + + This setting is defined as an env variable and is not editable. + + : + + } - -

{e.obj.description}

+ {e.description == null && + +

{e.obj.description}

+ + } +
+ ); + } else if(e.type == 'text') { + return ( + + + + {name} + {readonly ? + <> + + This setting is defined as an env variable and is not editable. + + : + + } + + {e.description == null && + +

{e.obj.description}

+ + }
); } else if(e.type == 'select') { return ( - + {name} - - {e.options.map((e,i) => { - return ( - - ) - })} - + {readonly ? + <> + + {e.options.map((e,i) => { + return ( + + ) + })} + + This setting is defined as an env variable and is not editable. + + : + + {e.options.map((e,i) => { + return ( + + ) + })} + + } - -

{e.obj.description}

+ {e.description == null && + +

{e.obj.description}

+ + } +
+ ) + } else if(e.type == 'button-get') { + return ( + + +

{name}

+ + {e.description == null && + +

{e.obj.description}

+ + }
) } diff --git a/resources/js/components/Home/Settings.js b/resources/js/components/Home/Settings.js index 09d54431..1098adff 100644 --- a/resources/js/components/Home/Settings.js +++ b/resources/js/components/Home/Settings.js @@ -61,7 +61,7 @@ export default class Settings extends Component { - - name('settings.config'); + Route::get('/test-notification', 'SettingsController@testNotification') + ->name('settings.test_notification'); Route::get('/', 'SettingsController@index') ->name('settings.index'); Route::put('/', 'SettingsController@store')