Added General settings section & min value on widgets

This commit is contained in:
Henry Whitaker
2020-09-11 00:51:27 +01:00
parent 9028ffb7cd
commit 334623454d
8 changed files with 244 additions and 85 deletions

View File

@@ -7,7 +7,8 @@ use App\Setting;
use Cache;
use Carbon\Carbon;
class SettingsHelper {
class SettingsHelper
{
/**
* Get a Setting object by name
@@ -138,6 +139,11 @@ class SettingsHelper {
{
return [
'base' => SettingsHelper::getBase(),
'widgets' => [
'show_average' => (bool)SettingsHelper::get('show_average')->value,
'show_max' => (bool)SettingsHelper::get('show_max')->value,
'show_min' => (bool)SettingsHelper::get('show_min')->value,
],
'graphs' => [
'download_upload_graph_enabled' => SettingsHelper::get('download_upload_graph_enabled'),
'download_upload_graph_width' => SettingsHelper::get('download_upload_graph_width'),

View File

@@ -122,20 +122,38 @@ class SpeedtestController extends Controller
public function latest()
{
$data = SpeedtestHelper::latest();
$avg = Speedtest::select(DB::raw('AVG(ping) as ping, AVG(download) as download, AVG(upload) as upload'))
->where('failed', false)
->get();
$max = Speedtest::select(DB::raw('MAX(ping) as ping, MAX(download) as download, MAX(upload) as upload'))
->where('failed', false)
->get();
if($data) {
return response()->json([
$response = [
'method' => 'get latest speedtest',
'data' => $data,
'average' => $avg[0],
'max' => $max[0],
], 200);
];
if (SettingsHelper::get('show_average')) {
$avg = Speedtest::select(DB::raw('AVG(ping) as ping, AVG(download) as download, AVG(upload) as upload'))
->where('failed', false)
->first()
->toArray();
$response['average'] = $avg;
}
if (SettingsHelper::get('show_max')) {
$max = Speedtest::select(DB::raw('MAX(ping) as ping, MAX(download) as download, MAX(upload) as upload'))
->where('failed', false)
->first()
->toArray();
$response['maximum'] = $max;
}
if (SettingsHelper::get('show_average')) {
$min = Speedtest::select(DB::raw('MIN(ping) as ping, MIN(download) as download, MIN(upload) as upload'))
->where('failed', false)
->first()
->toArray();
$response['minimum'] = $min;
}
if ($data) {
return response()->json($response, 200);
} else {
return response()->json([
'method' => 'get latest speedtest',

View File

@@ -0,0 +1,56 @@
<?php
use App\Helpers\SettingsHelper;
use App\Setting;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddWidgetCardSettings extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (!SettingsHelper::get('show_average')) {
Setting::create([
'name' => 'show_average',
'value' => true,
'description' => 'If enabled, the average value for speedtests will be shown in the widgets.'
]);
}
if (!SettingsHelper::get('show_max')) {
Setting::create([
'name' => 'show_max',
'value' => true,
'description' => 'If enabled, the maximum value for speedtests will be shown in the widgets.'
]);
}
if (!SettingsHelper::get('show_min')) {
Setting::create([
'name' => 'show_min',
'value' => true,
'description' => 'If enabled, the minimum value for speedtests will be shown in the widgets.'
]);
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Setting::whereIn('name', [
'show_average',
'show_max',
'show_min',
])->delete();
}
}

2
public/js/app.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -131,9 +131,7 @@ export default class LatestResults extends Component {
>
<Widget
title="Ping"
value={parseFloat(data.data.ping).toFixed(1)}
avg={parseFloat(data.average.ping).toFixed(1)}
max={parseFloat(data.max.ping).toFixed(1)}
data={data}
failed={data.data.failed}
unit="ms"
icon="ping"
@@ -147,9 +145,7 @@ export default class LatestResults extends Component {
>
<Widget
title="Download"
value={parseFloat(data.data.download).toFixed(1)}
avg={parseFloat(data.average.download).toFixed(1)}
max={parseFloat(data.max.download).toFixed(1)}
data={data}
failed={data.data.failed}
unit="Mbit/s"
icon="dl"
@@ -163,9 +159,7 @@ export default class LatestResults extends Component {
>
<Widget
title="Upload"
value={parseFloat(data.data.upload).toFixed(1)}
avg={parseFloat(data.average.upload).toFixed(1)}
max={parseFloat(data.max.upload).toFixed(1)}
data={data}
failed={data.data.failed}
unit="Mbit/s"
icon="ul"

View File

@@ -8,38 +8,88 @@ export default class Widget extends Component {
this.state = {
title: this.props.title,
value: this.props.value,
unit: this.props.unit,
icon: this.props.icon,
avg: this.props.avg,
max: this.props.max,
failed: this.props.failed,
data: this.props.data
}
}
parseData(title, data) {
var returnData = {};
if(title == 'Ping') {
returnData.value = parseFloat(data.data.ping).toFixed(1);
if(window.config.widgets.show_average) {
returnData.avg = parseFloat(data.average.ping).toFixed(1);
}
if(window.config.widgets.show_max) {
returnData.max = parseFloat(data.maximum.ping).toFixed(1);
}
if(window.config.widgets.show_max) {
returnData.min = parseFloat(data.minimum.ping).toFixed(1);
}
}
if(title == 'Upload') {
returnData.value = parseFloat(data.data.upload).toFixed(1);
if(window.config.widgets.show_average) {
returnData.avg = parseFloat(data.average.upload).toFixed(1);
}
if(window.config.widgets.show_max) {
returnData.max = parseFloat(data.maximum.upload).toFixed(1);
}
if(window.config.widgets.show_max) {
returnData.min = parseFloat(data.minimum.upload).toFixed(1);
}
}
if(title == 'Download') {
returnData.value = parseFloat(data.data.download).toFixed(1);
if(window.config.widgets.show_average) {
returnData.avg = parseFloat(data.average.download).toFixed(1);
}
if(window.config.widgets.show_max) {
returnData.max = parseFloat(data.maximum.download).toFixed(1);
}
if(window.config.widgets.show_max) {
returnData.min = parseFloat(data.minimum.download).toFixed(1);
}
}
return returnData;
}
componentDidUpdate = () => {
if(this.props.title != this.state.title || this.props.value != this.state.value || this.props.unit != this.state.unit || this.props.icon != this.state.icon || this.props.avg != this.state.avg || this.props.max != this.state.max || this.props.failed != this.state.failed) {
if(this.props.title != this.state.title || this.props.data != this.state.data || this.props.unit != this.state.unit || this.props.icon != this.state.icon || this.props.failed != this.state.failed) {
this.setState({
title: this.props.title,
value: this.props.value,
unit: this.props.unit,
icon: this.props.icon,
avg: this.props.avg,
max: this.props.max,
failed: this.props.failed,
data: this.props.data
});
}
}
render() {
var title = this.state.title;
var value = this.state.value;
var unit = this.state.unit;
var icon = this.state.icon;
var max = this.state.max;
var avg = this.state.avg;
var failed = Boolean(Number(this.state.failed));
var data = this.parseData(title, this.state.data);
switch(icon) {
case 'ping':
icon = <span className="ti-pulse icon text-success"></span>;
@@ -63,17 +113,30 @@ export default class Widget extends Component {
</div>
<div className="text-truncate">
<h3 className="d-inline">{(!failed) ? value : <span className="ti-close text-danger"></span> }</h3>
<h3 className="d-inline">{(!failed) ? data.value : <span className="ti-close text-danger"></span> }</h3>
<p className="d-inline ml-2">{unit} (current)</p>
</div>
{window.config.widgets.show_average &&
<div className="text-muted text-truncate">
<h5 className="d-inline">{avg}</h5>
<h5 className="d-inline">{data.avg}</h5>
<p className="d-inline ml-2">{unit} (average)</p>
</div>
}
{window.config.widgets.show_max &&
<div className="text-muted text-truncate">
<h5 className="d-inline">{max}</h5>
<h5 className="d-inline">{data.max}</h5>
<p className="d-inline ml-2">{unit} (maximum)</p>
</div>
}
{window.config.widgets.show_min &&
<div className="text-muted text-truncate">
<h5 className="d-inline">{data.min}</h5>
<p className="d-inline ml-2">{unit} (minimum)</p>
</div>
}
</div>
</div>
</Card.Body>

View File

@@ -47,6 +47,10 @@ export default class SettingWithModal extends Component {
if(this.state.autoClose) {
this.toggleShow();
}
Axios.get('api/settings/config')
.then((resp) => {
window.config = resp.data;
})
})
.catch((err) => {
if(err.response.status == 422) {
@@ -194,7 +198,7 @@ export default class SettingWithModal extends Component {
</Col>
{e.description == null &&
<Col md={md} sm={sm}>
<p>{e.obj.description}</p>
<p dangerouslySetInnerHTML={{ __html: e.obj.description}}></p>
</Col>
}
</Row>

View File

@@ -59,10 +59,28 @@ export default class Settings extends Component {
return (
<Row>
<Col lg={{ span: 4 }} md={{ span: 6 }} sm={{ span: 12 }}>
<Setting name={e.schedule.name} value={e.schedule.value} description={e.schedule.description} />
</Col>
<Col lg={{ span: 4 }} md={{ span: 6 }} sm={{ span: 12 }}>
<Setting name={e.server.name} value={e.server.value} description={e.server.description} />
<SettingWithModal title="General settings" description="Configure general settings for the app." autoClose={true} settings={[
{
obj: e.schedule,
type: 'text'
},
{
obj: e.server,
type: 'text'
},
{
obj: e.show_average,
type: 'checkbox'
},
{
obj: e.show_max,
type: 'checkbox'
},
{
obj: e.show_min,
type: 'checkbox'
},
]} />
</Col>
<Col lg={{ span: 4 }} md={{ span: 6 }} sm={{ span: 12 }}>
<SettingWithModal title="Graph settings" description="Control settings for the graphs." autoClose={true} settings={[