Order/location of columns is now variable

This commit is contained in:
Henry Whitaker
2021-04-10 11:22:37 +01:00
parent 0b593e60b4
commit 305e4bb17f
6 changed files with 209 additions and 19 deletions

View File

@@ -0,0 +1,51 @@
<?php
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class CommaSeparatedArrayCast implements CastsAttributes
{
/**
* Array of settings that should be cast
*/
private array $shouldCast = [
'visible_columns',
];
/**
* Cast the given value.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return mixed
*/
public function get($model, $key, $value, $attributes)
{
if (!in_array($model->name, $this->shouldCast)) {
return $value;
}
return explode(',', $value);
}
/**
* Prepare the given value for storage.
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return mixed
*/
public function set($model, $key, $value, $attributes)
{
if (!in_array($model->name, $this->shouldCast)) {
return $value;
}
return implode(',', $value);
}
}

View File

@@ -168,6 +168,9 @@ class SettingsHelper
'telegram_bot_token' => SettingsHelper::settingIsEditable('telegram_bot_token'), 'telegram_bot_token' => SettingsHelper::settingIsEditable('telegram_bot_token'),
'telegram_chat_id' => SettingsHelper::settingIsEditable('telegram_chat_id'), 'telegram_chat_id' => SettingsHelper::settingIsEditable('telegram_chat_id'),
], ],
'tables' => [
'visible_columns' => SettingsHelper::get('visible_columns')->value,
],
'auth' => (bool)SettingsHelper::get('auth')->value 'auth' => (bool)SettingsHelper::get('auth')->value
]; ];
} }

View File

@@ -2,6 +2,7 @@
namespace App; namespace App;
use App\Casts\CommaSeparatedArrayCast;
use App\Helpers\SettingsHelper; use App\Helpers\SettingsHelper;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
@@ -17,4 +18,8 @@ class Setting extends Model
]; ];
protected $table = 'settings'; protected $table = 'settings';
protected $casts = [
'value' => CommaSeparatedArrayCast::class,
];
} }

View File

@@ -0,0 +1,38 @@
<?php
use App\Helpers\SettingsHelper;
use App\Setting;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddVisibleColumnsSetting extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (!SettingsHelper::get('visible_columns')) {
Setting::create([
'name' => 'visible_columns',
'value' => 'id,created_at,download,upload,ping',
'description' => 'Columns visible in the "All Tests" table.'
]);
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Setting::whereIn('name', [
'visible_columns',
])->delete();
}
}

View File

@@ -47,18 +47,62 @@ export default class TableRow extends Component {
this.toggleShow(); this.toggleShow();
} }
getDataFields = () => {
let allFields = this.props.allFields;
let data = this.state.data;
let processedFields = [];
for(var key in allFields) {
let field = allFields[key];
let value = data[key];
if(field.type === 'date') {
value = new Date(value).toLocaleString();
} else if(field.type === 'bool') {
value = Boolean(value) ? field.if_true : field.if_false
}
let final = {
name: key,
key: field.alias,
value: value,
type: field.type
};
processedFields.push(final);
}
let visible = [];
let inModal = [];
window.config.tables.visible_columns.forEach(column => {
visible.push(processedFields.find(x => x.name == column));
});
inModal = processedFields.filter(el => {
return !visible.includes(el);
});
return {
visible: visible,
modal: inModal
};
}
render() { render() {
var e = this.state.data; var e = this.state.data;
var show = this.state.show; var show = this.state.show;
var fields = this.getDataFields();
if(e.failed != true) { if(e.failed != true) {
return ( return (
<tr> <tr>
<td>{e.id}</td> {fields.visible.map((e, i) => {
<td>{new Date(e.created_at).toLocaleString()}</td> return (
<td>{e.download}</td> <td key={i}>{e.value}</td>
<td>{e.upload}</td> );
<td>{e.ping}</td> })}
{e.server_host != null ? {e.server_host != null ?
<td> <td>
<span onClick={this.toggleShow} className="ti-arrow-top-right mouse"></span> <span onClick={this.toggleShow} className="ti-arrow-top-right mouse"></span>
@@ -67,13 +111,17 @@ export default class TableRow extends Component {
<Modal.Title>More info</Modal.Title> <Modal.Title>More info</Modal.Title>
</Modal.Header> </Modal.Header>
<Modal.Body className="text-center"> <Modal.Body className="text-center">
<p>Server ID: {e.server_id}</p> {fields.modal.map((e, i) => {
<p>Name: {e.server_name}</p> if(e.type === 'url') {
<p>Host: {e.server_host}</p> return (
<p>URL: <a href={e.url} target="_blank" rel="noopener noreferer">Speedtest.net</a></p> <p key={i}>{e.key}: <a href={e.value} target="_blank" rel="noopener noreferer">Speedtest.net</a></p>
{e.scheduled != undefined && );
<p>Type: {e.scheduled == true ? 'scheduled' : 'manual'}</p> } else {
return (
<p key={i}>{e.key}: {e.value}</p>
);
} }
})}
<Button variant="danger" onClick={() => { this.delete(e.id) }}>Delete</Button> <Button variant="danger" onClick={() => { this.delete(e.id) }}>Delete</Button>
</Modal.Body> </Modal.Body>
</Modal> </Modal>

View File

@@ -14,7 +14,51 @@ export default class TestsTable extends Component {
data: [], data: [],
showTable: false, showTable: false,
refresh: true, refresh: true,
interval: null interval: null,
allFields: {
id: {
type: 'int',
alias: 'ID'
},
created_at: {
type: 'date',
alias: 'Time'
},
download: {
type: 'float',
alias: 'Download (Mbit/s)'
},
upload: {
type: 'float',
alias: 'Upload (Mbit/s)'
},
ping: {
type: 'float',
alias: 'Ping (ms)'
},
server_id: {
type: 'int',
alias: 'Server ID'
},
server_name: {
type: 'string',
alias: 'Name'
},
server_host: {
type: 'string',
alias: 'Host'
},
url: {
type: 'url',
alias: 'URL'
},
scheduled: {
type: 'bool',
alias: 'Type',
if_true: 'scheduled',
if_false: 'manual'
}
}
} }
} }
@@ -84,6 +128,7 @@ export default class TestsTable extends Component {
var data = this.state.data; var data = this.state.data;
var show = this.state.showTable; var show = this.state.showTable;
var refresh = this.state.refresh; var refresh = this.state.refresh;
let allFields = this.state.allFields;
if(data.length > 0) { if(data.length > 0) {
return ( return (
@@ -102,18 +147,18 @@ export default class TestsTable extends Component {
<Table responsive> <Table responsive>
<thead> <thead>
<tr> <tr>
<th>ID</th> {window.config.tables.visible_columns.map((e, i) => {
<th>Time</th> return (
<th>Download (Mbit/s)</th> <th key={i}>{allFields[e].alias}</th>
<th>Upload (Mbit/s)</th> );
<th>Ping (ms)</th> })}
<th>More</th> <th>More</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{data.map((e,i) => { {data.map((e,i) => {
return ( return (
<TableRow key={e.id} data={e} refresh={this.getData} /> <TableRow key={e.id} data={e} allFields={allFields} refresh={this.getData} />
); );
})} })}
</tbody> </tbody>