mirror of
https://github.com/henrywhitaker3/Speedtest-Tracker.git
synced 2025-12-21 13:23:04 +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()
|
||||
{
|
||||
$this->info('Speedtest Tracker');
|
||||
$this->info('Author: Henry Whitaker');
|
||||
$this->info('');
|
||||
$this->info('Installed version v' . config('speedtest.version'));
|
||||
$this->info('Speedtest Tracker v' . config('speedtest.version'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Console;
|
||||
|
||||
use App\Events\SpeedtestOverviewEvent;
|
||||
use App\Helpers\SettingsHelper;
|
||||
use App\Helpers\SpeedtestHelper;
|
||||
use App\Jobs\SpeedtestJob;
|
||||
@@ -28,6 +29,7 @@ class Kernel extends ConsoleKernel
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
$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 Carbon\Carbon;
|
||||
use Exception;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use JsonException;
|
||||
use SimpleXMLElement;
|
||||
|
||||
class SpeedtestHelper {
|
||||
|
||||
@@ -70,6 +67,22 @@ class SpeedtestHelper {
|
||||
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
|
||||
*
|
||||
|
||||
@@ -67,6 +67,49 @@ class SettingsController extends Controller
|
||||
], 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
|
||||
*
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Listeners;
|
||||
|
||||
use App\Helpers\SettingsHelper;
|
||||
use App\Notifications\SpeedtestCompleteSlack;
|
||||
use App\Notifications\SpeedtestCompleteTelegram;
|
||||
use Exception;
|
||||
@@ -31,6 +32,7 @@ class SpeedtestCompleteListener
|
||||
*/
|
||||
public function handle($event)
|
||||
{
|
||||
if(SettingsHelper::get('speedtest_notifications')->value == true) {
|
||||
$data = $event->speedtest;
|
||||
if(env('SLACK_WEBHOOK')) {
|
||||
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;
|
||||
|
||||
use App\Events\SpeedtestCompleteEvent;
|
||||
use App\Events\SpeedtestOverviewEvent;
|
||||
use App\Listeners\SpeedtestCompleteListener;
|
||||
use App\Listeners\SpeedtestOverviewListener;
|
||||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
@@ -23,6 +25,9 @@ class EventServiceProvider extends ServiceProvider
|
||||
SpeedtestCompleteEvent::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 {
|
||||
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;
|
||||
|
||||
return (
|
||||
<Card className="m-2">
|
||||
<Card.Body>
|
||||
<Card className="m-2 setting-card">
|
||||
<Card.Body className="d-flex align-items-center">
|
||||
<div>
|
||||
<h4>{this.ucfirst(name)}</h4>
|
||||
<div dangerouslySetInnerHTML={{ __html: description}} />
|
||||
<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.Group>
|
||||
<Button variant="primary" onClick={this.update}>Save</Button>
|
||||
</div>
|
||||
</Card.Body>
|
||||
</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 Axios from 'axios';
|
||||
import Setting from './Setting';
|
||||
import SettingWithModal from './SettingWithModal';
|
||||
|
||||
export default class Settings extends Component {
|
||||
constructor(props) {
|
||||
@@ -53,12 +54,30 @@ export default class Settings extends Component {
|
||||
var e = this.state.data;
|
||||
return (
|
||||
<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} />
|
||||
</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} />
|
||||
</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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -66,4 +66,6 @@ Route::group([
|
||||
->name('settings.store');
|
||||
Route::post('/', 'SettingsController@store')
|
||||
->name('settings.update');
|
||||
Route::post('/bulk', 'SettingsController@bulkStore')
|
||||
->name('settings.bulk.update');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user