From a170a96cedaec9f5e3a244ca49d69aa4ca52d1ea Mon Sep 17 00:00:00 2001 From: Henry Whitaker Date: Sun, 7 Mar 2021 09:46:28 +0000 Subject: [PATCH 01/26] Upgrade to laravel 8 --- composer.json | 16 +- composer.lock | 533 +++++++++++++++++++++++++---------- storage/clockwork/.gitignore | 3 + 3 files changed, 390 insertions(+), 162 deletions(-) create mode 100644 storage/clockwork/.gitignore diff --git a/composer.json b/composer.json index 9b12f87f..741ada07 100644 --- a/composer.json +++ b/composer.json @@ -10,26 +10,28 @@ "require": { "php": "^7.2.5", "doctrine/dbal": "^2.10", - "dragonmantank/cron-expression": "^2", + "dragonmantank/cron-expression": "^3", "fideloper/proxy": "^4.2", "fruitcake/laravel-cors": "^2.0", - "guzzlehttp/guzzle": "^7.0", + "guzzlehttp/guzzle": "^7.0.1", "henrywhitaker3/healthchecks-io": "^1.0", "laravel-notification-channels/telegram": "^0.5.0", - "laravel/framework": "^7.0", + "laravel/framework": "^8.0", "laravel/slack-notification-channel": "^2.0", "laravel/tinker": "^2.0", - "laravel/ui": "^2.0", + "laravel/ui": "^3.0", "tymon/jwt-auth": "^1.0" }, "require-dev": { "barryvdh/laravel-ide-helper": "^2.8", - "facade/ignition": "^2.0", + "brianium/paratest": "^6.2", + "facade/ignition": "^2.3.6", "fzaninotto/faker": "^1.9.1", + "itsgoingd/clockwork": "^5.0", "mockery/mockery": "^1.3.1", - "phpunit/phpunit": "^9.5", + "nunomaduro/collision": "^5.3", "nunomaduro/larastan": "^0.7.0", - "nunomaduro/collision": "^5.3" + "phpunit/phpunit": "^9.5" }, "config": { "optimize-autoloader": true, diff --git a/composer.lock b/composer.lock index cd5b177b..05930e5b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "19bd0375e29ab5c67bacc1ea15b2e4e8", + "content-hash": "2ad8d03c7090b8725a7d7f639409a8de", "packages": [ { "name": "asm89/stack-cors", @@ -637,30 +637,32 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v2.3.1", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "65b2d8ee1f10915efb3b55597da3404f096acba2" + "reference": "7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/65b2d8ee1f10915efb3b55597da3404f096acba2", - "reference": "65b2d8ee1f10915efb3b55597da3404f096acba2", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c", + "reference": "7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c", "shasum": "" }, "require": { - "php": "^7.0|^8.0" + "php": "^7.2|^8.0", + "webmozart/assert": "^1.7.0" + }, + "replace": { + "mtdowling/cron-expression": "^1.0" }, "require-dev": { - "phpunit/phpunit": "^6.4|^7.0|^8.0|^9.0" + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-webmozart-assert": "^0.12.7", + "phpunit/phpunit": "^7.0|^8.0|^9.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.3-dev" - } - }, "autoload": { "psr-4": { "Cron\\": "src/Cron/" @@ -671,11 +673,6 @@ "MIT" ], "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, { "name": "Chris Tankersley", "email": "chris@ctankersley.com", @@ -689,7 +686,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v2.3.1" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.1.0" }, "funding": [ { @@ -697,7 +694,7 @@ "type": "github" } ], - "time": "2020-10-13T00:52:37+00:00" + "time": "2020-11-24T19:55:57+00:00" }, { "name": "egulias/email-validator", @@ -902,6 +899,72 @@ ], "time": "2020-10-22T13:57:20+00:00" }, + { + "name": "graham-campbell/result-type", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/GrahamCampbell/Result-Type.git", + "reference": "7e279d2cd5d7fbb156ce46daada972355cea27bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GrahamCampbell/Result-Type/zipball/7e279d2cd5d7fbb156ce46daada972355cea27bb", + "reference": "7e279d2cd5d7fbb156ce46daada972355cea27bb", + "shasum": "" + }, + "require": { + "php": "^7.0|^8.0", + "phpoption/phpoption": "^1.7.3" + }, + "require-dev": { + "phpunit/phpunit": "^6.5|^7.5|^8.5|^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "GrahamCampbell\\ResultType\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Graham Campbell", + "email": "graham@alt-three.com" + } + ], + "description": "An Implementation Of The Result Type", + "keywords": [ + "Graham Campbell", + "GrahamCampbell", + "Result Type", + "Result-Type", + "result" + ], + "support": { + "issues": "https://github.com/GrahamCampbell/Result-Type/issues", + "source": "https://github.com/GrahamCampbell/Result-Type/tree/v1.0.1" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/graham-campbell/result-type", + "type": "tidelift" + } + ], + "time": "2020-04-13T13:17:36+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "7.2.0", @@ -1006,16 +1069,16 @@ }, { "name": "guzzlehttp/promises", - "version": "1.4.0", + "version": "1.4.1", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "60d379c243457e073cff02bc323a2a86cb355631" + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/60d379c243457e073cff02bc323a2a86cb355631", - "reference": "60d379c243457e073cff02bc323a2a86cb355631", + "url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d", + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d", "shasum": "" }, "require": { @@ -1055,9 +1118,9 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/1.4.0" + "source": "https://github.com/guzzle/promises/tree/1.4.1" }, - "time": "2020-09-30T07:37:28+00:00" + "time": "2021-03-07T09:25:29+00:00" }, { "name": "guzzlehttp/psr7", @@ -1256,21 +1319,21 @@ }, { "name": "laravel/framework", - "version": "v7.30.4", + "version": "v8.31.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "9dd38140dc2924daa1a020a3d7a45f9ceff03df3" + "reference": "2aa5c2488d25178ebc097052c7897a0e463ddc35" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/9dd38140dc2924daa1a020a3d7a45f9ceff03df3", - "reference": "9dd38140dc2924daa1a020a3d7a45f9ceff03df3", + "url": "https://api.github.com/repos/laravel/framework/zipball/2aa5c2488d25178ebc097052c7897a0e463ddc35", + "reference": "2aa5c2488d25178ebc097052c7897a0e463ddc35", "shasum": "" }, "require": { "doctrine/inflector": "^1.4|^2.0", - "dragonmantank/cron-expression": "^2.3.1", + "dragonmantank/cron-expression": "^3.0.2", "egulias/email-validator": "^2.1.10", "ext-json": "*", "ext-mbstring": "*", @@ -1280,23 +1343,22 @@ "monolog/monolog": "^2.0", "nesbot/carbon": "^2.31", "opis/closure": "^3.6", - "php": "^7.2.5|^8.0", + "php": "^7.3|^8.0", "psr/container": "^1.0", "psr/simple-cache": "^1.0", - "ramsey/uuid": "^3.7|^4.0", + "ramsey/uuid": "^4.0", "swiftmailer/swiftmailer": "^6.0", - "symfony/console": "^5.0", - "symfony/error-handler": "^5.0", - "symfony/finder": "^5.0", - "symfony/http-foundation": "^5.0", - "symfony/http-kernel": "^5.0", - "symfony/mime": "^5.0", - "symfony/polyfill-php73": "^1.17", - "symfony/process": "^5.0", - "symfony/routing": "^5.0", - "symfony/var-dumper": "^5.0", + "symfony/console": "^5.1.4", + "symfony/error-handler": "^5.1.4", + "symfony/finder": "^5.1.4", + "symfony/http-foundation": "^5.1.4", + "symfony/http-kernel": "^5.1.4", + "symfony/mime": "^5.1.4", + "symfony/process": "^5.1.4", + "symfony/routing": "^5.1.4", + "symfony/var-dumper": "^5.1.4", "tijsverkoyen/css-to-inline-styles": "^2.2.2", - "vlucas/phpdotenv": "^4.0", + "vlucas/phpdotenv": "^5.2", "voku/portable-ascii": "^1.4.8" }, "conflict": { @@ -1310,6 +1372,7 @@ "illuminate/broadcasting": "self.version", "illuminate/bus": "self.version", "illuminate/cache": "self.version", + "illuminate/collections": "self.version", "illuminate/config": "self.version", "illuminate/console": "self.version", "illuminate/container": "self.version", @@ -1322,6 +1385,7 @@ "illuminate/hashing": "self.version", "illuminate/http": "self.version", "illuminate/log": "self.version", + "illuminate/macroable": "self.version", "illuminate/mail": "self.version", "illuminate/notifications": "self.version", "illuminate/pagination": "self.version", @@ -1338,21 +1402,21 @@ }, "require-dev": { "aws/aws-sdk-php": "^3.155", - "doctrine/dbal": "^2.6", + "doctrine/dbal": "^2.6|^3.0", "filp/whoops": "^2.8", - "guzzlehttp/guzzle": "^6.3.1|^7.0.1", + "guzzlehttp/guzzle": "^6.5.5|^7.0.1", "league/flysystem-cached-adapter": "^1.0", - "mockery/mockery": "~1.3.3|^1.4.2", - "moontoast/math": "^1.1", - "orchestra/testbench-core": "^5.8", + "mockery/mockery": "^1.4.2", + "orchestra/testbench-core": "^6.8", "pda/pheanstalk": "^4.0", - "phpunit/phpunit": "^8.4|^9.3.3", + "phpunit/phpunit": "^8.5.8|^9.3.3", "predis/predis": "^1.1.1", - "symfony/cache": "^5.0" + "symfony/cache": "^5.1.4" }, "suggest": { "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.155).", - "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6).", + "brianium/paratest": "Required to run tests in parallel (^6.0).", + "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6|^3.0).", "ext-ftp": "Required to use the Flysystem FTP driver.", "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", "ext-memcached": "Required to use the memcache cache driver.", @@ -1361,37 +1425,42 @@ "ext-redis": "Required to use the Redis cache and queue drivers (^4.0|^5.0).", "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", "filp/whoops": "Required for friendly error pages in development (^2.8).", - "guzzlehttp/guzzle": "Required to use the HTTP Client, Mailgun mail driver and the ping methods on schedules (^6.3.1|^7.0.1).", + "guzzlehttp/guzzle": "Required to use the HTTP Client, Mailgun mail driver and the ping methods on schedules (^6.5.5|^7.0.1).", "laravel/tinker": "Required to use the tinker console command (^2.0).", "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^1.0).", "league/flysystem-cached-adapter": "Required to use the Flysystem cache (^1.0).", "league/flysystem-sftp": "Required to use the Flysystem SFTP driver (^1.0).", - "mockery/mockery": "Required to use mocking (~1.3.3|^1.4.2).", - "moontoast/math": "Required to use ordered UUIDs (^1.1).", + "mockery/mockery": "Required to use mocking (^1.4.2).", "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^4.0).", - "phpunit/phpunit": "Required to use assertions and run tests (^8.4|^9.3.3).", + "phpunit/phpunit": "Required to use assertions and run tests (^8.5.8|^9.3.3).", "predis/predis": "Required to use the predis connector (^1.1.2).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", - "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^5.0).", - "symfony/filesystem": "Required to create relative storage directory symbolic links (^5.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0|^5.0).", + "symfony/cache": "Required to PSR-6 cache bridge (^5.1.4).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^5.1.4).", "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0).", "wildbit/swiftmailer-postmark": "Required to use Postmark mail driver (^3.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "7.x-dev" + "dev-master": "8.x-dev" } }, "autoload": { "files": [ + "src/Illuminate/Collections/helpers.php", + "src/Illuminate/Events/functions.php", "src/Illuminate/Foundation/helpers.php", "src/Illuminate/Support/helpers.php" ], "psr-4": { - "Illuminate\\": "src/Illuminate/" + "Illuminate\\": "src/Illuminate/", + "Illuminate\\Support\\": [ + "src/Illuminate/Macroable/", + "src/Illuminate/Collections/" + ] } }, "notification-url": "https://packagist.org/downloads/", @@ -1414,7 +1483,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2021-01-21T14:10:48+00:00" + "time": "2021-03-04T15:22:36+00:00" }, { "name": "laravel/slack-notification-channel", @@ -1547,26 +1616,29 @@ }, { "name": "laravel/ui", - "version": "v2.5.0", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/laravel/ui.git", - "reference": "d01a705763c243b07be795e9d1bb47f89260f73d" + "reference": "a1f82c6283c8373ea1958b8a27c3d5c98cade351" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/ui/zipball/d01a705763c243b07be795e9d1bb47f89260f73d", - "reference": "d01a705763c243b07be795e9d1bb47f89260f73d", + "url": "https://api.github.com/repos/laravel/ui/zipball/a1f82c6283c8373ea1958b8a27c3d5c98cade351", + "reference": "a1f82c6283c8373ea1958b8a27c3d5c98cade351", "shasum": "" }, "require": { - "illuminate/console": "^7.0", - "illuminate/filesystem": "^7.0", - "illuminate/support": "^7.0", - "php": "^7.2.5|^8.0" + "illuminate/console": "^8.0", + "illuminate/filesystem": "^8.0", + "illuminate/support": "^8.0", + "php": "^7.3|^8.0" }, "type": "library", "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + }, "laravel": { "providers": [ "Laravel\\Ui\\UiServiceProvider" @@ -1596,9 +1668,9 @@ ], "support": { "issues": "https://github.com/laravel/ui/issues", - "source": "https://github.com/laravel/ui/tree/v2.5.0" + "source": "https://github.com/laravel/ui/tree/v3.2.0" }, - "time": "2020-11-03T19:45:19+00:00" + "time": "2021-01-06T19:20:22+00:00" }, { "name": "lcobucci/jwt", @@ -5459,37 +5531,39 @@ }, { "name": "vlucas/phpdotenv", - "version": "v4.2.0", + "version": "v5.3.0", "source": { "type": "git", "url": "https://github.com/vlucas/phpdotenv.git", - "reference": "da64796370fc4eb03cc277088f6fede9fde88482" + "reference": "b3eac5c7ac896e52deab4a99068e3f4ab12d9e56" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/da64796370fc4eb03cc277088f6fede9fde88482", - "reference": "da64796370fc4eb03cc277088f6fede9fde88482", + "url": "https://api.github.com/repos/vlucas/phpdotenv/zipball/b3eac5c7ac896e52deab4a99068e3f4ab12d9e56", + "reference": "b3eac5c7ac896e52deab4a99068e3f4ab12d9e56", "shasum": "" }, "require": { - "php": "^5.5.9 || ^7.0 || ^8.0", - "phpoption/phpoption": "^1.7.3", - "symfony/polyfill-ctype": "^1.17" + "ext-pcre": "*", + "graham-campbell/result-type": "^1.0.1", + "php": "^7.1.3 || ^8.0", + "phpoption/phpoption": "^1.7.4", + "symfony/polyfill-ctype": "^1.17", + "symfony/polyfill-mbstring": "^1.17", + "symfony/polyfill-php80": "^1.17" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.4.1", "ext-filter": "*", - "ext-pcre": "*", - "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20" + "phpunit/phpunit": "^7.5.20 || ^8.5.14 || ^9.5.1" }, "suggest": { - "ext-filter": "Required to use the boolean validator.", - "ext-pcre": "Required to use most of the library." + "ext-filter": "Required to use the boolean validator." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.1-dev" + "dev-master": "5.3-dev" } }, "autoload": { @@ -5521,7 +5595,7 @@ ], "support": { "issues": "https://github.com/vlucas/phpdotenv/issues", - "source": "https://github.com/vlucas/phpdotenv/tree/v4.2.0" + "source": "https://github.com/vlucas/phpdotenv/tree/v5.3.0" }, "funding": [ { @@ -5533,7 +5607,7 @@ "type": "tidelift" } ], - "time": "2021-01-20T15:11:48+00:00" + "time": "2021-01-20T15:23:13+00:00" }, { "name": "voku/portable-ascii", @@ -5608,49 +5682,102 @@ } ], "time": "2020-11-12T00:07:28+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<3.9.1" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^7.5.13" + }, + "type": "library", + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.9.1" + }, + "time": "2020-07-08T17:02:28+00:00" } ], "packages-dev": [ { "name": "barryvdh/laravel-ide-helper", - "version": "v2.8.2", + "version": "v2.9.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-ide-helper.git", - "reference": "5515cabea39b9cf55f98980d0f269dc9d85cfcca" + "reference": "64a6b902583802c162cdccf7e76dc8619368bf1a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/5515cabea39b9cf55f98980d0f269dc9d85cfcca", - "reference": "5515cabea39b9cf55f98980d0f269dc9d85cfcca", + "url": "https://api.github.com/repos/barryvdh/laravel-ide-helper/zipball/64a6b902583802c162cdccf7e76dc8619368bf1a", + "reference": "64a6b902583802c162cdccf7e76dc8619368bf1a", "shasum": "" }, "require": { "barryvdh/reflection-docblock": "^2.0.6", "composer/composer": "^1.6 || ^2", - "doctrine/dbal": "~2.3", + "doctrine/dbal": "^2.6 || ^3", "ext-json": "*", - "illuminate/console": "^6 || ^7 || ^8", - "illuminate/filesystem": "^6 || ^7 || ^8", - "illuminate/support": "^6 || ^7 || ^8", - "php": ">=7.2", + "illuminate/console": "^8", + "illuminate/filesystem": "^8", + "illuminate/support": "^8", + "php": "^7.3 || ^8.0", "phpdocumentor/type-resolver": "^1.1.0" }, "require-dev": { "ext-pdo_sqlite": "*", "friendsofphp/php-cs-fixer": "^2", - "illuminate/config": "^6 || ^7 || ^8", - "illuminate/view": "^6 || ^7 || ^8", - "mockery/mockery": "^1.3.3", - "orchestra/testbench": "^4 || ^5 || ^6", + "illuminate/config": "^8", + "illuminate/view": "^8", + "mockery/mockery": "^1.4", + "orchestra/testbench": "^6", "phpunit/phpunit": "^8.5 || ^9", - "spatie/phpunit-snapshot-assertions": "^1.4 || ^2.2 || ^3 || ^4", + "spatie/phpunit-snapshot-assertions": "^3 || ^4", "vimeo/psalm": "^3.12" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "2.9-dev" }, "laravel": { "providers": [ @@ -5687,7 +5814,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-ide-helper/issues", - "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v2.8.2" + "source": "https://github.com/barryvdh/laravel-ide-helper/tree/v2.9.0" }, "funding": [ { @@ -5695,7 +5822,7 @@ "type": "github" } ], - "time": "2020-12-06T08:55:05+00:00" + "time": "2020-12-29T10:11:05+00:00" }, { "name": "barryvdh/reflection-docblock", @@ -5749,6 +5876,86 @@ }, "time": "2018-12-13T10:34:14+00:00" }, + { + "name": "brianium/paratest", + "version": "v6.2.0", + "source": { + "type": "git", + "url": "https://github.com/paratestphp/paratest.git", + "reference": "9a94366983ce32c7724fc92e3b544327d4adb9be" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/9a94366983ce32c7724fc92e3b544327d4adb9be", + "reference": "9a94366983ce32c7724fc92e3b544327d4adb9be", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-simplexml": "*", + "php": "^7.3 || ^8.0", + "phpunit/php-code-coverage": "^9.2.5", + "phpunit/php-file-iterator": "^3.0.5", + "phpunit/php-timer": "^5.0.3", + "phpunit/phpunit": "^9.5.1", + "sebastian/environment": "^5.1.3", + "symfony/console": "^4.4 || ^5.2", + "symfony/process": "^4.4 || ^5.2" + }, + "require-dev": { + "doctrine/coding-standard": "^8.2.0", + "ekino/phpstan-banned-code": "^0.3.1", + "ergebnis/phpstan-rules": "^0.15.3", + "ext-posix": "*", + "infection/infection": "^0.20.2", + "phpstan/phpstan": "^0.12.70", + "phpstan/phpstan-deprecation-rules": "^0.12.6", + "phpstan/phpstan-phpunit": "^0.12.17", + "phpstan/phpstan-strict-rules": "^0.12.9", + "squizlabs/php_codesniffer": "^3.5.8", + "symfony/filesystem": "^5.2.2", + "thecodingmachine/phpstan-strict-rules": "^0.12.1", + "vimeo/psalm": "^4.4.1" + }, + "bin": [ + "bin/paratest" + ], + "type": "library", + "autoload": { + "psr-4": { + "ParaTest\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Scaturro", + "email": "scaturrob@gmail.com", + "homepage": "http://brianscaturro.com", + "role": "Lead" + } + ], + "description": "Parallel testing for PHP", + "homepage": "https://github.com/paratestphp/paratest", + "keywords": [ + "concurrent", + "parallel", + "phpunit", + "testing" + ], + "support": { + "issues": "https://github.com/paratestphp/paratest/issues", + "source": "https://github.com/paratestphp/paratest/tree/v6.2.0" + }, + "time": "2021-01-29T15:25:31+00:00" + }, { "name": "composer/ca-bundle", "version": "1.2.9", @@ -6586,6 +6793,75 @@ }, "time": "2020-07-09T08:09:16+00:00" }, + { + "name": "itsgoingd/clockwork", + "version": "v5.0.6", + "source": { + "type": "git", + "url": "https://github.com/itsgoingd/clockwork.git", + "reference": "1de3f9f9fc22217aa024f79ecbdf0fde418fc0a1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/itsgoingd/clockwork/zipball/1de3f9f9fc22217aa024f79ecbdf0fde418fc0a1", + "reference": "1de3f9f9fc22217aa024f79ecbdf0fde418fc0a1", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=5.6", + "psr/log": "1.*" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Clockwork\\Support\\Laravel\\ClockworkServiceProvider" + ], + "aliases": { + "Clockwork": "Clockwork\\Support\\Laravel\\Facade" + } + } + }, + "autoload": { + "psr-4": { + "Clockwork\\": "Clockwork/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "itsgoingd", + "email": "itsgoingd@luzer.sk", + "homepage": "https://twitter.com/itsgoingd" + } + ], + "description": "php dev tools in your browser", + "homepage": "https://underground.works/clockwork", + "keywords": [ + "Devtools", + "debugging", + "laravel", + "logging", + "lumen", + "profiling", + "slim" + ], + "support": { + "issues": "https://github.com/itsgoingd/clockwork/issues", + "source": "https://github.com/itsgoingd/clockwork/tree/v5.0.6" + }, + "funding": [ + { + "url": "https://github.com/itsgoingd", + "type": "github" + } + ], + "time": "2020-12-27T00:18:25+00:00" + }, { "name": "justinrainbow/json-schema", "version": "5.2.10", @@ -9024,59 +9300,6 @@ } ], "time": "2020-07-12T23:59:07+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.9.1", - "source": { - "type": "git", - "url": "https://github.com/webmozarts/assert.git", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<3.9.1" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.5.13" - }, - "type": "library", - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozarts/assert/issues", - "source": "https://github.com/webmozarts/assert/tree/1.9.1" - }, - "time": "2020-07-08T17:02:28+00:00" } ], "aliases": [], diff --git a/storage/clockwork/.gitignore b/storage/clockwork/.gitignore new file mode 100644 index 00000000..3fac1bff --- /dev/null +++ b/storage/clockwork/.gitignore @@ -0,0 +1,3 @@ +*.json +*.json.gz +index From 1fd033b3c1398986a461b21db386166f31c6304b Mon Sep 17 00:00:00 2001 From: Henry Whitaker Date: Sun, 7 Mar 2021 09:46:44 +0000 Subject: [PATCH 02/26] Grab all settings instead of new query for each one --- app/Helpers/SettingsHelper.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/Helpers/SettingsHelper.php b/app/Helpers/SettingsHelper.php index 8acffb36..1ff03877 100644 --- a/app/Helpers/SettingsHelper.php +++ b/app/Helpers/SettingsHelper.php @@ -9,6 +9,7 @@ use Carbon\Carbon; class SettingsHelper { + private static $settings = null; /** * Get a Setting object by name @@ -18,12 +19,16 @@ class SettingsHelper */ public static function get(String $name) { - $name = Setting::where('name', $name)->get(); + if (self::$settings === null) { + self::$settings = Setting::get(); + } + + $name = self::$settings->where('name', $name); if (sizeof($name) == 0) { return false; } else if (sizeof($name) == 1) { - return $name[0]; + return $name->first(); } else { $name = $name->keyBy('name'); return $name->all(); From ba8f82aa98bc5d619c21e95c72a4881130dfff3d Mon Sep 17 00:00:00 2001 From: Henry Whitaker Date: Sun, 7 Mar 2021 09:53:01 +0000 Subject: [PATCH 03/26] Ignore file from clockwork --- config/clockwork.php | 409 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 409 insertions(+) create mode 100644 config/clockwork.php diff --git a/config/clockwork.php b/config/clockwork.php new file mode 100644 index 00000000..6d866808 --- /dev/null +++ b/config/clockwork.php @@ -0,0 +1,409 @@ + env('CLOCKWORK_ENABLE', null), + + /* + |------------------------------------------------------------------------------------------------------------------ + | Features + |------------------------------------------------------------------------------------------------------------------ + | + | You can enable or disable various Clockwork features here. Some features have additional settings (eg. slow query + | threshold for database queries). + | + */ + + 'features' => [ + + // Cache usage stats and cache queries including results + 'cache' => [ + 'enabled' => env('CLOCKWORK_CACHE_ENABLED', true), + + // Collect cache queries including results (high performance impact with a high number of queries) + 'collect_queries' => env('CLOCKWORK_CACHE_QUERIES', false) + ], + + // Database usage stats and queries + 'database' => [ + 'enabled' => env('CLOCKWORK_DATABASE_ENABLED', true), + + // Collect database queries (high performance impact with a very high number of queries) + 'collect_queries' => env('CLOCKWORK_DATABASE_COLLECT_QUERIES', true), + + // Collect details of models updates (high performance impact with a lot of model updates) + 'collect_models_actions' => env('CLOCKWORK_DATABASE_COLLECT_MODELS_ACTIONS', true), + + // Collect details of retrieved models (very high performance impact with a lot of models retrieved) + 'collect_models_retrieved' => env('CLOCKWORK_DATABASE_COLLECT_MODELS_RETRIEVED', false), + + // Query execution time threshold in miliseconds after which the query will be marked as slow + 'slow_threshold' => env('CLOCKWORK_DATABASE_SLOW_THRESHOLD'), + + // Collect only slow database queries + 'slow_only' => env('CLOCKWORK_DATABASE_SLOW_ONLY', false), + + // Detect and report duplicate (N+1) queries + 'detect_duplicate_queries' => env('CLOCKWORK_DATABASE_DETECT_DUPLICATE_QUERIES', false) + ], + + // Dispatched events + 'events' => [ + 'enabled' => env('CLOCKWORK_EVENTS_ENABLED', true), + + // Ignored events (framework events are ignored by default) + 'ignored_events' => [ + // App\Events\UserRegistered::class, + // 'user.registered' + ], + ], + + // Laravel log (you can still log directly to Clockwork with laravel log disabled) + 'log' => [ + 'enabled' => env('CLOCKWORK_LOG_ENABLED', true) + ], + + // Sent notifications + 'notifications' => [ + 'enabled' => env('CLOCKWORK_NOTIFICATIONS_ENABLED', true), + ], + + // Performance metrics + 'performance' => [ + // Allow collecting of client metrics. Requires separate clockwork-browser npm package. + 'client_metrics' => env('CLOCKWORK_PERFORMANCE_CLIENT_METRICS', true) + ], + + // Dispatched queue jobs + 'queue' => [ + 'enabled' => env('CLOCKWORK_QUEUE_ENABLED', true) + ], + + // Redis commands + 'redis' => [ + 'enabled' => env('CLOCKWORK_REDIS_ENABLED', true) + ], + + // Routes list + 'routes' => [ + 'enabled' => env('CLOCKWORK_ROUTES_ENABLED', false) + ], + + // Rendered views + 'views' => [ + 'enabled' => env('CLOCKWORK_VIEWS_ENABLED', true), + + // Collect views including view data (high performance impact with a high number of views) + 'collect_data' => env('CLOCKWORK_VIEWS_COLLECT_DATA', false), + + // Use Twig profiler instead of Laravel events for apps using laravel-twigbridge (more precise, but does + // not support collecting view data) + 'use_twig_profiler' => env('CLOCKWORK_VIEWS_USE_TWIG_PROFILER', false) + ] + + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Enable web UI + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork comes with a web UI accessibla via http://your.app/clockwork. Here you can enable or disable this + | feature. You can also set a custom path for the web UI. + | + */ + + 'web' => env('CLOCKWORK_WEB', true), + + /* + |------------------------------------------------------------------------------------------------------------------ + | Enable toolbar + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can show a toolbar with basic metrics on all responses. Here you can enable or disable this feature. + | Requires a separate clockwork-browser npm library. + | + */ + + 'toolbar' => env('CLOCKWORK_TOOLBAR', false), + + /* + |------------------------------------------------------------------------------------------------------------------ + | HTTP requests collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork collects data about HTTP requests to your app. Here you can choose which requests should be collected. + | + */ + + 'requests' => [ + // With on-demand mode enabled, Clockwork will only profile requests when the browser extension is open or you + // manually pass a "clockwork-profile" cookie or get/post data key. + // Optionally you can specify a "secret" that has to be passed as the value to enable profiling. + 'on_demand' => env('CLOCKWORK_REQUESTS_ON_DEMAND', false), + + // Collect only errors (requests with HTTP 4xx and 5xx responses) + 'errors_only' => env('CLOCKWORK_REQUESTS_ERRORS_ONLY', false), + + // Response time threshold in miliseconds after which the request will be marked as slow + 'slow_threshold' => env('CLOCKWORK_REQUESTS_SLOW_THRESHOLD'), + + // Collect only slow requests + 'slow_only' => env('CLOCKWORK_REQUESTS_SLOW_ONLY', false), + + // Sample the collected requests (eg. set to 100 to collect only 1 in 100 requests) + 'sample' => env('CLOCKWORK_REQUESTS_SAMPLE', false), + + // List of URIs that should not be collected + 'except' => [ + '/horizon/.*', // Laravel Horizon requests + '/telescope/.*', // Laravel Telescope requests + '/files/*' + ], + + // List of URIs that should be collected, any other URI will not be collected if not empty + 'only' => [ + // '/api/.*' + ], + + // Don't collect OPTIONS requests, mostly used in the CSRF pre-flight requests and are rarely of interest + 'except_preflight' => env('CLOCKWORK_REQUESTS_EXCEPT_PREFLIGHT', true) + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Artisan commands collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can collect data about executed artisan commands. Here you can enable and configure which commands + | should be collected. + | + */ + + 'artisan' => [ + // Enable or disable collection of executed Artisan commands + 'collect' => env('CLOCKWORK_ARTISAN_COLLECT', false), + + // List of commands that should not be collected (built-in commands are not collected by default) + 'except' => [ + // 'inspire' + ], + + // List of commands that should be collected, any other command will not be collected if not empty + 'only' => [ + // 'inspire' + ], + + // Enable or disable collection of command output + 'collect_output' => env('CLOCKWORK_ARTISAN_COLLECT_OUTPUT', false), + + // Enable or disable collection of built-in Laravel commands + 'except_laravel_commands' => env('CLOCKWORK_ARTISAN_EXCEPT_LARAVEL_COMMANDS', true) + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Queue jobs collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can collect data about executed queue jobs. Here you can enable and configure which queue jobs should + | be collected. + | + */ + + 'queue' => [ + // Enable or disable collection of executed queue jobs + 'collect' => env('CLOCKWORK_QUEUE_COLLECT', false), + + // List of queue jobs that should not be collected + 'except' => [ + // App\Jobs\ExpensiveJob::class + ], + + // List of queue jobs that should be collected, any other queue job will not be collected if not empty + 'only' => [ + // App\Jobs\BuggyJob::class + ] + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Tests collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can collect data about executed tests. Here you can enable and configure which tests should be + | collected. + | + */ + + 'tests' => [ + // Enable or disable collection of ran tests + 'collect' => env('CLOCKWORK_TESTS_COLLECT', false), + + // List of tests that should not be collected + 'except' => [ + // Tests\Unit\ExampleTest::class + ] + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Enable data collection when Clockwork is disabled + |------------------------------------------------------------------------------------------------------------------ + | + | You can enable this setting to collect data even when Clockwork is disabled. Eg. for future analysis. + | + */ + + 'collect_data_always' => env('CLOCKWORK_COLLECT_DATA_ALWAYS', false), + + /* + |------------------------------------------------------------------------------------------------------------------ + | Metadata storage + |------------------------------------------------------------------------------------------------------------------ + | + | Configure how is the metadata collected by Clockwork stored. Two options are available: + | - files - A simple fast storage implementation storing data in one-per-request files. + | - sql - Stores requests in a sql database. Supports MySQL, Postgresql, Sqlite and requires PDO. + | + */ + + 'storage' => env('CLOCKWORK_STORAGE', 'files'), + + // Path where the Clockwork metadata is stored + 'storage_files_path' => env('CLOCKWORK_STORAGE_FILES_PATH', storage_path('clockwork')), + + // Compress the metadata files using gzip, trading a little bit of performance for lower disk usage + 'storage_files_compress' => env('CLOCKWORK_STORAGE_FILES_COMPRESS', false), + + // SQL database to use, can be a name of database configured in database.php or a path to a sqlite file + 'storage_sql_database' => env('CLOCKWORK_STORAGE_SQL_DATABASE', storage_path('clockwork.sqlite')), + + // SQL table name to use, the table is automatically created and udpated when needed + 'storage_sql_table' => env('CLOCKWORK_STORAGE_SQL_TABLE', 'clockwork'), + + // Maximum lifetime of collected metadata in minutes, older requests will automatically be deleted, false to disable + 'storage_expiration' => env('CLOCKWORK_STORAGE_EXPIRATION', 60 * 24 * 7), + + /* + |------------------------------------------------------------------------------------------------------------------ + | Authentication + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can be configured to require authentication before allowing access to the collected data. This might be + | useful when the application is publicly accessible. Setting to true will enable a simple authentication with a + | pre-configured password. You can also pass a class name of a custom implementation. + | + */ + + 'authentication' => env('CLOCKWORK_AUTHENTICATION', false), + + // Password for the simple authentication + 'authentication_password' => env('CLOCKWORK_AUTHENTICATION_PASSWORD', 'VerySecretPassword'), + + /* + |------------------------------------------------------------------------------------------------------------------ + | Stack traces collection + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork can collect stack traces for log messages and certain data like database queries. Here you can set + | whether to collect stack traces, limit the number of collected frames and set further configuration. Collecting + | long stack traces considerably increases metadata size. + | + */ + + 'stack_traces' => [ + // Enable or disable collecting of stack traces + 'enabled' => env('CLOCKWORK_STACK_TRACES_ENABLED', true), + + // Limit the number of frames to be collected + 'limit' => env('CLOCKWORK_STACK_TRACES_LIMIT', 10), + + // List of vendor names to skip when determining caller, common vendors are automatically added + 'skip_vendors' => [ + // 'phpunit' + ], + + // List of namespaces to skip when determining caller + 'skip_namespaces' => [ + // 'Laravel' + ], + + // List of class names to skip when determining caller + 'skip_classes' => [ + // App\CustomLog::class + ] + + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Serialization + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork serializes the collected data to json for storage and transfer. Here you can configure certain aspects + | of serialization. Serialization has a large effect on the cpu time and memory usage. + | + */ + + // Maximum depth of serialized multi-level arrays and objects + 'serialization_depth' => env('CLOCKWORK_SERIALIZATION_DEPTH', 10), + + // A list of classes that will never be serialized (eg. a common service container class) + 'serialization_blackbox' => [ + \Illuminate\Container\Container::class, + \Illuminate\Foundation\Application::class, + \Laravel\Lumen\Application::class + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Register helpers + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork comes with a "clock" global helper function. You can use this helper to quickly log something and to + | access the Clockwork instance. + | + */ + + 'register_helpers' => env('CLOCKWORK_REGISTER_HELPERS', true), + + /* + |------------------------------------------------------------------------------------------------------------------ + | Send Headers for AJAX request + |------------------------------------------------------------------------------------------------------------------ + | + | When trying to collect data the AJAX method can sometimes fail if it is missing required headers. For example, an + | API might require a version number using Accept headers to route the HTTP request to the correct codebase. + | + */ + + 'headers' => [ + // 'Accept' => 'application/vnd.com.whatever.v1+json', + ], + + /* + |------------------------------------------------------------------------------------------------------------------ + | Server-Timing + |------------------------------------------------------------------------------------------------------------------ + | + | Clockwork supports the W3C Server Timing specification, which allows for collecting a simple performance metrics + | in a cross-browser way. Eg. in Chrome, your app, database and timeline event timings will be shown in the Dev + | Tools network tab. This setting specifies the max number of timeline events that will be sent. Setting to false + | will disable the feature. + | + */ + + 'server_timing' => env('CLOCKWORK_SERVER_TIMING', 10) + +]; From a2d8886bae92f4f6e4cf6d079691967a2488a648 Mon Sep 17 00:00:00 2001 From: Henry Whitaker Date: Sun, 7 Mar 2021 10:26:09 +0000 Subject: [PATCH 04/26] Moved speedtest logic into interface --- app/Actions/QueueSpeedtest.php | 35 ++++ app/Exceptions/SpeedtestFailureException.php | 10 + app/Helpers/SpeedtestHelper.php | 190 ++++-------------- app/Http/Controllers/SpeedtestController.php | 58 +----- app/Interfaces/SpeedtestProvider.php | 11 + app/Jobs/SpeedtestJob.php | 11 +- app/Providers/SpeedtestServiceProvider.php | 34 ++++ app/Utils/OoklaTester.php | 128 ++++++++++++ config/app.php | 1 + ..._101259_add_speedtest_provider_setting.php | 38 ++++ 10 files changed, 315 insertions(+), 201 deletions(-) create mode 100644 app/Actions/QueueSpeedtest.php create mode 100644 app/Exceptions/SpeedtestFailureException.php create mode 100644 app/Interfaces/SpeedtestProvider.php create mode 100644 app/Providers/SpeedtestServiceProvider.php create mode 100644 app/Utils/OoklaTester.php create mode 100644 database/migrations/2021_03_07_101259_add_speedtest_provider_setting.php diff --git a/app/Actions/QueueSpeedtest.php b/app/Actions/QueueSpeedtest.php new file mode 100644 index 00000000..e52038e8 --- /dev/null +++ b/app/Actions/QueueSpeedtest.php @@ -0,0 +1,35 @@ +speedtestProvider = $speedtestProvider; + } + + /** + * Run the action. + * + * @return mixed + */ + public function run() + { + SettingsHelper::loadIntegrationConfig(); + + SpeedtestJob::dispatch(false, config('integrations'), $this->speedtestProvider); + } +} diff --git a/app/Exceptions/SpeedtestFailureException.php b/app/Exceptions/SpeedtestFailureException.php new file mode 100644 index 00000000..ca668814 --- /dev/null +++ b/app/Exceptions/SpeedtestFailureException.php @@ -0,0 +1,10 @@ + $output['ping']['latency'], - 'download' => SpeedtestHelper::convert($output['download']['bandwidth']), - 'upload' => SpeedtestHelper::convert($output['upload']['bandwidth']), - 'server_id' => $output['server']['id'], - 'server_name' => $output['server']['name'], - 'server_host' => $output['server']['host'] . ':' . $output['server']['port'], - 'url' => $output['result']['url'], - 'scheduled' => $scheduled - ]); - } catch(JsonException $e) { - Log::error('Failed to parse speedtest JSON'); - Log::error($output); - $test = false; - } catch(Exception $e) { - Log::error($e->getMessage()); - $test = false; - } - - if($test == false) { - Speedtest::create([ - 'ping' => 0, - 'upload' => 0, - 'download' => 0, - 'failed' => true, - 'scheduled' => $scheduled, - ]); - - return false; - } - - Cache::flush(); - - return $test; - } - - /** - * Gets the output of executing speedtest binary. - * - * @return boolean|string - */ - public static function output() - { - $server = SettingsHelper::get('server')['value']; - - $binPath = app_path() . DIRECTORY_SEPARATOR . 'Bin' . DIRECTORY_SEPARATOR . 'speedtest'; - $homePrefix = config('speedtest.home') . ' && '; - - if($server != '' && $server != false) { - $server = explode(',', $server); - $server = $server[array_rand($server)]; - if($server == false) { - Log::error('Speedtest server undefined'); - return false; - } - - return shell_exec($homePrefix . $binPath . ' -f json -s ' . $server); - } - - return shell_exec($homePrefix . $binPath . ' -f json'); + $tester = new OoklaTester(); + return $tester->run(); } /** @@ -105,10 +38,10 @@ class SpeedtestHelper { { $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) - ->where('failed', false) - ->first() - ->toArray(); + ->where('created_at', '>=', $t) + ->where('failed', false) + ->first() + ->toArray(); return $s; } @@ -119,8 +52,9 @@ class SpeedtestHelper { * @param int|float $bytes * @return int|float */ - public static function convert($bytes) { - return ( $bytes * 8 ) / 1000000; + public static function convert($bytes) + { + return ($bytes * 8) / 1000000; } /** @@ -132,7 +66,7 @@ class SpeedtestHelper { { $data = Speedtest::latest()->get(); - if($data->isEmpty()) { + if ($data->isEmpty()) { return false; } @@ -152,7 +86,7 @@ class SpeedtestHelper { $val = (float)$input[0]; $unit = explode('/', $input[1])[0]; - switch($unit) { + switch ($unit) { case 'Mbyte': $val = $val * 8; break; @@ -173,48 +107,6 @@ class SpeedtestHelper { ]; } - /** - * Checks that the speedtest JSON output is complete/valid - * - * @param array $output - * @return boolean - */ - public static function checkOutputIsComplete($output) - { - /** - * Array of indexes that must exist in $output - */ - $checks = [ - 'type' => 'result', - 'download' => [ 'bandwidth' => '*' ], - 'upload' => [ 'bandwidth' => '*' ], - 'ping' => [ 'latency' => '*' ], - 'server' => [ - 'id' => '*', - 'name' => '*', - 'host' => '*', - 'port' => '*' - ], - 'result' => [ - 'url' => '*' - ], - ]; - /** - * Array of indexes that must not exist - */ - $checkMissing = [ - 'type' => 'error' - ]; - - foreach($checks as $key => $value) { - if(!isset($output[$key])) { - return false; - } - } - - return true; - } - /** * Get a percentage rate of failure by days * @@ -228,7 +120,7 @@ class SpeedtestHelper { $range = [ Carbon::today() ]; - for($i = 0; $i < ($days - 1); $i++) { + for ($i = 0; $i < ($days - 1); $i++) { $prev = end($range); $new = $prev->copy()->subDays(1); array_push($range, $new); @@ -236,7 +128,7 @@ class SpeedtestHelper { $rate = []; - foreach($range as $day) { + foreach ($range as $day) { $success = Speedtest::select(DB::raw('COUNT(id) as rate'))->whereDate('created_at', $day)->where('failed', false)->get()[0]['rate']; $fail = Speedtest::select(DB::raw('COUNT(id) as rate'))->whereDate('created_at', $day)->where('failed', true)->get()[0]['rate']; @@ -260,14 +152,14 @@ class SpeedtestHelper { */ public static function dbBackup() { - if(env('DB_CONNECTION') === 'sqlite') { - if(env('DB_DATABASE') !== null) { + if (env('DB_CONNECTION') === 'sqlite') { + if (env('DB_DATABASE') !== null) { $current = env('DB_DATABASE'); try { - if(File::copy($current, $current . '.bak')) { + if (File::copy($current, $current . '.bak')) { return true; } - }catch(Exception $e) { + } catch (Exception $e) { return false; } } @@ -289,8 +181,8 @@ class SpeedtestHelper { SpeedtestHelper::dbBackup(); - if(sizeof(Speedtest::whereNotNull('id')->get()) > 0) { - if(Speedtest::whereNotNull('id')->delete()) { + if (sizeof(Speedtest::whereNotNull('id')->get()) > 0) { + if (Speedtest::whereNotNull('id')->delete()) { return [ 'success' => true, ]; @@ -311,31 +203,31 @@ class SpeedtestHelper { */ public static function testIsLowerThanThreshold(String $type, Speedtest $test) { - if($type == 'percentage') { + if ($type == 'percentage') { $avg = Speedtest::select(DB::raw('AVG(ping) as ping, AVG(download) as download, AVG(upload) as upload')) - ->where('failed', false) - ->get() - ->toArray()[0]; + ->where('failed', false) + ->get() + ->toArray()[0]; $threshold = SettingsHelper::get('threshold_alert_percentage')->value; - if($threshold == '') { + if ($threshold == '') { return []; } $errors = []; - foreach($avg as $key => $value) { - if($key == 'ping') { - $threshold = (float)$value * (1 + ( $threshold / 100 )); + foreach ($avg as $key => $value) { + if ($key == 'ping') { + $threshold = (float)$value * (1 + ($threshold / 100)); - if($test->$key > $threshold) { + if ($test->$key > $threshold) { array_push($errors, $key); } - } else { - $threshold = (float)$value * (1 - ( $threshold / 100 )); + } else { + $threshold = (float)$value * (1 - ($threshold / 100)); - if($test->$key < $threshold) { + if ($test->$key < $threshold) { array_push($errors, $key); } } @@ -344,7 +236,7 @@ class SpeedtestHelper { return $errors; } - if($type == 'absolute') { + if ($type == 'absolute') { $thresholds = [ 'download' => SettingsHelper::get('threshold_alert_absolute_download')->value, 'upload' => SettingsHelper::get('threshold_alert_absolute_upload')->value, @@ -353,17 +245,17 @@ class SpeedtestHelper { $errors = []; - foreach($thresholds as $key => $value) { - if($value == '') { + foreach ($thresholds as $key => $value) { + if ($value == '') { continue; } - if($key == 'ping') { - if($test->$key > $value) { + if ($key == 'ping') { + if ($test->$key > $value) { array_push($errors, $key); } } else { - if($test->$key < $value) { + if ($test->$key < $value) { array_push($errors, $key); } } diff --git a/app/Http/Controllers/SpeedtestController.php b/app/Http/Controllers/SpeedtestController.php index ddb4b719..900616c7 100644 --- a/app/Http/Controllers/SpeedtestController.php +++ b/app/Http/Controllers/SpeedtestController.php @@ -2,6 +2,9 @@ namespace App\Http\Controllers; +use App\Actions\GetLatestSpeedtestData; +use App\Actions\GetSpeedtestTimeData; +use App\Actions\QueueSpeedtest; use App\Helpers\SettingsHelper; use App\Helpers\SpeedtestHelper; use App\Jobs\SpeedtestJob; @@ -61,21 +64,7 @@ class SpeedtestController extends Controller ], 422); } - $ttl = Carbon::now()->addDays(1); - $data = Cache::remember('speedtest-days-' . $days, $ttl, function () use ($days) { - $showFailed = (bool)SettingsHelper::get('show_failed_tests_on_graph')->value; - - if ($showFailed === true) { - return Speedtest::where('created_at', '>=', Carbon::now()->subDays($days)) - ->orderBy('created_at', 'asc') - ->get(); - } - - return Speedtest::where('created_at', '>=', Carbon::now()->subDays($days)) - ->where('failed', false) - ->orderBy('created_at', 'asc') - ->get(); - }); + $data = run(GetSpeedtestTimeData::class, $days); return response()->json([ 'method' => 'get speedtests in last x days', @@ -121,39 +110,10 @@ class SpeedtestController extends Controller */ public function latest() { - $data = SpeedtestHelper::latest(); + $data = run(GetLatestSpeedtestData::class); - $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); + if ($data['data']) { + return response()->json($data, 200); } else { return response()->json([ 'method' => 'get latest speedtest', @@ -170,8 +130,8 @@ class SpeedtestController extends Controller public function run() { try { - SettingsHelper::loadIntegrationConfig(); - $data = SpeedtestJob::dispatch(false, config('integrations')); + run(QueueSpeedtest::class); + return response()->json([ 'method' => 'run speedtest', 'data' => 'a new speedtest has been added to the queue' diff --git a/app/Interfaces/SpeedtestProvider.php b/app/Interfaces/SpeedtestProvider.php new file mode 100644 index 00000000..f0124d7f --- /dev/null +++ b/app/Interfaces/SpeedtestProvider.php @@ -0,0 +1,11 @@ +scheduled = $scheduled; $this->config = $config; + $this->speedtestProvider = $speedtestProvider; } /** @@ -55,8 +60,8 @@ class SpeedtestJob implements ShouldQueue if ($this->config['healthchecks_enabled'] === true) { $this->healthcheck('start'); } - $output = SpeedtestHelper::output(); - $speedtest = SpeedtestHelper::runSpeedtest($output, $this->scheduled); + $output = $this->speedtestProvider->output(); + $speedtest = $this->speedtestProvider->run($output, $this->scheduled); if ($speedtest == false) { if ($this->config['healthchecks_enabled'] === true) { $this->healthcheck('fail'); diff --git a/app/Providers/SpeedtestServiceProvider.php b/app/Providers/SpeedtestServiceProvider.php new file mode 100644 index 00000000..83615bb3 --- /dev/null +++ b/app/Providers/SpeedtestServiceProvider.php @@ -0,0 +1,34 @@ +app->singleton(SpeedtestProvider::class, function () { + return new OoklaTester(); + }); + break; + } + } + } + } +} diff --git a/app/Utils/OoklaTester.php b/app/Utils/OoklaTester.php new file mode 100644 index 00000000..41d7ee73 --- /dev/null +++ b/app/Utils/OoklaTester.php @@ -0,0 +1,128 @@ +output(); + } + + try { + $output = json_decode($output, true, 512, JSON_THROW_ON_ERROR); + + if (!$this->isOutputIsComplete($output)) { + $test = false; + } + + $test = Speedtest::create([ + 'ping' => $output['ping']['latency'], + 'download' => SpeedtestHelper::convert($output['download']['bandwidth']), + 'upload' => SpeedtestHelper::convert($output['upload']['bandwidth']), + 'server_id' => $output['server']['id'], + 'server_name' => $output['server']['name'], + 'server_host' => $output['server']['host'] . ':' . $output['server']['port'], + 'url' => $output['result']['url'], + 'scheduled' => $scheduled + ]); + } catch (JsonException $e) { + Log::error('Failed to parse speedtest JSON'); + Log::error($output); + $test = false; + } catch (Exception $e) { + Log::error($e->getMessage()); + $test = false; + } + + if ($test == false) { + Speedtest::create([ + 'ping' => 0, + 'upload' => 0, + 'download' => 0, + 'failed' => true, + 'scheduled' => $scheduled, + ]); + + throw new SpeedtestFailureException($output); + } + + Cache::flush(); + + return $test; + } + + public function output() + { + $server = SettingsHelper::get('server')['value']; + + $binPath = app_path() . DIRECTORY_SEPARATOR . 'Bin' . DIRECTORY_SEPARATOR . 'speedtest'; + $homePrefix = config('speedtest.home') . ' && '; + + if ($server != '' && $server != false) { + $server = explode(',', $server); + $server = $server[array_rand($server)]; + if ($server == false) { + Log::error('Speedtest server undefined'); + return false; + } + + return shell_exec($homePrefix . $binPath . ' -f json -s ' . $server); + } + + return shell_exec($homePrefix . $binPath . ' -f json'); + } + + /** + * Checks that the speedtest JSON output is complete/valid + * + * @param array $output + * @return boolean + */ + private static function isOutputIsComplete($output) + { + /** + * Array of indexes that must exist in $output + */ + $checks = [ + 'type' => 'result', + 'download' => ['bandwidth' => '*'], + 'upload' => ['bandwidth' => '*'], + 'ping' => ['latency' => '*'], + 'server' => [ + 'id' => '*', + 'name' => '*', + 'host' => '*', + 'port' => '*' + ], + 'result' => [ + 'url' => '*' + ], + ]; + /** + * Array of indexes that must not exist + */ + $checkMissing = [ + 'type' => 'error' + ]; + + foreach ($checks as $key => $value) { + if (!isset($output[$key])) { + return false; + } + } + + return true; + } +} diff --git a/config/app.php b/config/app.php index 8c3685ce..b3abb874 100644 --- a/config/app.php +++ b/config/app.php @@ -182,6 +182,7 @@ return [ * Custom providers... */ App\Providers\IntegrationsServiceProvider::class, + App\Providers\SpeedtestServiceProvider::class, ], diff --git a/database/migrations/2021_03_07_101259_add_speedtest_provider_setting.php b/database/migrations/2021_03_07_101259_add_speedtest_provider_setting.php new file mode 100644 index 00000000..4510dc09 --- /dev/null +++ b/database/migrations/2021_03_07_101259_add_speedtest_provider_setting.php @@ -0,0 +1,38 @@ + 'speedtest_provider', + 'value' => 'ookla', + 'description' => 'The provider/package used to run speedtests.' + ]); + } + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Setting::whereIn('name', [ + 'speedtest_provider', + ])->delete(); + } +} From 75c5a4939802cfcd842bd0cae6db3c1848948545 Mon Sep 17 00:00:00 2001 From: Henry Whitaker Date: Sun, 7 Mar 2021 10:43:07 +0000 Subject: [PATCH 05/26] Moved more stuff into actions, and made one endpoint for homepage data --- app/Actions/GetFailedSpeedtestData.php | 48 +++++++++++++++++ app/Actions/GetLatestSpeedtestData.php | 52 +++++++++++++++++++ app/Actions/GetSpeedtestTimeData.php | 37 +++++++++++++ app/Helpers/SpeedtestHelper.php | 38 -------------- .../Controllers/HomepageDataController.php | 33 ++++++++++++ app/Http/Controllers/SpeedtestController.php | 3 +- app/Providers/RouteServiceProvider.php | 2 +- 7 files changed, 173 insertions(+), 40 deletions(-) create mode 100644 app/Actions/GetFailedSpeedtestData.php create mode 100644 app/Actions/GetLatestSpeedtestData.php create mode 100644 app/Actions/GetSpeedtestTimeData.php create mode 100644 app/Http/Controllers/HomepageDataController.php diff --git a/app/Actions/GetFailedSpeedtestData.php b/app/Actions/GetFailedSpeedtestData.php new file mode 100644 index 00000000..7ffd586a --- /dev/null +++ b/app/Actions/GetFailedSpeedtestData.php @@ -0,0 +1,48 @@ +addDays(1); + + return Cache::remember('failure-rate-' . $days, $ttl, function () use ($days) { + $range = [ + Carbon::today() + ]; + for ($i = 0; $i < ($days - 1); $i++) { + $prev = end($range); + $new = $prev->copy()->subDays(1); + array_push($range, $new); + } + + $rate = []; + + foreach ($range as $day) { + $success = Speedtest::select(DB::raw('COUNT(id) as rate'))->whereDate('created_at', $day)->where('failed', false)->get()[0]['rate']; + $fail = Speedtest::select(DB::raw('COUNT(id) as rate'))->whereDate('created_at', $day)->where('failed', true)->get()[0]['rate']; + + array_push($rate, [ + 'date' => $day->toDateString(), + 'success' => $success, + 'failure' => $fail, + ]); + } + + return array_reverse($rate); + }); + } +} diff --git a/app/Actions/GetLatestSpeedtestData.php b/app/Actions/GetLatestSpeedtestData.php new file mode 100644 index 00000000..ec6b8044 --- /dev/null +++ b/app/Actions/GetLatestSpeedtestData.php @@ -0,0 +1,52 @@ + $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; + } + + return $response; + } +} diff --git a/app/Actions/GetSpeedtestTimeData.php b/app/Actions/GetSpeedtestTimeData.php new file mode 100644 index 00000000..105baa00 --- /dev/null +++ b/app/Actions/GetSpeedtestTimeData.php @@ -0,0 +1,37 @@ +addDays(1); + + return Cache::remember('speedtest-days-' . $days, $ttl, function () use ($days) { + $showFailed = (bool)SettingsHelper::get('show_failed_tests_on_graph')->value; + + if ($showFailed === true) { + return Speedtest::where('created_at', '>=', Carbon::now()->subDays($days)) + ->orderBy('created_at', 'asc') + ->get(); + } + + return Speedtest::where('created_at', '>=', Carbon::now()->subDays($days)) + ->where('failed', false) + ->orderBy('created_at', 'asc') + ->get(); + }); + } +} diff --git a/app/Helpers/SpeedtestHelper.php b/app/Helpers/SpeedtestHelper.php index 09ee999d..b75fbd83 100644 --- a/app/Helpers/SpeedtestHelper.php +++ b/app/Helpers/SpeedtestHelper.php @@ -107,44 +107,6 @@ class SpeedtestHelper ]; } - /** - * Get a percentage rate of failure by days - * - * @param integer $days number of days to get rate for - * @return integer percentage fail rate - */ - public static function failureRate(int $days) - { - $ttl = Carbon::now()->addDays(1); - $rate = Cache::remember('failure-rate-' . $days, $ttl, function () use ($days) { - $range = [ - Carbon::today() - ]; - for ($i = 0; $i < ($days - 1); $i++) { - $prev = end($range); - $new = $prev->copy()->subDays(1); - array_push($range, $new); - } - - $rate = []; - - foreach ($range as $day) { - $success = Speedtest::select(DB::raw('COUNT(id) as rate'))->whereDate('created_at', $day)->where('failed', false)->get()[0]['rate']; - $fail = Speedtest::select(DB::raw('COUNT(id) as rate'))->whereDate('created_at', $day)->where('failed', true)->get()[0]['rate']; - - array_push($rate, [ - 'date' => $day->toDateString(), - 'success' => $success, - 'failure' => $fail, - ]); - } - - return array_reverse($rate); - }); - - return $rate; - } - /** * Create a backup of the SQLite database * diff --git a/app/Http/Controllers/HomepageDataController.php b/app/Http/Controllers/HomepageDataController.php new file mode 100644 index 00000000..fc69020a --- /dev/null +++ b/app/Http/Controllers/HomepageDataController.php @@ -0,0 +1,33 @@ + $days], + ['days' => ['required', 'numeric']], + ); + + if ($validator->fails()) { + return response()->json([ + 'method' => 'get speedtests in last x days', + 'error' => $validator->errors(), + ], 422); + } + + return [ + 'latest' => run(GetLatestSpeedtestData::class), + 'time' => run(GetSpeedtestTimeData::class), + 'fail' => run(GetFailedSpeedtestData::class), + ]; + } +} diff --git a/app/Http/Controllers/SpeedtestController.php b/app/Http/Controllers/SpeedtestController.php index 900616c7..f4204ff0 100644 --- a/app/Http/Controllers/SpeedtestController.php +++ b/app/Http/Controllers/SpeedtestController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Actions\GetFailedSpeedtestData; use App\Actions\GetLatestSpeedtestData; use App\Actions\GetSpeedtestTimeData; use App\Actions\QueueSpeedtest; @@ -94,7 +95,7 @@ class SpeedtestController extends Controller ], 422); } - $data = SpeedtestHelper::failureRate($days); + $data = run(GetFailedSpeedtestData::class, $days); return response()->json([ 'method' => 'get speedtests in last x days', diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 916cdf51..7133239d 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -15,7 +15,7 @@ class RouteServiceProvider extends ServiceProvider * * @var string */ - protected $namespace = 'App\Http\Controllers'; + protected $namespace = null; /** * The path to the "home" route for your application. From ce4913afa60c8ea5f57300bbd550bd9ef9c05aab Mon Sep 17 00:00:00 2001 From: Henry Whitaker Date: Sun, 7 Mar 2021 12:15:55 +0000 Subject: [PATCH 06/26] Grab all stats data in one go --- .../Controllers/HomepageDataController.php | 2 + public/js/app.js | 555 ++++++++++-------- .../js/components/Graphics/HistoryGraph.js | 397 ++++++------- .../js/components/Graphics/LatestResults.js | 33 +- resources/js/components/Home/HomePage.js | 56 +- routes/api.php | 105 ++-- 6 files changed, 619 insertions(+), 529 deletions(-) diff --git a/app/Http/Controllers/HomepageDataController.php b/app/Http/Controllers/HomepageDataController.php index fc69020a..256fe189 100644 --- a/app/Http/Controllers/HomepageDataController.php +++ b/app/Http/Controllers/HomepageDataController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers; use App\Actions\GetFailedSpeedtestData; use App\Actions\GetLatestSpeedtestData; use App\Actions\GetSpeedtestTimeData; +use App\Helpers\SettingsHelper; use Illuminate\Http\Request; use Validator; @@ -28,6 +29,7 @@ class HomepageDataController extends Controller 'latest' => run(GetLatestSpeedtestData::class), 'time' => run(GetSpeedtestTimeData::class), 'fail' => run(GetFailedSpeedtestData::class), + 'config' => SettingsHelper::getConfig(), ]; } } diff --git a/public/js/app.js b/public/js/app.js index c27d0f3c..4b930133 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -134704,239 +134704,23 @@ var HistoryGraph = /*#__PURE__*/function (_Component) { _this = _super.call(this, props); - _defineProperty(_assertThisInitialized(_this), "componentDidMount", function () { - _this.getData(); - - var _int = setInterval(_this.getData, 10000); - - _this.setState({ - interval: _int - }); - }); - - _defineProperty(_assertThisInitialized(_this), "getDLULPing", function (days) { - var url = 'api/speedtest/time/' + days; - axios__WEBPACK_IMPORTED_MODULE_2___default.a.get(url).then(function (resp) { - var duData = { - labels: [], - datasets: [{ - data: [], - label: 'Download', - borderColor: "#fca503", - fill: false - }, { - data: [], - label: 'Upload', - borderColor: "#3e95cd", - fill: false - }] - }; - var duOptions = { - maintainAspectRatio: false, - responsive: true, - tooltips: { - callbacks: { - label: function label(item) { - return "".concat(item.yLabel, " Mbit/s"); - } - } - }, - title: { - display: false, - text: 'Speedtests results for the last ' + days + ' days' - }, - scales: { - xAxes: [{ - display: false, - scaleLabel: { - display: true, - labelString: 'DateTime' - } - }] - }, - elements: { - point: { - radius: 0, - hitRadius: 8 - } - } - }; - var pingData = { - labels: [], - datasets: [{ - data: [], - label: 'Ping', - borderColor: "#07db71", - fill: false - }] - }; - var pingOptions = { - maintainAspectRatio: false, - responsive: true, - tooltips: { - callbacks: { - label: function label(item) { - return "".concat(item.yLabel, " ms"); - } - } - }, - title: { - display: false, - text: 'Ping results for the last ' + days + ' days' - }, - scales: { - xAxes: [{ - display: false, - scaleLabel: { - display: true, - labelString: 'DateTime' - } - }] - }, - elements: { - point: { - radius: 0, - hitRadius: 8 - } - } - }; - resp.data.data.forEach(function (e) { - var download = { - t: new Date(e.created_at), - y: e.download - }; - var upload = { - t: new Date(e.created_at), - y: e.upload - }; - var ping = { - t: new Date(e.created_at), - y: parseFloat(e.ping) - }; - duData.datasets[0].data.push(download); - duData.datasets[1].data.push(upload); - pingData.datasets[0].data.push(ping); - duData.labels.push(new Date(e.created_at).toLocaleString()); - pingData.labels.push(new Date(e.created_at).toLocaleString()); - }); - - _this.setState({ - duData: duData, - duOptions: duOptions, - pingData: pingData, - pingOptions: pingOptions, - loading: false - }); - })["catch"](function (err) { - console.log(err); - }); - }); - - _defineProperty(_assertThisInitialized(_this), "getFailure", function (days) { - var url = 'api/speedtest/fail/' + days; - axios__WEBPACK_IMPORTED_MODULE_2___default.a.get(url).then(function (resp) { - var failData = { - labels: [], - datasets: [{ - data: [], - label: 'Successful', - backgroundColor: '#07db71' - }, { - data: [], - label: 'Failed', - backgroundColor: '#E74C3C' - }] - }; - var failOptions = { - maintainAspectRatio: false, - responsive: true, - tooltips: { - callbacks: { - label: function label(item) { - return "".concat(item.yLabel, " speedtests"); - } - } - }, - scales: { - xAxes: [{ - stacked: true - }], - yAxes: [{ - stacked: true - }] - } - }; - resp.data.data.forEach(function (e) { - var success = { - x: e.date, - y: e.success - }; - var fail = { - x: e.date, - y: e.failure - }; - failData.datasets[0].data.push(success); - failData.datasets[1].data.push(fail); - failData.labels.push(new Date(e.date).toLocaleString([], { - year: '2-digit', - month: '2-digit', - day: '2-digit' - })); - }); - - _this.setState({ - failData: failData, - failOptions: failOptions - }); - })["catch"](function (err) { - console.log(err); - }); - }); - - _defineProperty(_assertThisInitialized(_this), "getData", function () { - var days = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : _this.state.days; - axios__WEBPACK_IMPORTED_MODULE_2___default.a.get('api/settings/config').then(function (resp) { - var data = resp.data.graphs; - - _this.setState({ - graph_ul_dl_enabled: Boolean(Number(data.download_upload_graph_enabled.value)), - graph_ul_dl_width: data.download_upload_graph_width.value, - graph_ping_enabled: Boolean(Number(data.ping_graph_enabled.value)), - graph_ping_width: data.ping_graph_width.value, - graph_failure_enabled: Boolean(Number(data.failure_graph_enabled.value)), - graph_failure_width: data.failure_graph_width.value - }); - - _this.getDLULPing(days); - - _this.getFailure(days); - })["catch"](function (err) { - console.log('Couldn\'t get the site config'); - console.log(err); - }); - }); + _defineProperty(_assertThisInitialized(_this), "componentDidMount", function () {}); _defineProperty(_assertThisInitialized(_this), "updateDays", function (e) { var days = e.target.value; if (days) { - _this.getData(days); - - clearInterval(_this.state["int"]); - - var _int2 = setInterval(_this.getData, 10000); - react_toastify__WEBPACK_IMPORTED_MODULE_5__["toast"].info('Showing results for the last ' + days + ' days'); - _this.setState({ - days: days, - interval: _int2 - }); + _this.props.updateDays(days); } }); _this.state = { - days: 7, + days: props.days, + time: props.dlUl, + fail: props.fail, + config: props.config, duData: {}, duOptions: {}, pingData: {}, @@ -134950,15 +134734,224 @@ var HistoryGraph = /*#__PURE__*/function (_Component) { graph_failure_enabled: true, graph_failure_width: 6, graph_ping_enabled: true, - graph_ping_width: 6 + graph_ping_width: 6, + firstUpdate: false }; return _this; } _createClass(HistoryGraph, [{ - key: "componentWillUnmount", - value: function componentWillUnmount() { - clearInterval(this.state.interval); + key: "componentDidUpdate", + value: function componentDidUpdate() { + if (this.state.time != this.props.dlUl || this.state.fail != this.props.fail || this.state.config != this.props.config || this.state.days != this.props.days) { + this.setState({ + time: this.props.dlUl, + fail: this.props.fail, + config: this.props.config, + days: this.props.days + }); + + if (this.state.config !== null) { + this.processData(); + } + } + + if (!this.state.firstUpdate && this.state.config !== null) { + this.processData(); + this.setState({ + firstUpdate: true + }); + } + } + }, { + key: "processData", + value: function processData() { + this.processConfig(); + this.processDlUlPing(); + this.processFailure(); + } + }, { + key: "processConfig", + value: function processConfig() { + this.setState({ + graph_ul_dl_enabled: Boolean(Number(this.state.config.graphs.download_upload_graph_enabled.value)), + graph_ul_dl_width: this.state.config.graphs.download_upload_graph_width.value, + graph_ping_enabled: Boolean(Number(this.state.config.graphs.ping_graph_enabled.value)), + graph_ping_width: this.state.config.graphs.ping_graph_width.value, + graph_failure_enabled: Boolean(Number(this.state.config.graphs.failure_graph_enabled.value)), + graph_failure_width: this.state.config.graphs.failure_graph_width.value + }); + } + }, { + key: "processDlUlPing", + value: function processDlUlPing() { + var days = this.state.days; + var duData = { + labels: [], + datasets: [{ + data: [], + label: 'Download', + borderColor: "#fca503", + fill: false + }, { + data: [], + label: 'Upload', + borderColor: "#3e95cd", + fill: false + }] + }; + var duOptions = { + maintainAspectRatio: false, + responsive: true, + tooltips: { + callbacks: { + label: function label(item) { + return "".concat(item.yLabel, " Mbit/s"); + } + } + }, + title: { + display: false, + text: 'Speedtests results for the last ' + days + ' days' + }, + scales: { + xAxes: [{ + display: false, + scaleLabel: { + display: true, + labelString: 'DateTime' + } + }] + }, + elements: { + point: { + radius: 0, + hitRadius: 8 + } + } + }; + var pingData = { + labels: [], + datasets: [{ + data: [], + label: 'Ping', + borderColor: "#07db71", + fill: false + }] + }; + var pingOptions = { + maintainAspectRatio: false, + responsive: true, + tooltips: { + callbacks: { + label: function label(item) { + return "".concat(item.yLabel, " ms"); + } + } + }, + title: { + display: false, + text: 'Ping results for the last ' + days + ' days' + }, + scales: { + xAxes: [{ + display: false, + scaleLabel: { + display: true, + labelString: 'DateTime' + } + }] + }, + elements: { + point: { + radius: 0, + hitRadius: 8 + } + } + }; + this.state.time.forEach(function (e) { + var download = { + t: new Date(e.created_at), + y: e.download + }; + var upload = { + t: new Date(e.created_at), + y: e.upload + }; + var ping = { + t: new Date(e.created_at), + y: parseFloat(e.ping) + }; + duData.datasets[0].data.push(download); + duData.datasets[1].data.push(upload); + pingData.datasets[0].data.push(ping); + duData.labels.push(new Date(e.created_at).toLocaleString()); + pingData.labels.push(new Date(e.created_at).toLocaleString()); + }); + this.setState({ + duData: duData, + duOptions: duOptions, + pingData: pingData, + pingOptions: pingOptions, + loading: false + }); + } + }, { + key: "processFailure", + value: function processFailure() { + var days = this.state.days; + var failData = { + labels: [], + datasets: [{ + data: [], + label: 'Successful', + backgroundColor: '#07db71' + }, { + data: [], + label: 'Failed', + backgroundColor: '#E74C3C' + }] + }; + var failOptions = { + maintainAspectRatio: false, + responsive: true, + tooltips: { + callbacks: { + label: function label(item) { + return "".concat(item.yLabel, " speedtests"); + } + } + }, + scales: { + xAxes: [{ + stacked: true + }], + yAxes: [{ + stacked: true + }] + } + }; + this.state.fail.forEach(function (e) { + var success = { + x: e.date, + y: e.success + }; + var fail = { + x: e.date, + y: e.failure + }; + failData.datasets[0].data.push(success); + failData.datasets[1].data.push(fail); + failData.labels.push(new Date(e.date).toLocaleString([], { + year: '2-digit', + month: '2-digit', + day: '2-digit' + })); + }); + this.setState({ + failData: failData, + failOptions: failOptions + }); } }, { key: "render", @@ -135187,32 +135180,6 @@ var LatestResults = /*#__PURE__*/function (_Component) { _this = _super.call(this, props); - _defineProperty(_assertThisInitialized(_this), "componentDidMount", function () { - _this.getData(); - - var _int = setInterval(_this.getData, 10000); - - _this.setState({ - interval: _int - }); - }); - - _defineProperty(_assertThisInitialized(_this), "getData", function () { - var url = 'api/speedtest/latest'; - axios__WEBPACK_IMPORTED_MODULE_2___default.a.get(url).then(function (resp) { - _this.setState({ - data: resp.data, - loading: false - }); - })["catch"](function (err) { - _this.setState({ - data: false - }); - - console.log(err); - }); - }); - _defineProperty(_assertThisInitialized(_this), "newScan", function () { var url = 'api/speedtest/run?token=' + window.token; axios__WEBPACK_IMPORTED_MODULE_2___default.a.get(url).then(function (resp) { @@ -135231,7 +135198,7 @@ var LatestResults = /*#__PURE__*/function (_Component) { }); _this.state = { - data: {}, + data: props.data, interval: null, loading: true }; @@ -135239,6 +135206,16 @@ var LatestResults = /*#__PURE__*/function (_Component) { } _createClass(LatestResults, [{ + key: "componentDidUpdate", + value: function componentDidUpdate() { + if (this.state.data !== this.props.data) { + this.setState({ + data: this.props.data, + loading: false + }); + } + } + }, { key: "componentWillUnmount", value: function componentWillUnmount() { clearInterval(this.state.interval); @@ -136022,6 +135999,8 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var _Login__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../Login */ "./resources/js/components/Login.js"); /* harmony import */ var _Authentication_Authentication__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../Authentication/Authentication */ "./resources/js/components/Authentication/Authentication.js"); /* harmony import */ var _Navbar__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../Navbar */ "./resources/js/components/Navbar.js"); +/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! axios */ "./node_modules/axios/index.js"); +/* harmony import */ var axios__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(axios__WEBPACK_IMPORTED_MODULE_10__); function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } @@ -136044,6 +136023,9 @@ function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Re function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + + @@ -136060,18 +136042,79 @@ var HomePage = /*#__PURE__*/function (_Component) { var _super = _createSuper(HomePage); - function HomePage() { + function HomePage(props) { + var _this; + _classCallCheck(this, HomePage); - return _super.apply(this, arguments); + _this = _super.call(this, props); + + _defineProperty(_assertThisInitialized(_this), "componentDidMount", function () { + _this.getData(); + + var interval = setInterval(_this.getData, 10000); + + _this.setState({ + interval: interval + }); + }); + + _defineProperty(_assertThisInitialized(_this), "updateDays", function (days) { + _this.setState({ + days: days + }); + + _this.getData(); + }); + + _defineProperty(_assertThisInitialized(_this), "getData", function () { + axios__WEBPACK_IMPORTED_MODULE_10___default.a.get('api/speedtest/home/' + _this.state.days).then(function (resp) { + _this.setState({ + latest: resp.data.latest, + time: resp.data.time, + fail: resp.data.fail, + config: resp.data.config + }); + })["catch"](function (err) { + console.log(err); + }); + }); + + _this.state = { + latest: null, + time: null, + fail: null, + config: null, + days: 7, + interval: null + }; + return _this; } _createClass(HomePage, [{ + key: "componentWillUnmount", + value: function componentWillUnmount() { + clearInterval(this.state.interval); + } + }, { key: "render", value: function render() { + var latest = this.state.latest; + var time = this.state.time; + var fail = this.state.fail; + var config = this.state.config; + var days = this.state.days; return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Navbar__WEBPACK_IMPORTED_MODULE_9__["default"], null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement("div", { className: "my-4" - }, window.config.auth == true && window.authenticated == false && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Login__WEBPACK_IMPORTED_MODULE_7__["default"], null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Graphics_LatestResults__WEBPACK_IMPORTED_MODULE_3__["default"], null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Graphics_HistoryGraph__WEBPACK_IMPORTED_MODULE_2__["default"], null)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Footer__WEBPACK_IMPORTED_MODULE_4__["default"], null)); + }, window.config.auth == true && window.authenticated == false && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Login__WEBPACK_IMPORTED_MODULE_7__["default"], null), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Graphics_LatestResults__WEBPACK_IMPORTED_MODULE_3__["default"], { + data: latest + }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Graphics_HistoryGraph__WEBPACK_IMPORTED_MODULE_2__["default"], { + updateDays: this.updateDays, + dlUl: time, + fail: fail, + config: config, + days: days + })), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement(_Footer__WEBPACK_IMPORTED_MODULE_4__["default"], null)); } }]); diff --git a/resources/js/components/Graphics/HistoryGraph.js b/resources/js/components/Graphics/HistoryGraph.js index 4eb4e49f..d1620a9b 100644 --- a/resources/js/components/Graphics/HistoryGraph.js +++ b/resources/js/components/Graphics/HistoryGraph.js @@ -11,7 +11,10 @@ export default class HistoryGraph extends Component { super(props) this.state = { - days: 7, + days: props.days, + time: props.dlUl, + fail: props.fail, + config: props.config, duData: {}, duOptions: {}, pingData: {}, @@ -26,233 +29,233 @@ export default class HistoryGraph extends Component { graph_failure_width: 6, graph_ping_enabled: true, graph_ping_width: 6, + firstUpdate: false, } } componentDidMount = () => { - this.getData(); - var int = setInterval(this.getData, 10000); + } + + componentDidUpdate() { + if( + this.state.time != this.props.dlUl || + this.state.fail != this.props.fail || + this.state.config != this.props.config || + this.state.days != this.props.days + ) { + this.setState({ + time: this.props.dlUl, + fail: this.props.fail, + config: this.props.config, + days: this.props.days + }); + + if(this.state.config !== null) { + this.processData(); + } + } + + if( + !this.state.firstUpdate && + this.state.config !== null + ) { + this.processData(); + this.setState({ + firstUpdate: true, + }); + } + } + + processData() { + this.processConfig(); + this.processDlUlPing(); + this.processFailure(); + } + + processConfig() { this.setState({ - interval: int, + graph_ul_dl_enabled: Boolean(Number(this.state.config.graphs.download_upload_graph_enabled.value)), + graph_ul_dl_width: this.state.config.graphs.download_upload_graph_width.value, + graph_ping_enabled: Boolean(Number(this.state.config.graphs.ping_graph_enabled.value)), + graph_ping_width: this.state.config.graphs.ping_graph_width.value, + graph_failure_enabled: Boolean(Number(this.state.config.graphs.failure_graph_enabled.value)), + graph_failure_width: this.state.config.graphs.failure_graph_width.value, }); } - componentWillUnmount() { - clearInterval(this.state.interval); - } + processDlUlPing() { + let days = this.state.days; - getDLULPing = (days) => { - var url = 'api/speedtest/time/' + days; - - Axios.get(url) - .then((resp) => { - var duData = { - labels: [], - datasets:[ - { - data: [], - label: 'Download', - borderColor: "#fca503", - fill: false, - }, - { - data: [], - label: 'Upload', - borderColor: "#3e95cd", - fill: false, - } - ], - }; - var duOptions = { - maintainAspectRatio: false, - responsive: true, - tooltips: { - callbacks: { - label: (item) => `${item.yLabel} Mbit/s`, - }, + var duData = { + labels: [], + datasets:[ + { + data: [], + label: 'Download', + borderColor: "#fca503", + fill: false, }, - title: { - display: false, - text: 'Speedtests results for the last ' + days + ' days', - }, - scales: { - xAxes: [{ - display: false, - scaleLabel: { - display: true, - labelString: 'DateTime' - } - }], - }, - elements: { - point:{ - radius: 0, - hitRadius: 8 - } + { + data: [], + label: 'Upload', + borderColor: "#3e95cd", + fill: false, } - }; - - var pingData = { - labels: [], - datasets:[ - { - data: [], - label: 'Ping', - borderColor: "#07db71", - fill: false, - }, - ], - }; - var pingOptions = { - maintainAspectRatio: false, - responsive: true, - tooltips: { - callbacks: { - label: (item) => `${item.yLabel} ms`, - }, + ], + }; + var duOptions = { + maintainAspectRatio: false, + responsive: true, + tooltips: { + callbacks: { + label: (item) => `${item.yLabel} Mbit/s`, }, - title: { + }, + title: { + display: false, + text: 'Speedtests results for the last ' + days + ' days', + }, + scales: { + xAxes: [{ display: false, - text: 'Ping results for the last ' + days + ' days', - }, - scales: { - xAxes: [{ - display: false, - scaleLabel: { - display: true, - labelString: 'DateTime' - } - }], - }, - elements: { - point:{ - radius: 0, - hitRadius: 8 + scaleLabel: { + display: true, + labelString: 'DateTime' } + }], + }, + elements: { + point:{ + radius: 0, + hitRadius: 8 } } + }; - resp.data.data.forEach(e => { - var download = { - t: new Date(e.created_at), - y: e.download, - }; - var upload = { - t: new Date(e.created_at), - y: e.upload, - }; - var ping = { - t: new Date(e.created_at), - y: parseFloat(e.ping) - } - duData.datasets[0].data.push(download); - duData.datasets[1].data.push(upload); - pingData.datasets[0].data.push(ping); - duData.labels.push(new Date(e.created_at).toLocaleString()); - pingData.labels.push(new Date(e.created_at).toLocaleString()); - }); - - this.setState({ - duData: duData, - duOptions: duOptions, - pingData: pingData, - pingOptions: pingOptions, - loading: false, - }); - }) - .catch((err) => { - console.log(err); - }) - } - - getFailure = (days) => { - var url = 'api/speedtest/fail/' + days; - Axios.get(url) - .then((resp) => { - var failData = { - labels: [], - datasets: [ - { - data: [], - label: 'Successful', - backgroundColor: '#07db71' - }, - { - data: [], - label: 'Failed', - backgroundColor: '#E74C3C' - }, - ], - }; - var failOptions = { - maintainAspectRatio: false, - responsive: true, - tooltips: { - callbacks: { - label: (item) => `${item.yLabel} speedtests`, - }, + var pingData = { + labels: [], + datasets:[ + { + data: [], + label: 'Ping', + borderColor: "#07db71", + fill: false, }, - scales: { - xAxes: [{ - stacked: true - }], - yAxes: [{ - stacked: true - }] + ], + }; + var pingOptions = { + maintainAspectRatio: false, + responsive: true, + tooltips: { + callbacks: { + label: (item) => `${item.yLabel} ms`, + }, + }, + title: { + display: false, + text: 'Ping results for the last ' + days + ' days', + }, + scales: { + xAxes: [{ + display: false, + scaleLabel: { + display: true, + labelString: 'DateTime' + } + }], + }, + elements: { + point:{ + radius: 0, + hitRadius: 8 } + } + } + + this.state.time.forEach(e => { + var download = { + t: new Date(e.created_at), + y: e.download, }; + var upload = { + t: new Date(e.created_at), + y: e.upload, + }; + var ping = { + t: new Date(e.created_at), + y: parseFloat(e.ping) + } + duData.datasets[0].data.push(download); + duData.datasets[1].data.push(upload); + pingData.datasets[0].data.push(ping); + duData.labels.push(new Date(e.created_at).toLocaleString()); + pingData.labels.push(new Date(e.created_at).toLocaleString()); + }); - resp.data.data.forEach(e => { - var success = {x: e.date, y: e.success}; - var fail = {x: e.date, y: e.failure}; - failData.datasets[0].data.push(success); - failData.datasets[1].data.push(fail); - failData.labels.push(new Date(e.date).toLocaleString([], {year: '2-digit', month:'2-digit', day:'2-digit'})); - }) - - this.setState({ - failData: failData, - failOptions: failOptions - }); - }) - .catch((err) => { - console.log(err); - }) + this.setState({ + duData: duData, + duOptions: duOptions, + pingData: pingData, + pingOptions: pingOptions, + loading: false, + }); } - getData = (days = this.state.days) => { - Axios.get('api/settings/config') - .then((resp) => { - var data = resp.data.graphs; - this.setState({ - graph_ul_dl_enabled: Boolean(Number(data.download_upload_graph_enabled.value)), - graph_ul_dl_width: data.download_upload_graph_width.value, - graph_ping_enabled: Boolean(Number(data.ping_graph_enabled.value)), - graph_ping_width: data.ping_graph_width.value, - graph_failure_enabled: Boolean(Number(data.failure_graph_enabled.value)), - graph_failure_width: data.failure_graph_width.value, - }); + processFailure() { + let days = this.state.days; - this.getDLULPing(days); - this.getFailure(days); - }) - .catch((err) => { - console.log('Couldn\'t get the site config'); - console.log(err); + var failData = { + labels: [], + datasets: [ + { + data: [], + label: 'Successful', + backgroundColor: '#07db71' + }, + { + data: [], + label: 'Failed', + backgroundColor: '#E74C3C' + }, + ], + }; + var failOptions = { + maintainAspectRatio: false, + responsive: true, + tooltips: { + callbacks: { + label: (item) => `${item.yLabel} speedtests`, + }, + }, + scales: { + xAxes: [{ + stacked: true + }], + yAxes: [{ + stacked: true + }] + } + }; + + this.state.fail.forEach(e => { + var success = {x: e.date, y: e.success}; + var fail = {x: e.date, y: e.failure}; + failData.datasets[0].data.push(success); + failData.datasets[1].data.push(fail); + failData.labels.push(new Date(e.date).toLocaleString([], {year: '2-digit', month:'2-digit', day:'2-digit'})); }) + + this.setState({ + failData: failData, + failOptions: failOptions + }); } updateDays = (e) => { var days = e.target.value; if(days) { - this.getData(days); - clearInterval(this.state.int); - var int = setInterval(this.getData, 10000); toast.info('Showing results for the last ' + days + ' days'); - this.setState({ - days: days, - interval: int - }); + this.props.updateDays(days); } } diff --git a/resources/js/components/Graphics/LatestResults.js b/resources/js/components/Graphics/LatestResults.js index dd1bd5dc..c2a4fe01 100644 --- a/resources/js/components/Graphics/LatestResults.js +++ b/resources/js/components/Graphics/LatestResults.js @@ -12,42 +12,25 @@ export default class LatestResults extends Component { super(props) this.state = { - data: {}, + data: props.data, interval: null, loading: true, } } - componentDidMount = () => { - this.getData(); - var int = setInterval(this.getData, 10000); - this.setState({ - interval: int, - }); + componentDidUpdate() { + if(this.state.data !== this.props.data) { + this.setState({ + data: this.props.data, + loading: false, + }); + } } componentWillUnmount() { clearInterval(this.state.interval); } - getData = () => { - var url = 'api/speedtest/latest'; - - Axios.get(url) - .then((resp) => { - this.setState({ - data: resp.data, - loading: false - }); - }) - .catch((err) => { - this.setState({ - data: false - }); - console.log(err); - }) - } - newScan = () => { var url = 'api/speedtest/run?token=' + window.token; diff --git a/resources/js/components/Home/HomePage.js b/resources/js/components/Home/HomePage.js index 9c1a20b2..58544c71 100644 --- a/resources/js/components/Home/HomePage.js +++ b/resources/js/components/Home/HomePage.js @@ -8,10 +8,62 @@ import TestsTable from '../Graphics/TestsTable'; import Login from '../Login'; import Authentication from '../Authentication/Authentication'; import Navbar from '../Navbar'; +import axios from 'axios'; export default class HomePage extends Component { + constructor(props) { + super(props) + + this.state = { + latest: null, + time: null, + fail: null, + config: null, + days: 7, + interval: null, + } + } + + componentDidMount = () => { + this.getData(); + var interval = setInterval(this.getData, 10000); + this.setState({ + interval: interval, + }); + } + + componentWillUnmount() { + clearInterval(this.state.interval); + } + + updateDays = (days) => { + this.setState({ days: days }); + this.getData(); + } + + + getData = () => { + axios.get('api/speedtest/home/' + this.state.days) + .then((resp) => { + this.setState({ + latest: resp.data.latest, + time: resp.data.time, + fail: resp.data.fail, + config: resp.data.config + }); + }) + .catch((err) => { + console.log(err); + }) + } render() { + let latest = this.state.latest; + let time = this.state.time; + let fail = this.state.fail; + let config = this.state.config; + let days = this.state.days; + return (
@@ -19,8 +71,8 @@ export default class HomePage extends Component { {(window.config.auth == true && window.authenticated == false) && } - - + +