mirror of
https://github.com/henrywhitaker3/Speedtest-Tracker.git
synced 2025-12-24 14:31:52 +01:00
Updated site to v1.5.5
This commit is contained in:
2
conf/site/.gitignore
vendored
2
conf/site/.gitignore
vendored
@@ -1,6 +1,8 @@
|
||||
/node_modules
|
||||
/public/hot
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
/vendor
|
||||
.env
|
||||
.env.backup
|
||||
.phpunit.result.cache
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
[](https://hub.docker.com/r/henrywhitaker3/speedtest-tracker) [](https://github.com/henrywhitaker3/Speedtest-Tracker/commits) [](https://github.com/henrywhitaker3/Speedtest-Tracker/issues)  [](https://github.com/henrywhitaker3/Speedtest-Tracker/blob/master/LICENSE)
|
||||
|
||||
This program runs a speedtest check every hour and graphs the results. The back-end is written in [Laravel](https://laravel.com/) and the front-end uses [React](https://reactjs.org/). It uses the [speedtest-cli](https://github.com/sivel/speedtest-cli) package to get the data and uses [Chart.js](https://www.chartjs.org/) to plot the results.
|
||||
This program runs a speedtest check every hour and graphs the results. The back-end is written in [Laravel](https://laravel.com/) and the front-end uses [React](https://reactjs.org/). It uses the [speedtest-cli](https://www.speedtest.net/apps/cli) package to get the data and uses [Chart.js](https://www.chartjs.org/) to plot the results.
|
||||
|
||||

|
||||
|
||||
|
||||
2
conf/site/app/Bin/.gitignore
vendored
2
conf/site/app/Bin/.gitignore
vendored
@@ -1 +1 @@
|
||||
SpeedTest
|
||||
speedtest
|
||||
|
||||
@@ -32,9 +32,9 @@ class SpeedtestCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
* Runs a speedtest synchroonously and displays the results..
|
||||
*
|
||||
* @return mixed
|
||||
* @return null
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
@@ -33,9 +33,9 @@ class SpeedtestLatestCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
* Prints the latest speedtest values.
|
||||
*
|
||||
* @return mixed
|
||||
* @return null
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
@@ -9,7 +9,14 @@ use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class BackupHelper {
|
||||
public static function backup($format = 'json')
|
||||
|
||||
/**
|
||||
* Generates a backup of all speedtests.
|
||||
*
|
||||
* @param string $format json|csv
|
||||
* @return string $name Returns the filename of the backup.
|
||||
*/
|
||||
public static function backup(String $format = 'json')
|
||||
{
|
||||
$timestamp = new DateTime();
|
||||
$timestamp = $timestamp->format('Y-m-d_H:i:s');
|
||||
@@ -43,6 +50,13 @@ class BackupHelper {
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore data from a backup in CSV or JSON format
|
||||
*
|
||||
* @param array|string $array Backup data
|
||||
* @param string $format json|csv
|
||||
* @return boolean
|
||||
*/
|
||||
public static function restore($array, $format)
|
||||
{
|
||||
if($format == 'json') {
|
||||
|
||||
@@ -5,6 +5,13 @@ namespace App\Helpers;
|
||||
use App\Setting;
|
||||
|
||||
class SettingsHelper {
|
||||
|
||||
/**
|
||||
* Get a Setting object by name
|
||||
*
|
||||
* @param String $name The name field in the setting table
|
||||
* @return \App\Setting|boolean $name The Setting object. Returns false if no mathcing obj.
|
||||
*/
|
||||
public static function get(String $name)
|
||||
{
|
||||
$name = Setting::where('name', $name)->get();
|
||||
@@ -19,6 +26,13 @@ class SettingsHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create / update value for Setting object.
|
||||
*
|
||||
* @param String $name Name of setting
|
||||
* @param String $value Value of setting
|
||||
* @return \App\Setting
|
||||
*/
|
||||
public static function set(String $name, String $value)
|
||||
{
|
||||
$setting = SettingsHelper::get($name);
|
||||
@@ -36,6 +50,11 @@ class SettingsHelper {
|
||||
return $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the app's base path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getBase()
|
||||
{
|
||||
$base = env('BASE_PATH', '/');
|
||||
|
||||
@@ -13,6 +13,13 @@ use JsonException;
|
||||
use SimpleXMLElement;
|
||||
|
||||
class SpeedtestHelper {
|
||||
|
||||
/**
|
||||
* Runs/processes speedtest output to created a Speedtest object
|
||||
*
|
||||
* @param boolean|string $output If false, new speedtest runs. If anything else, will try to parse as JSON for speedtest results.
|
||||
* @return \App\Speedtest|boolean
|
||||
*/
|
||||
public static function runSpeedtest($output = false)
|
||||
{
|
||||
if($output === false) {
|
||||
@@ -25,6 +32,10 @@ class SpeedtestHelper {
|
||||
'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'],
|
||||
]);
|
||||
} catch(JsonException $e) {
|
||||
Log::error('Failed to parse speedtest JSON');
|
||||
@@ -36,6 +47,11 @@ class SpeedtestHelper {
|
||||
return (isset($test)) ? $test : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the output of executing speedtest binary.
|
||||
*
|
||||
* @return boolean|string
|
||||
*/
|
||||
public static function output()
|
||||
{
|
||||
$server = SettingsHelper::get('server')['value'];
|
||||
@@ -54,10 +70,21 @@ class SpeedtestHelper {
|
||||
return shell_exec('HOME=/config && ' . $binPath . ' -f json');
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts bytes/s to Mbps
|
||||
*
|
||||
* @param int|float $bytes
|
||||
* @return int|float
|
||||
*/
|
||||
public static function convert($bytes) {
|
||||
return ( $bytes * 8 ) / 1000000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the latest speedtest object.
|
||||
*
|
||||
* @return boolean|\App\Speedtest
|
||||
*/
|
||||
public static function latest()
|
||||
{
|
||||
$data = Speedtest::latest()->get();
|
||||
@@ -69,6 +96,12 @@ class SpeedtestHelper {
|
||||
return $data->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses network speeds and return converted to Mbps
|
||||
*
|
||||
* @param array $input
|
||||
* @return array
|
||||
*/
|
||||
public static function parseUnits($input)
|
||||
{
|
||||
$input = explode(' ', $input);
|
||||
|
||||
@@ -10,10 +10,39 @@ use RecursiveIteratorIterator;
|
||||
use ZipArchive;
|
||||
|
||||
class UpdateHelper {
|
||||
/**
|
||||
* URL of updates
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $url;
|
||||
|
||||
/**
|
||||
* Current app version number
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $currentVersion;
|
||||
|
||||
/**
|
||||
* Username of GitHub repo
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Name of GitHub repo
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $repo;
|
||||
|
||||
/**
|
||||
* Branch of GitHub repo
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $branch;
|
||||
|
||||
function __construct() {
|
||||
@@ -25,6 +54,11 @@ class UpdateHelper {
|
||||
$this->download = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns data on new version available
|
||||
*
|
||||
* @return boolean|array false|[ version, changelog ]
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
Log::info('Checking for new version');
|
||||
@@ -50,6 +84,11 @@ class UpdateHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the latest version number from GitHub
|
||||
*
|
||||
* @return array [ repo, branch, version ]
|
||||
*/
|
||||
public function checkLatestVersion()
|
||||
{
|
||||
$url = 'https://raw.githubusercontent.com/'
|
||||
@@ -78,6 +117,11 @@ class UpdateHelper {
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the latest changelog from GitHub
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getChangelog()
|
||||
{
|
||||
$url = 'https://raw.githubusercontent.com/'
|
||||
@@ -97,6 +141,11 @@ class UpdateHelper {
|
||||
return $changelog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the latest version from GitHub
|
||||
*
|
||||
* @return boolean|Exception
|
||||
*/
|
||||
public function downloadLatest()
|
||||
{
|
||||
Log::info('Downloading the latest version from GitHub');
|
||||
@@ -121,6 +170,11 @@ class UpdateHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts zip archive from update
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function extractFiles()
|
||||
{
|
||||
Log::info('Extracting the update');
|
||||
@@ -137,6 +191,11 @@ class UpdateHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace existing files with newly downloaded files
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function updateFiles()
|
||||
{
|
||||
Log::info('Applying update');
|
||||
@@ -151,6 +210,14 @@ class UpdateHelper {
|
||||
Log::info('Successfully applied update');
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes default templates from updated files.
|
||||
* This is for things like .env so that user specified files are not
|
||||
* overwritten.
|
||||
*
|
||||
* @param string $path
|
||||
* @return void
|
||||
*/
|
||||
private function deleteExcluded($path)
|
||||
{
|
||||
Log::info('Deleting excluded items from update directory');
|
||||
@@ -172,6 +239,11 @@ class UpdateHelper {
|
||||
Log::info('Excluded items deleted from update directory');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a ZIP backup of current installation
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function backupCurrent()
|
||||
{
|
||||
Log::info('Backing up current installation');
|
||||
@@ -209,6 +281,11 @@ class UpdateHelper {
|
||||
Log::info('Backup created at: ' . $backupZip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move updated files into server dir.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function moveFiles()
|
||||
{
|
||||
$new = array_filter(glob('/tmp/'.$this->repo.'-update/*'), 'is_dir');
|
||||
@@ -242,6 +319,11 @@ class UpdateHelper {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a copy of excluded, user customised files
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function tempStoreExcludedFiles()
|
||||
{
|
||||
Log::info('Temporarily moving exluded files from root directory');
|
||||
@@ -263,6 +345,11 @@ class UpdateHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore user cusotmised files from the copy
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function restoreExcludedFiles()
|
||||
{
|
||||
Log::info('Restoring exluded files to root directory');
|
||||
@@ -284,6 +371,11 @@ class UpdateHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete update files from download dir.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function clearup()
|
||||
{
|
||||
try {
|
||||
|
||||
@@ -10,6 +10,13 @@ use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class BackupController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Get backup of speedtests
|
||||
*
|
||||
* @param Request $request
|
||||
* @return file
|
||||
*/
|
||||
public function backup(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [ 'format' => 'in:json,csv' ]);
|
||||
@@ -25,6 +32,12 @@ class BackupController extends Controller
|
||||
return Storage::disk('local')->download($filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retore from a backup
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function restore(Request $request)
|
||||
{
|
||||
$rule = [
|
||||
|
||||
@@ -10,16 +10,34 @@ use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class SettingsController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Return all settings
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return Setting::get()->keyBy('name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get setting by id
|
||||
*
|
||||
* @param Setting $setting
|
||||
* @return Setting
|
||||
*/
|
||||
public function get(Setting $setting)
|
||||
{
|
||||
return $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store/update a setting
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$rule = [
|
||||
@@ -49,6 +67,11 @@ class SettingsController extends Controller
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns instance config
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function config()
|
||||
{
|
||||
|
||||
|
||||
@@ -13,6 +13,12 @@ use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class SpeedtestController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns paginated list of speedtests
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$data = Speedtest::orderBy('created_at', 'desc')
|
||||
@@ -24,6 +30,12 @@ class SpeedtestController extends Controller
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns speedtest going back 'x' days
|
||||
*
|
||||
* @param int $days
|
||||
* @return void
|
||||
*/
|
||||
public function time($days)
|
||||
{
|
||||
$rule = [
|
||||
@@ -50,6 +62,11 @@ class SpeedtestController extends Controller
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return latest speedtest
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function latest()
|
||||
{
|
||||
$data = SpeedtestHelper::latest();
|
||||
@@ -73,6 +90,11 @@ class SpeedtestController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue a new speedtest
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
try {
|
||||
|
||||
@@ -8,6 +8,12 @@ use Illuminate\Http\Request;
|
||||
|
||||
class UpdateController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Check for new update
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function checkForUpdate()
|
||||
{
|
||||
return response()->json([
|
||||
@@ -16,6 +22,11 @@ class UpdateController extends Controller
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download new update
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function downloadUpdate()
|
||||
{
|
||||
$dl = Updater::downloadLatest();
|
||||
@@ -33,6 +44,11 @@ class UpdateController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger update extraction
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function extractUpdate()
|
||||
{
|
||||
$ex = Updater::extractFiles();
|
||||
@@ -50,6 +66,11 @@ class UpdateController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger update file move
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function moveUpdate()
|
||||
{
|
||||
$cp = Updater::updateFiles();
|
||||
@@ -60,6 +81,11 @@ class UpdateController extends Controller
|
||||
], 200);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get local changelog
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function changelog()
|
||||
{
|
||||
$url = base_path() . '/changelog.json';
|
||||
|
||||
@@ -25,9 +25,9 @@ class SpeedtestJob implements ShouldQueue
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
* Runs a speedtest
|
||||
*
|
||||
* @return void
|
||||
* @return \App\Speedtest
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ class SpeedtestCompleteListener
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
* Handle what to do after speedtest completes
|
||||
*
|
||||
* @param object $event
|
||||
* @return void
|
||||
|
||||
@@ -34,6 +34,12 @@ class SpeedtestComplete extends Notification
|
||||
return ['slack'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Format slack notification
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return SlackMessage
|
||||
*/
|
||||
public function toSlack($notifiable)
|
||||
{
|
||||
$speedtest = $this->speedtest;
|
||||
|
||||
@@ -18,7 +18,7 @@ class Cron implements Rule
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the validation rule passes.
|
||||
* Determine if the value is a valid CRON expression
|
||||
*
|
||||
* @param string $attribute
|
||||
* @param mixed $value
|
||||
|
||||
@@ -12,7 +12,14 @@ class Speedtest extends Model
|
||||
* @var array
|
||||
*/
|
||||
protected $fillable = [
|
||||
'ping', 'download', 'upload', 'created_at'
|
||||
'ping',
|
||||
'download',
|
||||
'upload',
|
||||
'created_at',
|
||||
'server_id',
|
||||
'server_name',
|
||||
'server_host',
|
||||
'url',
|
||||
];
|
||||
|
||||
protected $table = 'speedtests';
|
||||
|
||||
@@ -75,6 +75,11 @@ class User extends Authenticatable implements JWTSubject
|
||||
return $this->hasOne('\App\Auth\EmailVerification');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a user's login sessions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function sessions()
|
||||
{
|
||||
return $this->hasMany('\App\Auth\LoginSession');
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
{
|
||||
"1.5.5": [
|
||||
{
|
||||
"description": "Store host/id of speedtes.net server",
|
||||
"link": ""
|
||||
}
|
||||
],
|
||||
"1.5.4": [
|
||||
{
|
||||
"description": "Updated dependencies",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.2.5",
|
||||
"doctrine/dbal": "^2.10",
|
||||
"dragonmantank/cron-expression": "^2",
|
||||
"fideloper/proxy": "^4.2",
|
||||
"fruitcake/laravel-cors": "^2.0",
|
||||
|
||||
855
conf/site/composer.lock
generated
855
conf/site/composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ return [
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
'version' => '1.5.4',
|
||||
'version' => '1.5.5',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class UpdateSpeedtestsTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('speedtests', function($table) {
|
||||
$table->integer('server_id')->nullable();
|
||||
$table->string('server_name')->nullable();
|
||||
$table->string('server_host')->nullable();
|
||||
$table->string('url')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('speedtests', function($table) {
|
||||
$table->dropColumn('server_id');
|
||||
});
|
||||
|
||||
Schema::table('speedtests', function($table) {
|
||||
$table->dropColumn('server_name');
|
||||
});
|
||||
|
||||
Schema::table('speedtests', function($table) {
|
||||
$table->dropColumn('server_host');
|
||||
});
|
||||
|
||||
Schema::table('speedtests', function($table) {
|
||||
$table->dropColumn('url');
|
||||
});
|
||||
}
|
||||
}
|
||||
Binary file not shown.
2
conf/site/public/js/app.js
vendored
2
conf/site/public/js/app.js
vendored
File diff suppressed because one or more lines are too long
65
conf/site/resources/js/components/Graphics/TableRow.js
vendored
Normal file
65
conf/site/resources/js/components/Graphics/TableRow.js
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
import React, { Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Modal } from 'react-bootstrap';
|
||||
|
||||
export default class TableRow extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
data: this.props.data,
|
||||
show: false,
|
||||
}
|
||||
}
|
||||
|
||||
toggleShow = () => {
|
||||
var show = this.state.show;
|
||||
if(show) {
|
||||
this.setState({
|
||||
show: false
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
show: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
var e = this.state.data;
|
||||
var show = this.state.show;
|
||||
console.log(e.server_host == null);
|
||||
|
||||
return (
|
||||
<tr>
|
||||
<td>{e.id}</td>
|
||||
<td>{new Date(e.created_at).toLocaleString()}</td>
|
||||
<td>{e.download}</td>
|
||||
<td>{e.upload}</td>
|
||||
<td>{e.ping}</td>
|
||||
{e.server_host != null ?
|
||||
<td>
|
||||
<span onClick={this.toggleShow} className="ti-arrow-top-right mouse"></span>
|
||||
<Modal show={show} onHide={this.toggleShow}>
|
||||
<Modal.Header>
|
||||
<Modal.Title>More info</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body className="text-center">
|
||||
<p>Server ID: {e.server_id}</p>
|
||||
<p>Name: {e.server_name}</p>
|
||||
<p>Host: {e.server_host}</p>
|
||||
<a href={e.url} target="_blank" rel="noopener noreferer">Speedtest.net</a>
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</td>
|
||||
:
|
||||
<td></td>
|
||||
}
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (document.getElementById('tableRow')) {
|
||||
ReactDOM.render(<TableRow />, document.getElementById('tableRow'));
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import React, { Component } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import Axios from 'axios';
|
||||
import { Container, Row, Table, Col, Collapse, Button } from 'react-bootstrap';
|
||||
import TableRow from './TableRow';
|
||||
|
||||
export default class TestsTable extends Component {
|
||||
constructor(props) {
|
||||
@@ -93,18 +94,13 @@ export default class TestsTable extends Component {
|
||||
<th>Download (Mbit/s)</th>
|
||||
<th>Upload (Mbit/s)</th>
|
||||
<th>Ping (ms)</th>
|
||||
<th>More</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.map((e,i) => {
|
||||
return (
|
||||
<tr key={e.id}>
|
||||
<td>{e.id}</td>
|
||||
<td>{new Date(e.created_at).toLocaleString()}</td>
|
||||
<td>{e.download}</td>
|
||||
<td>{e.upload}</td>
|
||||
<td>{e.ping}</td>
|
||||
</tr>
|
||||
<TableRow key={e.id} data={e} />
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
|
||||
Reference in New Issue
Block a user