Compare commits

...

38 Commits

Author SHA1 Message Date
Henry Whitaker
21d3aea934 Merge pull request #317 from henrywhitaker3/alpha
Fixed min setting bug
2020-09-11 01:26:35 +01:00
Henry Whitaker
342d3fabf4 Fixed min setting bug 2020-09-11 01:23:25 +01:00
Henry Whitaker
4b95cb12ef Merge pull request #315 from henrywhitaker3/alpha 2020-09-11 01:09:34 +01:00
Henry Whitaker
8ff87c2e7a Updated tests 2020-09-11 01:02:24 +01:00
Henry Whitaker
149c69ce64 Merge remote-tracking branch 'origin/alpha' into alpha 2020-09-11 00:56:59 +01:00
Henry Whitaker
933291c5fc Merge pull request #303 from henrywhitaker3/dependabot/npm_and_yarn/dev/sass-loader-10.0.2
Bump sass-loader from 10.0.1 to 10.0.2
2020-09-11 00:56:48 +01:00
Henry Whitaker
29c36d88e2 Merge pull request #304 from henrywhitaker3/dependabot/composer/dev/fruitcake/laravel-cors-2.0.2
Bump fruitcake/laravel-cors from 2.0.1 to 2.0.2
2020-09-11 00:55:57 +01:00
Henry Whitaker
4b167af50e Merge pull request #305 from henrywhitaker3/dependabot/composer/dev/facade/ignition-2.3.7 2020-09-11 00:55:30 +01:00
Henry Whitaker
7d0ea79798 Merge pull request #306 from henrywhitaker3/dependabot/composer/dev/laravel-notification-channels/telegram-0.5.0
Bump laravel-notification-channels/telegram from 0.4.1 to 0.5.0
2020-09-11 00:55:13 +01:00
Henry Whitaker
375eab288d Merge pull request #307 from henrywhitaker3/dependabot/composer/dev/barryvdh/laravel-ide-helper-2.8.1
Bump barryvdh/laravel-ide-helper from 2.8.0 to 2.8.1
2020-09-11 00:54:54 +01:00
Henry Whitaker
8e2ddd974a Merge pull request #311 from henrywhitaker3/dependabot/composer/dev/tymon/jwt-auth-1.0.1
Bump tymon/jwt-auth from 1.0.0 to 1.0.1
2020-09-11 00:54:34 +01:00
Henry Whitaker
d78c3e2669 Merge pull request #313 from henrywhitaker3/dependabot/composer/dev/laravel/framework-7.28.1
Bump laravel/framework from 7.27.0 to 7.28.1
2020-09-11 00:53:38 +01:00
Henry Whitaker
a83d4e363b Merge pull request #314 from henrywhitaker3/dependabot/composer/dev/laravel/ui-2.3.0
Bump laravel/ui from 2.2.0 to 2.3.0
2020-09-11 00:53:18 +01:00
Henry Whitaker
334623454d Added General settings section & min value on widgets 2020-09-11 00:51:27 +01:00
dependabot-preview[bot]
a7aa3e7885 Bump laravel/ui from 2.2.0 to 2.3.0
Bumps [laravel/ui](https://github.com/laravel/ui) from 2.2.0 to 2.3.0.
- [Release notes](https://github.com/laravel/ui/releases)
- [Changelog](https://github.com/laravel/ui/blob/2.x/CHANGELOG.md)
- [Commits](https://github.com/laravel/ui/compare/v2.2.0...v2.3.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-10 08:54:23 +00:00
dependabot-preview[bot]
2e1022c116 Bump laravel/framework from 7.27.0 to 7.28.1
Bumps [laravel/framework](https://github.com/laravel/framework) from 7.27.0 to 7.28.1.
- [Release notes](https://github.com/laravel/framework/releases)
- [Changelog](https://github.com/laravel/framework/blob/8.x/CHANGELOG-7.x.md)
- [Commits](https://github.com/laravel/framework/compare/v7.27.0...v7.28.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-10 08:51:58 +00:00
dependabot-preview[bot]
355d38acb7 Bump tymon/jwt-auth from 1.0.0 to 1.0.1
Bumps [tymon/jwt-auth](https://github.com/tymondesigns/jwt-auth) from 1.0.0 to 1.0.1.
- [Release notes](https://github.com/tymondesigns/jwt-auth/releases)
- [Commits](https://github.com/tymondesigns/jwt-auth/compare/1.0.0...1.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-09 09:25:14 +00:00
dependabot-preview[bot]
1e9887ac46 Bump barryvdh/laravel-ide-helper from 2.8.0 to 2.8.1
Bumps [barryvdh/laravel-ide-helper](https://github.com/barryvdh/laravel-ide-helper) from 2.8.0 to 2.8.1.
- [Release notes](https://github.com/barryvdh/laravel-ide-helper/releases)
- [Changelog](https://github.com/barryvdh/laravel-ide-helper/blob/master/CHANGELOG.md)
- [Commits](https://github.com/barryvdh/laravel-ide-helper/compare/v2.8.0...v2.8.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-08 08:27:04 +00:00
dependabot-preview[bot]
8538dd231f Bump laravel-notification-channels/telegram from 0.4.1 to 0.5.0
Bumps [laravel-notification-channels/telegram](https://github.com/laravel-notification-channels/telegram) from 0.4.1 to 0.5.0.
- [Release notes](https://github.com/laravel-notification-channels/telegram/releases)
- [Changelog](https://github.com/laravel-notification-channels/telegram/blob/master/CHANGELOG.md)
- [Commits](https://github.com/laravel-notification-channels/telegram/compare/0.4.1...0.5.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-08 08:24:37 +00:00
dependabot-preview[bot]
5793140e89 Bump facade/ignition from 2.3.6 to 2.3.7
Bumps [facade/ignition](https://github.com/facade/ignition) from 2.3.6 to 2.3.7.
- [Release notes](https://github.com/facade/ignition/releases)
- [Changelog](https://github.com/facade/ignition/blob/master/CHANGELOG.md)
- [Commits](https://github.com/facade/ignition/compare/2.3.6...2.3.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-08 08:23:14 +00:00
dependabot-preview[bot]
56ecff1a09 Bump fruitcake/laravel-cors from 2.0.1 to 2.0.2
Bumps [fruitcake/laravel-cors](https://github.com/fruitcake/laravel-cors) from 2.0.1 to 2.0.2.
- [Release notes](https://github.com/fruitcake/laravel-cors/releases)
- [Changelog](https://github.com/fruitcake/laravel-cors/blob/master/changelog.md)
- [Commits](https://github.com/fruitcake/laravel-cors/compare/v2.0.1...v2.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-08 08:21:46 +00:00
dependabot-preview[bot]
eff8f92016 Bump sass-loader from 10.0.1 to 10.0.2
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 10.0.1 to 10.0.2.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v10.0.1...v10.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-07 16:29:12 +00:00
Henry Whitaker
8ae4bc602c Merge pull request #299 from henrywhitaker3/alpha 2020-09-05 01:11:47 +01:00
Henry Whitaker
9028ffb7cd Updated changelog 2020-09-05 01:06:11 +01:00
Henry Whitaker
62fde8fb2a Merge remote-tracking branch 'origin/alpha' into alpha 2020-09-05 01:00:16 +01:00
Henry Whitaker
601d46915c Clear cache on restore 2020-09-05 00:58:04 +01:00
Henry Whitaker
751acff32c Updated demo link 2020-09-05 00:57:55 +01:00
Henry Whitaker
4e133e97c7 Merge pull request #289 from henrywhitaker3/dependabot/npm_and_yarn/dev/sass-loader-10.0.1
Bump sass-loader from 9.0.3 to 10.0.1
2020-09-05 00:57:25 +01:00
Henry Whitaker
61a85ced34 Merge pull request #291 from henrywhitaker3/dependabot/composer/dev/laravel/framework-7.27.0
Bump laravel/framework from 7.26.0 to 7.27.0
2020-09-05 00:56:59 +01:00
Henry Whitaker
aa37a50f57 Merge pull request #292 from henrywhitaker3/dependabot/composer/dev/doctrine/dbal-2.10.3
Bump doctrine/dbal from 2.10.2 to 2.10.3
2020-09-05 00:56:43 +01:00
Henry Whitaker
99ac0b008c Merge pull request #293 from henrywhitaker3/dependabot/composer/dev/symfony/http-kernel-5.1.5
[Security] Bump symfony/http-kernel from 5.1.3 to 5.1.5
2020-09-05 00:56:25 +01:00
Henry Whitaker
b4147ce57a Merge pull request #295 from henrywhitaker3/dependabot/composer/dev/nunomaduro/larastan-0.6.4 2020-09-05 00:55:55 +01:00
dependabot-preview[bot]
80b80811aa Bump nunomaduro/larastan from 0.6.2 to 0.6.4
Bumps [nunomaduro/larastan](https://github.com/nunomaduro/larastan) from 0.6.2 to 0.6.4.
- [Release notes](https://github.com/nunomaduro/larastan/releases)
- [Changelog](https://github.com/nunomaduro/larastan/blob/master/CHANGELOG.md)
- [Commits](https://github.com/nunomaduro/larastan/compare/v0.6.2...v0.6.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-03 11:05:31 +00:00
dependabot-preview[bot]
2d8bc7d71f [Security] Bump symfony/http-kernel from 5.1.3 to 5.1.5
Bumps [symfony/http-kernel](https://github.com/symfony/http-kernel) from 5.1.3 to 5.1.5. **This update includes a security fix.**
- [Release notes](https://github.com/symfony/http-kernel/releases)
- [Changelog](https://github.com/symfony/http-kernel/blob/master/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-kernel/compare/v5.1.3...v5.1.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-02 14:24:38 +00:00
dependabot-preview[bot]
a036ed7c8f Bump doctrine/dbal from 2.10.2 to 2.10.3
Bumps [doctrine/dbal](https://github.com/doctrine/dbal) from 2.10.2 to 2.10.3.
- [Release notes](https://github.com/doctrine/dbal/releases)
- [Commits](https://github.com/doctrine/dbal/compare/2.10.2...2.10.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-02 08:50:31 +00:00
dependabot-preview[bot]
01b097b4d3 Bump laravel/framework from 7.26.0 to 7.27.0
Bumps [laravel/framework](https://github.com/laravel/framework) from 7.26.0 to 7.27.0.
- [Release notes](https://github.com/laravel/framework/releases)
- [Changelog](https://github.com/laravel/framework/blob/7.x/CHANGELOG-7.x.md)
- [Commits](https://github.com/laravel/framework/compare/v7.26.0...v7.27.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-02 08:48:43 +00:00
dependabot-preview[bot]
a6326f6d98 Bump sass-loader from 9.0.3 to 10.0.1
Bumps [sass-loader](https://github.com/webpack-contrib/sass-loader) from 9.0.3 to 10.0.1.
- [Release notes](https://github.com/webpack-contrib/sass-loader/releases)
- [Changelog](https://github.com/webpack-contrib/sass-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/sass-loader/compare/v9.0.3...v10.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-31 17:11:09 +00:00
Henry Whitaker
ef34238043 Update README.md 2020-08-30 19:00:55 +01:00
18 changed files with 604 additions and 385 deletions

View File

@@ -1,10 +1,10 @@
# Speedtest Tracker
[![Docker pulls](https://img.shields.io/docker/pulls/henrywhitaker3/speedtest-tracker?style=flat-square)](https://hub.docker.com/r/henrywhitaker3/speedtest-tracker) [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/henrywhitaker3/Speedtest-Tracker/Stable?label=master&logo=github&style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/actions) [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/henrywhitaker3/Speedtest-Tracker/Dev?label=dev&logo=github&style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/actions) [![last_commit](https://img.shields.io/github/last-commit/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) [![issues](https://img.shields.io/github/issues/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/issues) [![commit_freq](https://img.shields.io/github/commit-activity/m/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) ![version](https://img.shields.io/badge/version-v1.9.5-success?style=flat-square) [![license](https://img.shields.io/github/license/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/blob/master/LICENSE)
[![Docker pulls](https://img.shields.io/docker/pulls/henrywhitaker3/speedtest-tracker?style=flat-square)](https://hub.docker.com/r/henrywhitaker3/speedtest-tracker) [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/henrywhitaker3/Speedtest-Tracker/Stable?label=master&logo=github&style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/actions) [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/henrywhitaker3/Speedtest-Tracker/Dev?label=dev&logo=github&style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/actions) [![last_commit](https://img.shields.io/github/last-commit/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) [![issues](https://img.shields.io/github/issues/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/issues) [![commit_freq](https://img.shields.io/github/commit-activity/m/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) ![version](https://img.shields.io/badge/version-v1.9.8-success?style=flat-square) [![license](https://img.shields.io/github/license/henrywhitaker3/Speedtest-Tracker?style=flat-square)](https://github.com/henrywhitaker3/Speedtest-Tracker/blob/master/LICENSE)
This program runs a speedtest check every hour and graphs the results. The back-end is written in [Laravel](https://laravel.com/) and the front-end uses [React](https://reactjs.org/). It uses the [Ookla's speedtest cli](https://www.speedtest.net/apps/cli) package to get the data and uses [Chart.js](https://www.chartjs.org/) to plot the results.
A demo can be found [here](https://speedtest.plexmox.com)
A demo can be found [here](https://speedtest.henrywhitaker.com)
Disclaimer: You will need to accept Ookla's EULA and privacy agreements in order to use this container.

View File

@@ -3,6 +3,7 @@
namespace App\Helpers;
use App\Speedtest;
use Cache;
use DateTime;
use Exception;
use Illuminate\Support\Facades\Log;
@@ -59,6 +60,7 @@ class BackupHelper {
*/
public static function restore($array, $format)
{
Cache::flush();
if($format == 'json') {
foreach($array as $test) {
try {

View File

@@ -7,7 +7,8 @@ use App\Setting;
use Cache;
use Carbon\Carbon;
class SettingsHelper {
class SettingsHelper
{
/**
* Get a Setting object by name
@@ -19,9 +20,9 @@ class SettingsHelper {
{
$name = Setting::where('name', $name)->get();
if(sizeof($name) == 0) {
if (sizeof($name) == 0) {
return false;
} else if(sizeof($name) == 1) {
} else if (sizeof($name) == 1) {
return $name[0];
} else {
$name = $name->keyBy('name');
@@ -40,11 +41,11 @@ class SettingsHelper {
{
$setting = SettingsHelper::get($name);
if($value === false) {
if ($value === false) {
$value = "0";
}
if($setting !== false) {
if ($setting !== false) {
$setting->value = $value;
$setting->save();
} else {
@@ -54,7 +55,7 @@ class SettingsHelper {
]);
}
if($name == 'show_failed_tests_on_graph') {
if ($name == 'show_failed_tests_on_graph') {
Cache::flush();
}
@@ -69,13 +70,13 @@ class SettingsHelper {
public static function getBase()
{
$base = env('BASE_PATH', '/');
if($base == '') {
if ($base == '') {
$base = '/';
} else {
if($base[0] != '/') {
if ($base[0] != '/') {
$base = '/' . $base;
}
if($base[-1] != '/') {
if ($base[-1] != '/') {
$base = $base . '/';
}
}
@@ -95,7 +96,7 @@ class SettingsHelper {
// Try exact key
$val = exec('echo $' . $key);
if($val == "") {
if ($val == "") {
array_push($results, true);
} else {
array_push($results, false);
@@ -104,25 +105,25 @@ class SettingsHelper {
// Try key all caps
$val = exec('echo $' . strtoupper($key));
if($val == "") {
if ($val == "") {
array_push($results, true);
} else {
array_push($results, false);
}
if(env($key, false) == false) {
if (env($key, false) == false) {
array_push($results, true);
} else {
array_push($results, false);
}
if(env(strtoupper($key), false) == false) {
if (env(strtoupper($key), false) == false) {
array_push($results, true);
} else {
array_push($results, false);
}
if(in_array(false, $results)) {
if (in_array(false, $results)) {
return false;
}
@@ -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'),
@@ -163,15 +169,15 @@ class SettingsHelper {
*/
public static function testNotification($agent = true)
{
$agents = [ 'slack', 'telegram' ];
$agents = ['slack', 'telegram'];
if($agent === true) {
if ($agent === true) {
event(new TestNotificationEvent($agents));
return true;
}
if(in_array($agent, $agents)) {
event(new TestNotificationEvent([ $agent ]));
if (in_array($agent, $agents)) {
event(new TestNotificationEvent([$agent]));
return true;
}
@@ -188,14 +194,14 @@ class SettingsHelper {
'telegram_chat_id' => SettingsHelper::get('telegram_chat_id')->value,
];
foreach($settings as $key => $value) {
foreach ($settings as $key => $value) {
$key = 'integrations.' . $key;
if($value === "") {
if ($value === "") {
$value = null;
}
config()->set([ $key => $value ]);
config()->set([$key => $value]);
}
}
}

View File

@@ -18,9 +18,9 @@ class SpeedtestController extends Controller
{
public function __construct()
{
if((bool)SettingsHelper::get('auth')->value === true) {
if ((bool)SettingsHelper::get('auth')->value === true) {
$this->middleware('auth:api')
->only([ 'run', 'delete', 'deleteAll' ]);
->only(['run', 'delete', 'deleteAll']);
}
}
@@ -32,7 +32,7 @@ class SpeedtestController extends Controller
public function index()
{
$data = Speedtest::orderBy('created_at', 'desc')
->paginate();
->paginate();
return response()->json([
'method' => 'index of speedtests',
@@ -49,12 +49,12 @@ class SpeedtestController extends Controller
public function time($days)
{
$rule = [
'days' => [ 'required', 'integer' ],
'days' => ['required', 'integer'],
];
$validator = Validator::make([ 'days' => $days ], $rule);
$validator = Validator::make(['days' => $days], $rule);
if($validator->fails()) {
if ($validator->fails()) {
return response()->json([
'method' => 'get speedtests in last x days',
'error' => $validator->errors(),
@@ -65,16 +65,16 @@ class SpeedtestController extends Controller
$data = Cache::remember('speedtest-days-' . $days, $ttl, function () use ($days) {
$showFailed = (bool)SettingsHelper::get('show_failed_tests_on_graph')->value;
if($showFailed === true) {
if ($showFailed === true) {
return Speedtest::where('created_at', '>=', Carbon::now()->subDays($days))
->orderBy('created_at', 'asc')
->get();
->orderBy('created_at', 'asc')
->get();
}
return Speedtest::where('created_at', '>=', Carbon::now()->subDays($days))
->where('failed', false)
->orderBy('created_at', 'asc')
->get();
->where('failed', false)
->orderBy('created_at', 'asc')
->get();
});
return response()->json([
@@ -93,12 +93,12 @@ class SpeedtestController extends Controller
public function fail($days)
{
$rule = [
'days' => [ 'required', 'integer' ],
'days' => ['required', 'integer'],
];
$validator = Validator::make([ 'days' => $days ], $rule);
$validator = Validator::make(['days' => $days], $rule);
if($validator->fails()) {
if ($validator->fails()) {
return response()->json([
'method' => 'get speedtests in last x days',
'error' => $validator->errors(),
@@ -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([
'method' => 'get latest speedtest',
'data' => $data,
'average' => $avg[0],
'max' => $max[0],
], 200);
$response = [
'method' => 'get latest speedtest',
'data' => $data,
];
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_min')) {
$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',
@@ -158,7 +176,7 @@ class SpeedtestController extends Controller
'method' => 'run speedtest',
'data' => 'a new speedtest has been added to the queue'
], 200);
} catch(Exception $e) {
} catch (Exception $e) {
return response()->json([
'method' => 'run speedtest',
'error' => $e
@@ -175,7 +193,7 @@ class SpeedtestController extends Controller
{
$ret = SpeedtestHelper::deleteAll();
if($ret['success']) {
if ($ret['success']) {
return response()->json([
'method' => 'delete all speedtests from the database',
'success' => true

View File

@@ -1,4 +1,34 @@
{
"1.9.8": [
{
"description": "Fixed bug with minimum display setting.",
"link": ""
}
],
"1.9.7": [
{
"description": "Added option to display minimum values on the top widgets.",
"link": ""
},
{
"description": "New general settings section.",
"link": ""
},
{
"description": "Updated dependencies.",
"link": ""
}
],
"1.9.6": [
{
"description": "Clear the cache on restore.",
"link": ""
},
{
"description": "Updated dependencies.",
"link": ""
}
],
"1.9.5": [
{
"description": "Added toggle to show failed tests on graphs.",

View File

@@ -15,7 +15,7 @@
"fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^7.0",
"henrywhitaker3/healthchecks-io": "^1.0",
"laravel-notification-channels/telegram": "^0.4.0",
"laravel-notification-channels/telegram": "^0.5.0",
"laravel/framework": "^7.0",
"laravel/slack-notification-channel": "^2.0",
"laravel/tinker": "^2.0",

548
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@ return [
|--------------------------------------------------------------------------
*/
'version' => '1.9.5',
'version' => '1.9.8',
/*
|--------------------------------------------------------------------------

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();
}
}

50
package-lock.json generated
View File

@@ -6401,9 +6401,9 @@
"dev": true
},
"klona": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/klona/-/klona-1.1.2.tgz",
"integrity": "sha512-xf88rTeHiXk+XE2Vhi6yj8Wm3gMZrygGdKjJqN8HkV+PwF/t50/LdAKHoHpPcxFAlmQszTZ1CugrK25S7qDRLA==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.3.tgz",
"integrity": "sha512-CgPOT3ZadDpXxKcfV56lEQ9OQSZ42Mk26gnozI+uN/k39vzD8toUhRQoqsX0m9Q3eMPEfsLWmtyUpK/yqST4yg==",
"dev": true
},
"laravel-mix": {
@@ -9032,29 +9032,23 @@
}
},
"sass-loader": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-9.0.3.tgz",
"integrity": "sha512-fOwsP98ac1VMme+V3+o0HaaMHp8Q/C9P+MUazLFVi3Jl7ORGHQXL1XeRZt3zLSGZQQPC8xE42Y2WptItvGjDQg==",
"version": "10.0.2",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.0.2.tgz",
"integrity": "sha512-wV6NDUVB8/iEYMalV/+139+vl2LaRFlZGEd5/xmdcdzQcgmis+npyco6NsDTVOlNA3y2NV9Gcz+vHyFMIT+ffg==",
"dev": true,
"requires": {
"klona": "^1.1.2",
"klona": "^2.0.3",
"loader-utils": "^2.0.0",
"neo-async": "^2.6.2",
"schema-utils": "^2.7.0",
"schema-utils": "^2.7.1",
"semver": "^7.3.2"
},
"dependencies": {
"ajv": {
"version": "6.12.3",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz",
"integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==",
"dev": true,
"requires": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
}
"ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
"dev": true
},
"loader-utils": {
"version": "2.0.0",
@@ -9067,21 +9061,15 @@
"json5": "^2.1.2"
}
},
"neo-async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
"schema-utils": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
"integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz",
"integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.4",
"ajv": "^6.12.2",
"ajv-keywords": "^3.4.1"
"@types/json-schema": "^7.0.5",
"ajv": "^6.12.4",
"ajv-keywords": "^3.5.2"
}
},
"semver": {

View File

@@ -22,7 +22,7 @@
"react-dom": "^16.2.0",
"resolve-url-loader": "^3.1.0",
"sass": "^1.26.10",
"sass-loader": "^9.0.3"
"sass-loader": "^10.0.2"
},
"dependencies": {
"@babel/plugin-proposal-class-properties": "^7.10.4",

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_min) {
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_min) {
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_min) {
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>
<div className="text-muted text-truncate">
<h5 className="d-inline">{avg}</h5>
<p className="d-inline ml-2">{unit} (average)</p>
</div>
<div className="text-muted text-truncate">
<h5 className="d-inline">{max}</h5>
<p className="d-inline ml-2">{unit} (maximum)</p>
</div>
{window.config.widgets.show_average &&
<div className="text-muted text-truncate">
<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">{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={[

View File

@@ -27,13 +27,13 @@ class APISpeedtestTest extends TestCase
$dl = [];
$ul = [];
for($i = 0; $i < 3; $i++) {
for ($i = 0; $i < 3; $i++) {
$pingVal = $faker->randomFloat();
array_push($ping,$pingVal);
array_push($ping, $pingVal);
$dlVal = $faker->randomFloat();
array_push($dl,$dlVal);
array_push($dl, $dlVal);
$ulVal = $faker->randomFloat();
array_push($ul,$ulVal);
array_push($ul, $ulVal);
Speedtest::create([
'ping' => $pingVal,
@@ -70,7 +70,12 @@ class APISpeedtestTest extends TestCase
'download',
'upload',
],
'max' => [
'maximum' => [
'ping',
'download',
'upload',
],
'minimum' => [
'ping',
'download',
'upload',

View File

@@ -19,7 +19,7 @@ class LatestTest extends TestCase
*/
private $controller;
public function setUp() : void
public function setUp(): void
{
parent::setUp();
@@ -53,6 +53,7 @@ class LatestTest extends TestCase
$this->assertArrayHasKey('data', $resp);
$this->assertArrayHasKey('average', $resp);
$this->assertArrayHasKey('max', $resp);
$this->assertArrayHasKey('maximum', $resp);
$this->assertArrayHasKey('minimum', $resp);
}
}