mirror of
https://github.com/henrywhitaker3/Speedtest-Tracker.git
synced 2025-12-24 06:28:27 +01:00
Added code for notifications changes
- Toggle for notification types - Custom time for overview
This commit is contained in:
46
app/Console/Commands/SpeedtestOverviewCommand.php
Normal file
46
app/Console/Commands/SpeedtestOverviewCommand.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Events\SpeedtestOverviewEvent;
|
||||||
|
use App\Helpers\SpeedtestHelper;
|
||||||
|
use App\Notifications\SpeedtestOverviewSlack;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\Notification;
|
||||||
|
|
||||||
|
class SpeedtestOverviewCommand extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'speedtest:overview';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Trigger a speedtest overview event';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
event(new SpeedtestOverviewEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,9 +37,6 @@ class SpeedtestVersionCommand extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$this->info('Speedtest Tracker');
|
$this->info('Speedtest Tracker v' . config('speedtest.version'));
|
||||||
$this->info('Author: Henry Whitaker');
|
|
||||||
$this->info('');
|
|
||||||
$this->info('Installed version v' . config('speedtest.version'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Console;
|
namespace App\Console;
|
||||||
|
|
||||||
|
use App\Events\SpeedtestOverviewEvent;
|
||||||
use App\Helpers\SettingsHelper;
|
use App\Helpers\SettingsHelper;
|
||||||
use App\Helpers\SpeedtestHelper;
|
use App\Helpers\SpeedtestHelper;
|
||||||
use App\Jobs\SpeedtestJob;
|
use App\Jobs\SpeedtestJob;
|
||||||
@@ -28,6 +29,7 @@ class Kernel extends ConsoleKernel
|
|||||||
protected function schedule(Schedule $schedule)
|
protected function schedule(Schedule $schedule)
|
||||||
{
|
{
|
||||||
$schedule->job(new SpeedtestJob)->cron(SettingsHelper::get('schedule')['value']);
|
$schedule->job(new SpeedtestJob)->cron(SettingsHelper::get('schedule')['value']);
|
||||||
|
$schedule->command('speedtest:overview')->cron('0 ' . SettingsHelper::get('speedtest_overview_time')->value . ' * * *');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
36
app/Events/SpeedtestOverviewEvent.php
Normal file
36
app/Events/SpeedtestOverviewEvent.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?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 SpeedtestOverviewEvent
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the channels the event should broadcast on.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Broadcasting\Channel|array
|
||||||
|
*/
|
||||||
|
public function broadcastOn()
|
||||||
|
{
|
||||||
|
return new PrivateChannel('channel-name');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,12 +5,9 @@ namespace App\Helpers;
|
|||||||
use App\Speedtest;
|
use App\Speedtest;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Exception;
|
use Exception;
|
||||||
use GuzzleHttp\Client;
|
use Illuminate\Support\Facades\DB;
|
||||||
use GuzzleHttp\Psr7\Request;
|
|
||||||
use Illuminate\Support\Facades\Cache;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use JsonException;
|
use JsonException;
|
||||||
use SimpleXMLElement;
|
|
||||||
|
|
||||||
class SpeedtestHelper {
|
class SpeedtestHelper {
|
||||||
|
|
||||||
@@ -70,6 +67,22 @@ class SpeedtestHelper {
|
|||||||
return shell_exec($binPath . ' -f json');
|
return shell_exec($binPath . ' -f json');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a 24 hour average of speedtest results
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function last24Hours()
|
||||||
|
{
|
||||||
|
$t = Carbon::now()->subDay();
|
||||||
|
$s = Speedtest::select(DB::raw('AVG(ping) as ping, AVG(download) as download, AVG(upload) as upload'))
|
||||||
|
->where('created_at', '>=', $t)
|
||||||
|
->first()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
return $s;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts bytes/s to Mbps
|
* Converts bytes/s to Mbps
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -67,6 +67,49 @@ class SettingsController extends Controller
|
|||||||
], 200);
|
], 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bulk store/update a setting
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function bulkStore(Request $request)
|
||||||
|
{
|
||||||
|
$rule = [
|
||||||
|
'data' => [ 'array', 'required' ],
|
||||||
|
'data.*.name' => [ 'string', 'required' ],
|
||||||
|
'data.*.value' => [ 'required' ],
|
||||||
|
];
|
||||||
|
|
||||||
|
$validator = Validator::make($request->all(), $rule);
|
||||||
|
if($validator->fails()) {
|
||||||
|
return response()->json([
|
||||||
|
'method' => 'Bulk store a setting',
|
||||||
|
'error' => $validator->errors()
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
$settings = [];
|
||||||
|
foreach($request->data as $d) {
|
||||||
|
if($d['name'] == 'speedtest_overview_time') {
|
||||||
|
$ok = [ '00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23' ];
|
||||||
|
if(!in_array($d['value'], $ok)) {
|
||||||
|
return response()->json([
|
||||||
|
'method' => 'Bulk store a setting',
|
||||||
|
'error' => 'Invalid speedtest_overview_time value'
|
||||||
|
], 422);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$setting = SettingsHelper::set($d['name'], $d['value']);
|
||||||
|
array_push($settings, $setting);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'method' => 'Bulk store a setting',
|
||||||
|
'data' => $settings,
|
||||||
|
], 200);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns instance config
|
* Returns instance config
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Listeners;
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Helpers\SettingsHelper;
|
||||||
use App\Notifications\SpeedtestCompleteSlack;
|
use App\Notifications\SpeedtestCompleteSlack;
|
||||||
use App\Notifications\SpeedtestCompleteTelegram;
|
use App\Notifications\SpeedtestCompleteTelegram;
|
||||||
use Exception;
|
use Exception;
|
||||||
@@ -31,6 +32,7 @@ class SpeedtestCompleteListener
|
|||||||
*/
|
*/
|
||||||
public function handle($event)
|
public function handle($event)
|
||||||
{
|
{
|
||||||
|
if(SettingsHelper::get('speedtest_notifications')->value == true) {
|
||||||
$data = $event->speedtest;
|
$data = $event->speedtest;
|
||||||
if(env('SLACK_WEBHOOK')) {
|
if(env('SLACK_WEBHOOK')) {
|
||||||
try {
|
try {
|
||||||
@@ -53,3 +55,4 @@ class SpeedtestCompleteListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
59
app/Listeners/SpeedtestOverviewListener.php
Normal file
59
app/Listeners/SpeedtestOverviewListener.php
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Helpers\SettingsHelper;
|
||||||
|
use App\Helpers\SpeedtestHelper;
|
||||||
|
use App\Notifications\SpeedtestOverviewSlack;
|
||||||
|
use App\Notifications\SpeedtestOverviewTelegram;
|
||||||
|
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 SpeedtestOverviewListener
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create the event listener.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the event.
|
||||||
|
*
|
||||||
|
* @param object $event
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle($event)
|
||||||
|
{
|
||||||
|
if(SettingsHelper::get('speedtest_overview_notification')->value == true) {
|
||||||
|
$data = SpeedtestHelper::last24Hours();
|
||||||
|
if(env('SLACK_WEBHOOK')) {
|
||||||
|
try {
|
||||||
|
Notification::route('slack', env('SLACK_WEBHOOK'))
|
||||||
|
->notify(new SpeedtestOverviewSlack($data));
|
||||||
|
} catch(Exception $e) {
|
||||||
|
Log::notice('Your sleck webhook is invalid');
|
||||||
|
Log::notice($e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(env('TELEGRAM_BOT_TOKEN') && env('TELEGRAM_CHAT_ID')) {
|
||||||
|
try {
|
||||||
|
Notification::route(TelegramChannel::class, env('TELEGRAM_CHAT_ID'))
|
||||||
|
->notify(new SpeedtestOverviewTelegram($data));
|
||||||
|
} catch(Exception $e) {
|
||||||
|
Log::notice('Your telegram settings are invalid');
|
||||||
|
Log::notice($e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
74
app/Notifications/SpeedtestOverviewSlack.php
Normal file
74
app/Notifications/SpeedtestOverviewSlack.php
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<?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 SpeedtestOverviewSlack extends Notification
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new notification instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($data)
|
||||||
|
{
|
||||||
|
$data['ping'] = number_format((float)$data['ping'], 1, '.', '');
|
||||||
|
$data['download'] = number_format((float)$data['download'], 1, '.', '');
|
||||||
|
$data['upload'] = number_format((float)$data['upload'], 1, '.', '');
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
$data = $this->data;
|
||||||
|
return (new SlackMessage)
|
||||||
|
->warning()
|
||||||
|
->attachment(function ($attachment) use ($data) {
|
||||||
|
$attachment->title('Speedtest Daily Overview')
|
||||||
|
->fields([
|
||||||
|
'Average ping' => $data['ping'] . ' ms',
|
||||||
|
'Average download' => $data['download'] . ' Mbit/s',
|
||||||
|
'Average upload' => $data['upload'] . ' Mbit/s',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the array representation of the notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($notifiable)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
73
app/Notifications/SpeedtestOverviewTelegram.php
Normal file
73
app/Notifications/SpeedtestOverviewTelegram.php
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Notifications;
|
||||||
|
|
||||||
|
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 SpeedtestOverviewTelegram extends Notification
|
||||||
|
{
|
||||||
|
use Queueable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new notification instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($data)
|
||||||
|
{
|
||||||
|
$data['ping'] = number_format((float)$data['ping'], 1, '.', '');
|
||||||
|
$data['download'] = number_format((float)$data['download'], 1, '.', '');
|
||||||
|
$data['upload'] = number_format((float)$data['upload'], 1, '.', '');
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
{
|
||||||
|
$data = $this->data;
|
||||||
|
$msg = "*Speedtest Daily Overview*
|
||||||
|
Average ping: *".$data["ping"]."*
|
||||||
|
Average download: *".$data["download"]."*
|
||||||
|
Average upload: *".$data["upload"]."*";
|
||||||
|
return TelegramMessage::create()
|
||||||
|
->to(env('TELEGRAM_CHAT_ID'))
|
||||||
|
->content($msg)
|
||||||
|
->options(['parse_mode' => 'Markdown']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the array representation of the notification.
|
||||||
|
*
|
||||||
|
* @param mixed $notifiable
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function toArray($notifiable)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,9 @@
|
|||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use App\Events\SpeedtestCompleteEvent;
|
use App\Events\SpeedtestCompleteEvent;
|
||||||
|
use App\Events\SpeedtestOverviewEvent;
|
||||||
use App\Listeners\SpeedtestCompleteListener;
|
use App\Listeners\SpeedtestCompleteListener;
|
||||||
|
use App\Listeners\SpeedtestOverviewListener;
|
||||||
use Illuminate\Auth\Events\Registered;
|
use Illuminate\Auth\Events\Registered;
|
||||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||||
@@ -23,6 +25,9 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
SpeedtestCompleteEvent::class => [
|
SpeedtestCompleteEvent::class => [
|
||||||
SpeedtestCompleteListener::class,
|
SpeedtestCompleteListener::class,
|
||||||
],
|
],
|
||||||
|
SpeedtestOverviewEvent::class => [
|
||||||
|
SpeedtestOverviewListener::class
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Setting;
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddNotificationsSettings extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Setting::create([
|
||||||
|
'name' => 'speedtest_notifications',
|
||||||
|
'value' => true,
|
||||||
|
'description' => 'Enable notifications for every speedtest that runs'
|
||||||
|
]);
|
||||||
|
|
||||||
|
Setting::create([
|
||||||
|
'name' => 'speedtest_overview_notification',
|
||||||
|
'value' => true,
|
||||||
|
'description' => 'Enable a daily notification with average values for the last 24 hours.'
|
||||||
|
]);
|
||||||
|
|
||||||
|
Setting::create([
|
||||||
|
'name' => 'speedtest_overview_time',
|
||||||
|
'value' => '12',
|
||||||
|
'description' => 'The hour (24-hour format) that the daily overview notification will be sent.'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Setting::whereIn('name', [
|
||||||
|
'speedtest_notifications',
|
||||||
|
'speedtest_overview_notification',
|
||||||
|
'speedtest_overview_time',
|
||||||
|
])->delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
2
public/css/main.css
vendored
2
public/css/main.css
vendored
@@ -53,5 +53,5 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.setting-card {
|
.setting-card {
|
||||||
width: 500px;
|
height: 270px;
|
||||||
}
|
}
|
||||||
|
|||||||
2
public/js/app.js
vendored
2
public/js/app.js
vendored
File diff suppressed because one or more lines are too long
6
resources/js/components/Home/Setting.js
vendored
6
resources/js/components/Home/Setting.js
vendored
@@ -55,8 +55,9 @@ export default class Setting extends Component {
|
|||||||
var description = this.state.description;
|
var description = this.state.description;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="m-2">
|
<Card className="m-2 setting-card">
|
||||||
<Card.Body>
|
<Card.Body className="d-flex align-items-center">
|
||||||
|
<div>
|
||||||
<h4>{this.ucfirst(name)}</h4>
|
<h4>{this.ucfirst(name)}</h4>
|
||||||
<div dangerouslySetInnerHTML={{ __html: description}} />
|
<div dangerouslySetInnerHTML={{ __html: description}} />
|
||||||
<Form.Group controlId={name}>
|
<Form.Group controlId={name}>
|
||||||
@@ -64,6 +65,7 @@ export default class Setting extends Component {
|
|||||||
<Form.Control type="text" label={name} defaultValue={value} onInput={this.updateValue} />
|
<Form.Control type="text" label={name} defaultValue={value} onInput={this.updateValue} />
|
||||||
</Form.Group>
|
</Form.Group>
|
||||||
<Button variant="primary" onClick={this.update}>Save</Button>
|
<Button variant="primary" onClick={this.update}>Save</Button>
|
||||||
|
</div>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
153
resources/js/components/Home/SettingWithModal.js
vendored
Normal file
153
resources/js/components/Home/SettingWithModal.js
vendored
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import ReactDOM from 'react-dom';
|
||||||
|
import { Card, Form, Button, Modal, Row, Col } from 'react-bootstrap';
|
||||||
|
import Axios from 'axios';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
|
export default class SettingWithModal extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
this.state = {
|
||||||
|
title: this.props.title,
|
||||||
|
description: this.props.description,
|
||||||
|
settings: this.props.settings,
|
||||||
|
show: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ucfirst(string) {
|
||||||
|
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
update = () => {
|
||||||
|
var url = 'api/settings/bulk';
|
||||||
|
var data = [];
|
||||||
|
var settings = this.state.settings;
|
||||||
|
|
||||||
|
settings.forEach(e => {
|
||||||
|
var res = {
|
||||||
|
name: e.obj.name,
|
||||||
|
value: e.obj.value
|
||||||
|
};
|
||||||
|
data.push(res);
|
||||||
|
});
|
||||||
|
|
||||||
|
data = {
|
||||||
|
data: data
|
||||||
|
};
|
||||||
|
|
||||||
|
Axios.post(url, data)
|
||||||
|
.then((resp) => {
|
||||||
|
toast.success(this.state.title + ' updated');
|
||||||
|
this.toggleShow();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if(err.response.status == 422) {
|
||||||
|
toast.error('Your input was invalid');
|
||||||
|
} else {
|
||||||
|
toast.error('Something went wrong')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
updateValue = (e) => {
|
||||||
|
var name = e.target.id;
|
||||||
|
if(e.target.type == 'checkbox') {
|
||||||
|
var val = e.target.checked;
|
||||||
|
} else {
|
||||||
|
var val = e.target.value;
|
||||||
|
}
|
||||||
|
var settings = this.state.settings;
|
||||||
|
var i = 0;
|
||||||
|
settings.forEach(ele => {
|
||||||
|
if(ele.obj.name == name) {
|
||||||
|
ele.obj.value = val;
|
||||||
|
}
|
||||||
|
settings[i] = ele;
|
||||||
|
i++;
|
||||||
|
});
|
||||||
|
this.setState({
|
||||||
|
settings: settings
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleShow = () => {
|
||||||
|
var show = this.state.show;
|
||||||
|
if(show) {
|
||||||
|
this.setState({
|
||||||
|
show: false
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
show: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
var title = this.state.title;
|
||||||
|
var description = this.state.description;
|
||||||
|
var show = this.state.show;
|
||||||
|
var settings = this.state.settings;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card className="m-2 setting-card">
|
||||||
|
<Card.Body className="d-flex align-items-center">
|
||||||
|
<div>
|
||||||
|
<h4>{title}</h4>
|
||||||
|
<p>{description}</p>
|
||||||
|
<Button variant="primary" onClick={this.toggleShow}>Edit</Button>
|
||||||
|
</div>
|
||||||
|
</Card.Body>
|
||||||
|
</Card>
|
||||||
|
<Modal show={show} onHide={this.toggleShow}>
|
||||||
|
<Modal.Header>
|
||||||
|
<Modal.Title>{title}</Modal.Title>
|
||||||
|
</Modal.Header>
|
||||||
|
<Modal.Body>
|
||||||
|
{settings.map((e,i) => {
|
||||||
|
var name = e.obj.name.split('_');
|
||||||
|
name[0] = this.ucfirst(name[0]);
|
||||||
|
name = name.join(' ');
|
||||||
|
if(e.type == 'checkbox') {
|
||||||
|
return (
|
||||||
|
<Row key={e.obj.id} className="d-flex align-items-center">
|
||||||
|
<Col md={{ span: 6 }} sm={{ span: 12 }}>
|
||||||
|
<Form.Group controlId={e.obj.name}>
|
||||||
|
<Form.Check type="checkbox" label={name} defaultChecked={e.obj.value} onInput={this.updateValue} />
|
||||||
|
</Form.Group>
|
||||||
|
</Col>
|
||||||
|
<Col md={{ span: 6 }} sm={{ span: 12 }}>
|
||||||
|
<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 }}>
|
||||||
|
<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} />
|
||||||
|
</Form.Group>
|
||||||
|
</Col>
|
||||||
|
<Col md={{ span: 6 }} sm={{ span: 12 }}>
|
||||||
|
<p>{e.obj.description}</p>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
<Button variant="primary" type="submit" onClick={this.update} >Save</Button>
|
||||||
|
</Modal.Body>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.getElementById('Setting')) {
|
||||||
|
ReactDOM.render(<Setting />, document.getElementById('Setting'));
|
||||||
|
}
|
||||||
23
resources/js/components/Home/Settings.js
vendored
23
resources/js/components/Home/Settings.js
vendored
@@ -4,6 +4,7 @@ import { Modal, Container, Row, Col, Collapse } from 'react-bootstrap';
|
|||||||
import Loader from '../Loader';
|
import Loader from '../Loader';
|
||||||
import Axios from 'axios';
|
import Axios from 'axios';
|
||||||
import Setting from './Setting';
|
import Setting from './Setting';
|
||||||
|
import SettingWithModal from './SettingWithModal';
|
||||||
|
|
||||||
export default class Settings extends Component {
|
export default class Settings extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -53,12 +54,30 @@ export default class Settings extends Component {
|
|||||||
var e = this.state.data;
|
var e = this.state.data;
|
||||||
return (
|
return (
|
||||||
<Row>
|
<Row>
|
||||||
<Col lg={{ span: 3, offset: 3 }} md={{ span: 6 }} sm={{ span: 12 }}>
|
<Col lg={{ span: 2, offset: 3 }} md={{ span: 6 }} sm={{ span: 12 }}>
|
||||||
<Setting name={e.schedule.name} value={e.schedule.value} description={e.schedule.description} />
|
<Setting name={e.schedule.name} value={e.schedule.value} description={e.schedule.description} />
|
||||||
</Col>
|
</Col>
|
||||||
<Col lg={{ span: 3 }} md={{ span: 6 }} sm={{ span: 12 }}>
|
<Col lg={{ span: 2 }} md={{ span: 6 }} sm={{ span: 12 }}>
|
||||||
<Setting name={e.server.name} value={e.server.value} description={e.server.description} />
|
<Setting name={e.server.name} value={e.server.value} description={e.server.description} />
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col lg={{ span: 2 }} md={{ span: 6 }} sm={{ span: 12 }}>
|
||||||
|
<SettingWithModal title="Notification settings" description="Control which types of notifications the server sends." settings={[
|
||||||
|
{
|
||||||
|
obj: e.speedtest_notifications,
|
||||||
|
type: 'checkbox'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
obj: e.speedtest_overview_notification,
|
||||||
|
type: 'checkbox'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
obj: e.speedtest_overview_time,
|
||||||
|
type: 'number',
|
||||||
|
min: 0,
|
||||||
|
max: 23
|
||||||
|
}
|
||||||
|
]} />
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,4 +66,6 @@ Route::group([
|
|||||||
->name('settings.store');
|
->name('settings.store');
|
||||||
Route::post('/', 'SettingsController@store')
|
Route::post('/', 'SettingsController@store')
|
||||||
->name('settings.update');
|
->name('settings.update');
|
||||||
|
Route::post('/bulk', 'SettingsController@bulkStore')
|
||||||
|
->name('settings.bulk.update');
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user