Dashboard code cleanup (#13996)

* Dashboard Cleanup
Remove static widgets table, list of available widgets should not be in the database.
Remove legacy ajax scripts
Cleanup and reorganize controllers

* reorganize code to put all dashboard things into it's controller
better url scheme while supporting the original

* lint clean ups

* properly formatted language file

* style fixes

* update schema
This commit is contained in:
Tony Murray 2022-05-31 08:08:40 -05:00 committed by GitHub
parent 4e5355b11d
commit 32f1ce494e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 726 additions and 762 deletions

View File

@ -0,0 +1,271 @@
<?php
/**
* DashboardController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* @link https://www.librenms.org
*
* @copyright 2022 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers;
use App\Models\Dashboard;
use App\Models\User;
use App\Models\UserPref;
use App\Models\UserWidget;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use LibreNMS\Config;
class DashboardController extends Controller
{
/** @var string[] */
public static $widgets = [
'alerts',
'alertlog',
'alertlog-stats',
'availability-map',
'component-status',
'device-summary-horiz',
'device-summary-vert',
'device-types',
'eventlog',
'globe',
'generic-graph',
'graylog',
'generic-image',
'notes',
'server-stats',
'syslog',
'top-devices',
'top-errors',
'top-interfaces',
'worldmap',
];
/** @var \Illuminate\Support\Collection<\App\Models\Dashboard> */
private $dashboards;
public function __construct()
{
$this->authorizeResource(Dashboard::class, 'dashboard');
}
/**
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View
*/
public function index(Request $request)
{
$request->validate([
'dashboard' => 'integer',
'bare' => 'nullable|in:yes',
]);
$user = $request->user();
$dashboards = $this->getAvailableDashboards($user);
// specific dashboard
if (! empty($request->dashboard) && $dashboards->has($request->dashboard)) {
return $this->show($request, $dashboards->get($request->dashboard));
}
// default dashboard
$user_default_dash = (int) UserPref::getPref($user, 'dashboard');
$global_default = (int) Config::get('webui.default_dashboard_id');
// load user default
if ($dashboards->has($user_default_dash)) {
return $this->show($request, $dashboards->get($user_default_dash));
}
// load global default
if ($dashboards->has($global_default)) {
return $this->show($request, $dashboards->get($global_default));
}
// load users first dashboard
$user_first_dashboard = $dashboards->firstWhere('user_id', $user->user_id);
if ($user_first_dashboard) {
return $this->show($request, $user_first_dashboard);
}
// create a dashboard for this user
return $this->show($request, Dashboard::create([
'dashboard_name' => 'Default',
'user_id' => $user->user_id,
]));
}
/**
* @param \Illuminate\Http\Request $request
* @param \App\Models\Dashboard $dashboard
* @return \Illuminate\Contracts\View\View
*/
public function show(Request $request, Dashboard $dashboard)
{
$request->validate([
'bare' => 'nullable|in:yes',
]);
$user = Auth::user();
// Split dashboards into user owned or shared
$dashboards = $this->getAvailableDashboards($user);
[$user_dashboards, $shared_dashboards] = $dashboards->partition(function ($dashboard) use ($user) {
return $dashboard->user_id == $user->user_id;
});
$data = $dashboard->widgets;
if ($data->isEmpty()) {
$data = [
[
'user_widget_id' => 0,
'title' => 'Add a widget',
'widget' => 'placeholder',
'col' => 1,
'row' => 1,
'size_x' => 6,
'size_y' => 2,
'refresh' => 60,
],
];
}
$widgets = array_combine(self::$widgets, array_map(function ($widget) {
return trans("widgets.$widget.title");
}, self::$widgets));
$user_list = $user->can('manage', User::class)
? User::where('user_id', '!=', $user->user_id)
->orderBy('username')
->pluck('username', 'user_id')
: [];
return view('overview.default', [
'bare' => $request->get('bare'),
'dash_config' => $data,
'dashboard' => $dashboard,
'hide_dashboard_editor' => UserPref::getPref($user, 'hide_dashboard_editor'),
'user_dashboards' => $user_dashboards,
'shared_dashboards' => $shared_dashboards,
'widgets' => $widgets,
'user_list' => $user_list,
]);
}
public function store(Request $request): JsonResponse
{
$this->validate($request, [
'dashboard_name' => 'string|max:255',
]);
$name = trim(strip_tags($request->get('dashboard_name')));
$dashboard = Dashboard::create([
'user_id' => Auth::id(),
'dashboard_name' => $name,
'access' => 0,
]);
return new JsonResponse([
'status' => 'ok',
'message' => 'Dashboard ' . htmlentities($name) . ' created',
'dashboard_id' => $dashboard->dashboard_id,
]);
}
public function update(Request $request, Dashboard $dashboard): JsonResponse
{
$validated = $this->validate($request, [
'dashboard_name' => 'string|max:255',
'access' => 'int|in:0,1,2',
]);
$dashboard->fill($validated);
$dashboard->save();
return new JsonResponse([
'status' => 'ok',
'message' => 'Dashboard ' . htmlentities($dashboard->dashboard_name) . ' updated',
]);
}
public function destroy(Dashboard $dashboard): JsonResponse
{
$dashboard->widgets()->delete();
$dashboard->delete();
return new JsonResponse([
'status' => 'ok',
'message' => 'Dashboard deleted',
]);
}
public function copy(Request $request, Dashboard $dashboard): JsonResponse
{
$this->validate($request, [
'target_user_id' => 'required|exists:App\Models\User,user_id',
]);
$target_user_id = $request->get('target_user_id');
$this->authorize('copy', [$dashboard, $target_user_id]);
$dashboard_copy = $dashboard->replicate()->fill([
'user_id' => $target_user_id,
'dashboard_name' => $dashboard->dashboard_name . '_' . Auth::user()->username,
]);
if ($dashboard_copy->save()) {
// copy widgets
$dashboard->widgets->each(function (UserWidget $widget) use ($dashboard_copy, $target_user_id) {
$dashboard_copy->widgets()->save($widget->replicate()->fill([
'user_id' => $target_user_id,
]));
});
return response()->json([
'status' => 'ok',
'message' => 'Dashboard copied',
]);
}
return response()->json([
'status' => 'error',
'message' => 'ERROR: Could not copy Dashboard',
]);
}
/**
* @param \App\Models\User $user
* @return \Illuminate\Support\Collection<\App\Models\Dashboard>
*/
private function getAvailableDashboards(User $user): Collection
{
if ($this->dashboards === null) {
$this->dashboards = Dashboard::allAvailable($user)->with('user:user_id,username')
->orderBy('dashboard_name')->get()->keyBy('dashboard_id');
}
return $this->dashboards;
}
}

View File

@ -0,0 +1,93 @@
<?php
namespace App\Http\Controllers;
use App\Models\Dashboard;
use App\Models\UserWidget;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;
class DashboardWidgetController extends Controller
{
public function add(Dashboard $dashboard, Request $request): JsonResponse
{
$this->authorize('update', $dashboard);
$this->validate($request, [
'widget_type' => Rule::in(DashboardController::$widgets),
]);
$type = $request->get('widget_type');
$widget = new UserWidget([
'user_id' => Auth::id(),
'widget' => $type,
'col' => 1,
'row' => 1,
'size_x' => 6,
'size_y' => 3,
'title' => trans("widgets.$type.title"),
'refresh' => 60,
'settings' => '',
]);
$dashboard->widgets()->save($widget);
return new JsonResponse([
'status' => 'ok',
'message' => 'Widget ' . htmlentities($widget->title) . ' added',
'extra' => $widget->attributesToArray(),
]);
}
public function remove(UserWidget $widget): JsonResponse
{
$this->authorize('update', $widget->dashboard);
$widget->delete();
return new JsonResponse([
'status' => 'ok',
'message' => 'Widget ' . htmlentities($widget->title) . ' removed',
]);
}
public function clear(Dashboard $dashboard): JsonResponse
{
$this->authorize('update', $dashboard);
$dashboard->widgets()->delete();
return new JsonResponse([
'status' => 'ok',
'message' => 'All widgets removed',
]);
}
public function update(Dashboard $dashboard, Request $request): JsonResponse
{
$this->authorize('update', $dashboard);
$validated = $this->getValidationFactory()->make(
json_decode($request->get('data', '[]'), true), [
'*' => 'array',
'*.id' => 'integer',
'*.col' => 'integer',
'*.row' => 'integer',
'*.size_x' => 'integer',
'*.size_y' => 'integer',
])->validate();
foreach ($validated as $item) {
if ($widget = UserWidget::find($item['id'])) {
$widget->fill($item);
$widget->save();
}
}
return new JsonResponse([
'status' => 'ok',
'message' => 'Widgets updated',
]);
}
}

View File

@ -1,82 +0,0 @@
<?php
/**
* CopyDashboardController.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* @link https://www.librenms.org
*
* @copyright 2020 Thomas Berberich
* @author Thomas Berberich <sourcehhdoctor@gmail.com>
*/
namespace App\Http\Controllers\Form;
use App\Http\Controllers\Controller;
use App\Models\Dashboard;
use App\Models\UserWidget;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class CopyDashboardController extends Controller
{
public function store(Request $request)
{
$target_user_id = $request->get('target_user_id');
$dashboard_id = $request->get('dashboard_id');
$dashboard = Dashboard::where(['dashboard_id' => $dashboard_id, 'user_id' => Auth::id()])->first();
$success = true;
if ((empty($dashboard)) || (empty($target_user_id))) {
$success = false;
}
if ($success) {
$dashboard_copy = $dashboard->replicate()->fill([
'user_id' => $target_user_id,
'dashboard_name' => $dashboard['dashboard_name'] .= '_' . Auth::user()->username,
]);
$success = $dashboard_copy->save();
}
if ($success && isset($dashboard_copy)) {
$widgets = UserWidget::where(['dashboard_id' => $dashboard_id, 'user_id' => Auth::id()])->get();
foreach ($widgets as $widget) {
$widget_copy = $widget->replicate()->fill([
'user_id' => $target_user_id,
'dashboard_id' => $dashboard_copy->dashboard_id,
]);
$success &= $widget_copy->save();
}
}
if ($success) {
$status = 'ok';
$message = 'Dashboard copied';
} else {
$status = 'error';
$message = 'ERROR: Could not copy Dashboard';
}
return response()->json([
'status' => $status,
'message' => $message,
]);
}
}

View File

@ -3,27 +3,22 @@
namespace App\Http\Controllers;
use App\Models\BgpPeer;
use App\Models\Dashboard;
use App\Models\Device;
use App\Models\Port;
use App\Models\Service;
use App\Models\Syslog;
use App\Models\User;
use App\Models\UserPref;
use App\Models\Widget;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use LibreNMS\Config;
class OverviewController extends Controller
{
/**
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View
*/
public function index(Request $request)
{
$request->validate([
'dashboard' => 'integer',
'bare' => 'nullable|in:yes',
]);
$view = Config::get('front_page');
if (view()->exists("overview.custom.$view")) {
@ -32,90 +27,14 @@ class OverviewController extends Controller
return $this->{$view}($request);
}
return $this->default($request);
}
public function default(Request $request)
{
$user = Auth::user();
$dashboards = Dashboard::allAvailable($user)->with('user:user_id,username')->orderBy('dashboard_name')->get()->keyBy('dashboard_id');
// Split dashboards into user owned or shared
[$user_dashboards, $shared_dashboards] = $dashboards->partition(function ($dashboard) use ($user) {
return $dashboard->user_id == $user->user_id;
});
if (! empty($request->dashboard) && isset($dashboards[$request->dashboard])) {
// specific dashboard
$dashboard = $dashboards[$request->dashboard];
} else {
$user_default_dash = (int) UserPref::getPref($user, 'dashboard');
$global_default = (int) Config::get('webui.default_dashboard_id');
// load user default
if (isset($dashboards[$user_default_dash])) {
$dashboard = $dashboards[$user_default_dash];
// load global default
} elseif (isset($dashboards[$global_default])) {
$dashboard = $dashboards[$global_default];
// load users first dashboard
} elseif (! empty($user_dashboards)) {
$dashboard = $user_dashboards->first();
}
// specific dashboard was requested, but doesn't exist
if (isset($dashboard) && ! empty($request->dashboard)) {
flash()
->using('template.librenms')
->title('Requested Dashboard Not Found!')
->addError("Dashboard <code>#$request->dashboard</code> does not exist! Loaded <code>
" . htmlentities($dashboard->dashboard_name) . '</code> instead.');
}
}
if (! isset($dashboard)) {
$dashboard = Dashboard::create([
'dashboard_name' => 'Default',
'user_id' => $user->user_id,
]);
}
$data = $dashboard
->widgets()
->select(['user_widget_id', 'users_widgets.widget_id', 'title', 'widget', 'col', 'row', 'size_x', 'size_y', 'refresh', 'settings'])
->join('widgets', 'widgets.widget_id', '=', 'users_widgets.widget_id')
->get();
if ($data->isEmpty()) {
$data[] = ['user_widget_id'=>'0',
'widget_id'=>1,
'title'=>'Add a widget',
'widget'=>'placeholder',
'col'=>1,
'row'=>1,
'size_x'=>6,
'size_y'=>2,
'refresh'=>60,
];
}
$bare = $request->bare;
$data = serialize(json_encode($data));
$dash_config = unserialize($data);
$hide_dashboard_editor = UserPref::getPref($user, 'hide_dashboard_editor');
$widgets = Widget::select(['widget_id', 'widget_title'])->orderBy('widget_title')->get();
$user_list = [];
if ($user->can('manage', User::class)) {
$user_list = User::select(['username', 'user_id'])
->where('user_id', '!=', $user->user_id)
->orderBy('username')
->get();
}
return view('overview.default', compact('bare', 'dash_config', 'dashboard', 'hide_dashboard_editor', 'user_dashboards', 'shared_dashboards', 'widgets', 'user_list'));
// default to dashboard
return (new DashboardController())->index($request);
}
/**
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Contracts\View\View
*/
public function simple(Request $request)
{
//TODO: All below missing D.ignore = '0' check
@ -168,10 +87,10 @@ class OverviewController extends Controller
if (Config::get('enable_syslog')) {
$syslog = Syslog::hasAccess(Auth::user())
->orderBy('timestamp', 'desc')
->limit(20)
->with('device')
->get();
->orderBy('timestamp', 'desc')
->limit(20)
->with('device')
->get();
}
return view('overview.simple', compact('devices_down', 'ports_down', 'services_down', 'bgp_down', 'devices_uptime', 'syslog'));

View File

@ -19,30 +19,29 @@
*
* @link https://www.librenms.org
*
* @copyright 2018 Tony Murray
* @copyright 2022 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Http\Controllers\Form;
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\UserWidget;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class WidgetSettingsController extends Controller
{
public function update(Request $request, $widget_settings)
public function update(Request $request, UserWidget $widget): JsonResponse
{
$this->validate($request, [
'settings' => 'array',
'settings.refresh' => 'int|min:1',
]);
$widget = UserWidget::with('dashboard')->findOrFail($widget_settings);
$widget_settings = (array) $request->get('settings', []);
unset($widget_settings['_token']);
if (! $widget->dashboard->canWrite($request->user())) {
if (! $request->user()->can('update', $widget->dashboard)) {
return response()->json([
'status' => 'error',
'message' => 'ERROR: You have no write-access to this dashboard',

View File

@ -13,26 +13,6 @@ class Dashboard extends Model
protected $primaryKey = 'dashboard_id';
protected $fillable = ['user_id', 'dashboard_name', 'access'];
// ---- Helper Functions ---
/**
* @param User $user
* @return bool
*/
public function canRead($user)
{
return $this->user_id == $user->user_id || $this->access > 0;
}
/**
* @param User $user
* @return bool
*/
public function canWrite($user)
{
return $this->user_id == $user->user_id || $this->access > 1;
}
// ---- Query scopes ----
/**

View File

@ -4,14 +4,13 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
class UserWidget extends Model
{
public $timestamps = false;
protected $table = 'users_widgets';
protected $primaryKey = 'user_widget_id';
protected $fillable = ['user_id', 'widget_id', 'col', 'row', 'size_x', 'size_y', 'title', 'refresh', 'settings', 'dashboard_id'];
protected $fillable = ['user_id', 'widget', 'col', 'row', 'size_x', 'size_y', 'title', 'refresh', 'settings', 'dashboard_id'];
protected $casts = ['settings' => 'array'];
// ---- Define Relationships ----
@ -21,11 +20,6 @@ class UserWidget extends Model
return $this->belongsTo(\App\Models\User::class, 'user_id');
}
public function widget(): HasOne
{
return $this->hasOne(\App\Models\Widget::class, 'widget_id');
}
public function dashboard(): BelongsTo
{
return $this->belongsTo(\App\Models\Dashboard::class, 'dashboard_id');

View File

@ -1,35 +0,0 @@
<?php
/**
* Widget.php
*
* -Description-
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* @link https://www.librenms.org
*
* @copyright 2018 Tony Murray
* @author Tony Murray <murraytony@gmail.com>
*/
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Widget extends Model
{
public $timestamps = false;
protected $primaryKey = 'widget_id';
protected $fillable = ['widget_title', 'widget', 'base_dimensions'];
}

View File

@ -0,0 +1,94 @@
<?php
namespace App\Policies;
use App\Models\Dashboard;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class DashboardPolicy
{
use HandlesAuthorization;
/**
* Create a new policy instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Determine whether the user can view any dashboard.
*
* @param \App\Models\User $user
* @return mixed
*/
public function viewAny(User $user)
{
return true;
}
/**
* Determine whether the user can view the dashboard.
*
* @param \App\Models\User $user
* @param \App\Models\Dashboard $dashboard
* @return mixed
*/
public function view(User $user, Dashboard $dashboard)
{
return $dashboard->user_id == $user->user_id || $dashboard->access > 0;
}
/**
* Determine whether the user can create dashboards.
*
* @param \App\Models\User $user
* @return mixed
*/
public function create(User $user)
{
return true;
}
/**
* Determine whether the user can update the dashboard.
*
* @param \App\Models\User $user
* @param \App\Models\Dashboard $dashboard
* @return mixed
*/
public function update(User $user, Dashboard $dashboard)
{
return $dashboard->user_id == $user->user_id || $dashboard->access > 1;
}
/**
* Determine whether the user can delete the dashboard.
*
* @param \App\Models\User $user
* @param \App\Models\Dashboard $dashboard
* @return mixed
*/
public function delete(User $user, Dashboard $dashboard)
{
return $dashboard->user_id == $user->user_id || $user->isAdmin();
}
/**
* Determine whether the user can copy the dashboard.
*
* @param \App\Models\User $user
* @param \App\Models\Dashboard $dashboard
* @param int $target_user_id
* @return bool
*/
public function copy(User $user, Dashboard $dashboard, int $target_user_id): bool
{
// user can copy to themselves if they can view, otherwise admins can
return $user->isAdmin() || ($user->user_id == $target_user_id && $this->view($user, $dashboard));
}
}

View File

@ -16,6 +16,7 @@ class AuthServiceProvider extends ServiceProvider
*/
protected $policies = [
\App\Models\User::class => \App\Policies\UserPolicy::class,
\App\Models\Dashboard::class => \App\Policies\DashboardPolicy::class,
\App\Models\Device::class => \App\Policies\DevicePolicy::class,
\App\Models\DeviceGroup::class => \App\Policies\DeviceGroupPolicy::class,
\App\Models\PollerCluster::class => \App\Policies\PollerClusterPolicy::class,

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddWidgetsColumnToUsersWidgetsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users_widgets', function (Blueprint $table) {
$table->string('widget', 32)->default('')->after('user_id');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users_widgets', function (Blueprint $table) {
$table->dropColumn('widget');
});
}
}

View File

@ -0,0 +1,45 @@
<?php
use App\Models\UserWidget;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Collection;
class MigrateWidgetIds extends Migration
{
/** @var Illuminate\Support\Collection<string, mixed> */
private $map;
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$this->map = DB::table('widgets')->pluck('widget', 'widget_id');
UserWidget::query()->chunk(1000, function (Collection $widgets) {
$widgets->each(function ($widget) {
$widget->widget = $this->map[$widget->widget_id];
$widget->save();
});
});
Schema::table('users_widgets', function (Blueprint $table) {
$table->string('widget', 32)->default(null)->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users_widgets', function (Blueprint $table) {
$table->string('widget', 32)->default('')->change();
});
}
}

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class RemoveUserWidgetsId extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users_widgets', function (Blueprint $table) {
$table->dropColumn('widget_id');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users_widgets', function (Blueprint $table) {
$table->unsignedInteger('widget_id')->after('widget');
});
}
}

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class DropWidgetsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::dropIfExists('widgets');
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::create('widgets', function (Blueprint $table) {
$table->increments('widget_id');
$table->string('widget_title');
$table->string('widget')->unique();
$table->string('base_dimensions', 10);
});
}
}

View File

@ -14,7 +14,6 @@ class DatabaseSeeder extends Seeder
public function run()
{
$this->call(DefaultAlertTemplateSeeder::class);
$this->call(DefaultWidgetSeeder::class);
$this->call(DefaultLegacySchemaSeeder::class);
$this->call(ConfigSeeder::class);
}

View File

@ -1,126 +0,0 @@
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class DefaultWidgetSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
$widgets = [
[
'widget_title' => 'Availability map',
'widget' => 'availability-map',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Device summary horizontal',
'widget' => 'device-summary-horiz',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Alerts',
'widget' => 'alerts',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Device summary vertical',
'widget' => 'device-summary-vert',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Globe map',
'widget' => 'globe',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Syslog',
'widget' => 'syslog',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Eventlog',
'widget' => 'eventlog',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'World map',
'widget' => 'worldmap',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Graylog',
'widget' => 'graylog',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Graph',
'widget' => 'generic-graph',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Top Devices',
'widget' => 'top-devices',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Top Interfaces',
'widget' => 'top-interfaces',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Notes',
'widget' => 'notes',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'External Images',
'widget' => 'generic-image',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Component Status',
'widget' => 'component-status',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Alert History Stats',
'widget' => 'alertlog-stats',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Server Stats',
'widget' => 'server-stats',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Alert History',
'widget' => 'alertlog',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Top Errors',
'widget' => 'top-errors',
'base_dimensions' => '6,3',
],
[
'widget_title' => 'Device Types',
'widget' => 'device-types',
'base_dimensions' => '6,3',
],
];
$existing = DB::table('widgets')->pluck('widget');
DB::table('widgets')->insert(array_filter($widgets, function ($entry) use ($existing) {
return ! $existing->contains($entry['widget']);
}));
}
}

View File

@ -1,53 +0,0 @@
<?php
/* Copyright (C) 2015 Daniel Preussker, QuxLabs UG <preussker@quxlabs.com>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. */
/**
* Create Dashboards
*
* @author Daniel Preussker
* @copyright 2015 Daniel Preussker, QuxLabs UG
* @license GPL
*/
header('Content-type: application/json');
if (! Auth::check()) {
$response = [
'status' => 'error',
'message' => 'Unauthenticated',
];
echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
exit;
}
$status = 'error';
$message = 'unknown error';
$dashboard_name = trim(strip_tags($_REQUEST['dashboard_name']));
if (! empty($dashboard_name) && ($dash_id = dbInsert(['dashboard_name' => $dashboard_name, 'user_id' => Auth::id()], 'dashboards'))) {
$status = 'ok';
$message = 'Dashboard ' . $dashboard_name . ' created';
} else {
$status = 'error';
$message = 'ERROR: Could not create';
}
$response = [
'status' => $status,
'message' => $message,
'dashboard_id' => $dash_id,
];
echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

View File

@ -1,56 +0,0 @@
<?php
/* Copyright (C) 2015 Daniel Preussker, QuxLabs UG <preussker@quxlabs.com>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. */
/**
* Delete Dashboards
*
* @author Daniel Preussker
* @copyright 2015 Daniel Preussker, QuxLabs UG
* @license GPL
*/
header('Content-type: application/json');
if (! Auth::check()) {
$response = [
'status' => 'error',
'message' => 'Unauthenticated',
];
echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
exit;
}
$status = 'error';
$message = 'unknown error';
$dashboard_id = (int) $_REQUEST['dashboard_id'];
if ($dashboard_id) {
dbDelete('users_widgets', 'user_id = ? && dashboard_id = ?', [Auth::id(), $dashboard_id]);
if (dbDelete('dashboards', 'user_id = ? && dashboard_id = ?', [Auth::id(), $dashboard_id])) {
$status = 'ok';
$message = 'Dashboard deleted';
} else {
$message = 'ERROR: Could not delete dashboard ' . $dashboard_id;
}
} else {
$message = 'ERROR: Not enough params';
}
$response = [
'status' => $status,
'message' => $message,
];
echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

View File

@ -1,48 +0,0 @@
<?php
/* Copyright (C) 2015 Daniel Preussker, QuxLabs UG <preussker@quxlabs.com>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. */
/**
* Edit Dashboards
*
* @author Daniel Preussker
* @copyright 2015 Daniel Preussker, QuxLabs UG
* @license GPL
*/
header('Content-type: application/json');
$status = 'error';
$message = 'unknown error';
$dashboard_id = (int) $_REQUEST['dashboard_id'];
$dashboard_name = \LibreNMS\Util\Clean::html($_REQUEST['dashboard_name'], []);
$access = $_REQUEST['access'];
if (isset($dashboard_id) && isset($dashboard_name) && isset($access)) {
if (dbUpdate(['dashboard_name'=> $dashboard_name, 'access'=> $access], 'dashboards', '(user_id = ? || access = 2) && dashboard_id = ?', [Auth::id(), $dashboard_id]) >= 0) {
$status = 'ok';
$message = 'Dashboard ' . $dashboard_name . ' updated';
} else {
$message = 'ERROR: Could not update dashboard ' . $dashboard_name;
}
} else {
$message = 'ERROR: Not enough params';
}
$response = [
'status' => $status,
'message' => $message,
];
echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

View File

@ -1,79 +0,0 @@
<?php
header('Content-type: application/json');
if (! Auth::check()) {
$response = [
'status' => 'error',
'message' => 'Unauthenticated',
];
echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
exit;
}
$status = 'error';
$message = 'Error updating user dashboard config';
$data = json_decode($vars['data'], true);
$sub_type = $vars['sub_type'];
$widget_id = $vars['widget_id'];
$dasboard_id = $vars['dashboard_id'];
if ($sub_type == 'remove' && is_numeric($widget_id)) {
if (dbFetchCell('select 1 from dashboards where (user_id = ? || access = 2) && dashboard_id = ?', [Auth::id(), $dasboard_id]) == 1) {
if ($widget_id == 0 || dbDelete('users_widgets', '`user_widget_id`=? AND `dashboard_id`=?', [$widget_id, $dasboard_id])) {
$status = 'ok';
$message = 'Widget ' . $widget_id . ' removed';
}
} else {
$status = 'error';
$message = 'ERROR: You don\'t have write access.';
}
} elseif ($sub_type == 'remove-all') {
if (dbFetchCell('select 1 from dashboards where (user_id = ? || access = 2) && dashboard_id = ?', [Auth::id(), $dasboard_id]) == 1) {
if (dbDelete('users_widgets', '`dashboard_id`=?', [$dasboard_id])) {
$status = 'ok';
$message = 'All widgets removed';
}
} else {
$status = 'error';
$message = 'ERROR: You don\'t have write access.';
}
} elseif ($sub_type == 'add' && is_numeric($widget_id)) {
if (dbFetchCell('select 1 from dashboards where (user_id = ? || access = 2) && dashboard_id = ?', [Auth::id(), $dasboard_id]) == 1) {
$widget = dbFetchRow('SELECT * FROM `widgets` WHERE `widget_id`=?', [$widget_id]);
if (is_array($widget)) {
[$x,$y] = explode(',', $widget['base_dimensions']);
$item_id = dbInsert(['user_id'=>Auth::id(), 'widget_id'=>$widget_id, 'col'=>1, 'row'=>1, 'refresh'=>60, 'title'=>$widget['widget_title'], 'size_x'=>$x, 'size_y'=>$y, 'settings'=>'', 'dashboard_id'=>$dasboard_id], 'users_widgets');
if (is_numeric($item_id)) {
$extra = ['user_widget_id'=>$item_id, 'widget_id'=>$item_id, 'title'=>$widget['widget_title'], 'widget'=>$widget['widget'], 'refresh'=>60, 'size_x'=>$x, 'size_y'=>$y];
$status = 'ok';
$message = 'Widget ' . $widget['widget_title'] . ' added';
}
}
} else {
$status = 'error';
$message = 'ERROR: You don\'t have write access.';
}
} else {
if (dbFetchCell('select 1 from dashboards where (user_id = ? || access = 2) && dashboard_id = ?', [Auth::id(), $dasboard_id]) == 1) {
$status = 'ok';
$message = 'Widgets updated';
foreach ($data as $line) {
if (is_array($line)) {
$update = ['col'=>$line['col'], 'row'=>$line['row'], 'size_x'=>$line['size_x'], 'size_y'=>$line['size_y']];
dbUpdate($update, 'users_widgets', '`user_widget_id`=? AND `dashboard_id`=?', [$line['id'], $dasboard_id]);
}
}
} else {
$status = 'error';
$message = 'ERROR: You don\'t have write access.';
}
}
$response = [
'status' => $status,
'message' => $message,
'extra' => $extra,
];
echo json_encode($response, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);

View File

@ -2067,7 +2067,7 @@ users_widgets:
Columns:
- { Field: user_widget_id, Type: 'int unsigned', 'Null': false, Extra: auto_increment }
- { Field: user_id, Type: 'int unsigned', 'Null': false, Extra: '' }
- { Field: widget_id, Type: 'int unsigned', 'Null': false, Extra: '' }
- { Field: widget, Type: varchar(32), 'Null': false, Extra: '' }
- { Field: col, Type: tinyint, 'Null': false, Extra: '' }
- { Field: row, Type: tinyint, 'Null': false, Extra: '' }
- { Field: size_x, Type: tinyint, 'Null': false, Extra: '' }
@ -2078,7 +2078,7 @@ users_widgets:
- { Field: dashboard_id, Type: 'int unsigned', 'Null': false, Extra: '' }
Indexes:
PRIMARY: { Name: PRIMARY, Columns: [user_widget_id], Unique: true, Type: BTREE }
user_id: { Name: user_id, Columns: [user_id, widget_id], Unique: false, Type: BTREE }
user_id: { Name: user_id, Columns: [user_id], Unique: false, Type: BTREE }
vlans:
Columns:
- { Field: vlan_id, Type: 'int unsigned', 'Null': false, Extra: auto_increment }
@ -2131,15 +2131,6 @@ vrf_lite_cisco:
vrf_lite_cisco_device_id_context_name_vrf_name_index: { Name: vrf_lite_cisco_device_id_context_name_vrf_name_index, Columns: [device_id, context_name, vrf_name], Unique: false, Type: BTREE }
vrf_lite_cisco_device_id_index: { Name: vrf_lite_cisco_device_id_index, Columns: [device_id], Unique: false, Type: BTREE }
vrf_lite_cisco_vrf_name_index: { Name: vrf_lite_cisco_vrf_name_index, Columns: [vrf_name], Unique: false, Type: BTREE }
widgets:
Columns:
- { Field: widget_id, Type: 'int unsigned', 'Null': false, Extra: auto_increment }
- { Field: widget_title, Type: varchar(255), 'Null': false, Extra: '' }
- { Field: widget, Type: varchar(255), 'Null': false, Extra: '' }
- { Field: base_dimensions, Type: varchar(10), 'Null': false, Extra: '' }
Indexes:
PRIMARY: { Name: PRIMARY, Columns: [widget_id], Unique: true, Type: BTREE }
widgets_widget_unique: { Name: widgets_widget_unique, Columns: [widget], Unique: true, Type: BTREE }
wireless_sensors:
Columns:
- { Field: sensor_id, Type: 'int unsigned', 'Null': false, Extra: auto_increment }

View File

@ -3087,51 +3087,6 @@ parameters:
count: 1
path: includes/html/forms/update-alert-rule.inc.php
-
message:
"""
#^Call to deprecated function dbDelete\\(\\)\\:
Please use Eloquent instead; https\\://laravel\\.com/docs/eloquent\\#deleting\\-models$#
"""
count: 2
path: includes/html/forms/update-dashboard-config.inc.php
-
message:
"""
#^Call to deprecated function dbFetchCell\\(\\)\\:
Please use Eloquent instead; https\\://laravel\\.com/docs/eloquent$#
"""
count: 4
path: includes/html/forms/update-dashboard-config.inc.php
-
message:
"""
#^Call to deprecated function dbFetchRow\\(\\)\\:
Please use Eloquent instead; https\\://laravel\\.com/docs/eloquent$#
"""
count: 1
path: includes/html/forms/update-dashboard-config.inc.php
-
message:
"""
#^Call to deprecated function dbInsert\\(\\)\\:
Please use Eloquent instead; https\\://laravel\\.com/docs/eloquent\\#inserting\\-and\\-updating\\-models$#
"""
count: 1
path: includes/html/forms/update-dashboard-config.inc.php
-
message:
"""
#^Call to deprecated function dbUpdate\\(\\)\\:
Please use Eloquent instead; https\\://laravel\\.com/docs/eloquent\\#inserting\\-and\\-updating\\-models$#
"""
count: 1
path: includes/html/forms/update-dashboard-config.inc.php
-
message:
"""

View File

@ -7535,21 +7535,6 @@ parameters:
count: 1
path: app/Http/Controllers/DeviceGroupController.php
-
message: "#^Method App\\\\Http\\\\Controllers\\\\Form\\\\CopyDashboardController\\:\\:store\\(\\) has no return type specified\\.$#"
count: 1
path: app/Http/Controllers/Form/CopyDashboardController.php
-
message: "#^Method App\\\\Http\\\\Controllers\\\\Form\\\\WidgetSettingsController\\:\\:update\\(\\) has no return type specified\\.$#"
count: 1
path: app/Http/Controllers/Form/WidgetSettingsController.php
-
message: "#^Method App\\\\Http\\\\Controllers\\\\Form\\\\WidgetSettingsController\\:\\:update\\(\\) has parameter \\$widget_settings with no type specified\\.$#"
count: 1
path: app/Http/Controllers/Form/WidgetSettingsController.php
-
message: "#^Method App\\\\Http\\\\Controllers\\\\Install\\\\ChecksController\\:\\:checkPhpVersion\\(\\) has no return type specified\\.$#"
count: 1
@ -7840,26 +7825,6 @@ parameters:
count: 1
path: app/Http/Controllers/Maps/MapController.php
-
message: "#^Method App\\\\Http\\\\Controllers\\\\OverviewController\\:\\:default\\(\\) has no return type specified\\.$#"
count: 1
path: app/Http/Controllers/OverviewController.php
-
message: "#^Method App\\\\Http\\\\Controllers\\\\OverviewController\\:\\:index\\(\\) has no return type specified\\.$#"
count: 1
path: app/Http/Controllers/OverviewController.php
-
message: "#^Method App\\\\Http\\\\Controllers\\\\OverviewController\\:\\:simple\\(\\) has no return type specified\\.$#"
count: 1
path: app/Http/Controllers/OverviewController.php
-
message: "#^Variable \\$user_dashboards in empty\\(\\) always exists and is always falsy\\.$#"
count: 1
path: app/Http/Controllers/OverviewController.php
-
message: "#^Method App\\\\Http\\\\Controllers\\\\PollerController\\:\\:checkTimeSinceLastPoll\\(\\) has no return type specified\\.$#"
count: 1

View File

@ -0,0 +1,64 @@
<?php
return [
'alerts' => [
'title' => 'Alerts',
],
'alertlog' => [
'title' => 'Alert History',
],
'alertlog-stats' => [
'title' => 'Alert History Stats',
],
'availability-map' => [
'title' => 'Availability Map',
],
'component-status' => [
'title' => 'Component Status',
],
'device-summary-horiz' => [
'title' => 'Device Summary Horizontal',
],
'device-summary-vert' => [
'title' => 'Device Summary Vertical',
],
'device-types' => [
'title' => 'Device Types',
],
'eventlog' => [
'title' => 'Eventlog',
],
'generic-graph' => [
'title' => 'Graph',
],
'generic-image' => [
'title' => 'External Images',
],
'globe' => [
'title' => 'Globe Map',
],
'graylog' => [
'title' => 'Graylog',
],
'notes' => [
'title' => 'Notes',
],
'server-stats' => [
'title' => 'Server Stats',
],
'syslog' => [
'title' => 'Syslog',
],
'top-devices' => [
'title' => 'Top Devices',
],
'top-errors' => [
'title' => 'Top Errors',
],
'top-interfaces' => [
'title' => 'Top Interfaces',
],
'worldmap' => [
'title' => 'World Map',
],
];

View File

@ -23,7 +23,7 @@
@forelse ($user_dashboards as $dash)
@if($dash->dashboard_id != $dashboard->dashboard_id)
<li>
<a href="{{ url("?dashboard=$dash->dashboard_id") }}">{{ $dash->dashboard_name }}</a>
<a href="{{ route('dashboard.show', $dash->dashboard_id) }}">{{ $dash->dashboard_name }}</a>
</li>
@endif
@empty
@ -36,7 +36,7 @@
@foreach ($shared_dashboards as $dash)
@if($dash->dashboard_id != $dashboard->dashboard_id)
<li>
<a href="{{ url("?dashboard=$dash->dashboard_id") }}">
<a href="{{ route('dashboard.show', $dash->dashboard_id) }}">
{{ ($dash->user->username ?? __('Deleted User')) . ':' . $dash->dashboard_name . ($dash->access == 1 ? ' (Read)' : '') }}</a>
</li>
@endif
@ -99,8 +99,8 @@
<div class="btn-group">
<select class="form-control" id="dashboard_copy_target" name="dashboard_copy_target" onchange="dashboard_copy_user_select()">
<option value="-1" selected> Copy Dashboard to </option>
@foreach ($user_list as $user)
<option value="{{ $user->user_id }}">{{ $user->username }}</option>
@foreach ($user_list as $user_id => $username)
<option value="{{ $user_id }}">{{ $username }}</option>
@endforeach
</select>
</div>
@ -124,9 +124,9 @@
</span>
</button>
<ul class="dropdown-menu">
@foreach ($widgets as $widget)
@foreach ($widgets as $type => $title)
<li>
<a href="#" onsubmit="return false;" class="place_widget" data-widget_id="{{ $widget->widget_id }}">{{ $widget->widget_title }}</a>
<a href="#" onsubmit="return false;" class="place_widget" data-widget_type="{{ $type }}">{{ $title }}</a>
</li>
@endforeach
</ul>
@ -175,7 +175,7 @@
<script type="text/javascript">
var gridster;
var serialization = {!! $dash_config !!};
var serialization = @json($dash_config);
serialization = Gridster.sort_by_row_and_col_asc(serialization);
var gridster_state = 0;
@ -244,16 +244,10 @@
});
$(document).on('click','#clear_widgets', function() {
var widget_id = $(this).data('widget-id');
if (dashboard_id > 0) {
$.ajax({
type: 'POST',
url: 'ajax_form.php',
data: {
type: "update-dashboard-config",
sub_type: 'remove-all',
dashboard_id: dashboard_id
},
type: 'DELETE',
url: '{{ route('dashboard.widget.clear', '?') }}'.replace('?', dashboard_id),
dataType: "json",
success: function (data) {
if (data.status == 'ok') {
@ -272,21 +266,18 @@
});
$('.place_widget').on('click', function(event, state) {
var widget_id = $(this).data('widget_id');
var widget_type = $(this).data('widget_type');
event.preventDefault();
if (dashboard_id > 0) {
$.ajax({
type: 'POST',
url: 'ajax_form.php',
url: '{{ route('dashboard.widget.add', '?') }}'.replace('?', dashboard_id),
data: {
type: "update-dashboard-config",
sub_type: 'add',
widget_id: widget_id,
dashboard_id: dashboard_id
widget_type: widget_type
},
dataType: "json",
success: function (data) {
if (data.status == 'ok') {
if (data.status === 'ok') {
widget_dom(data.extra);
updatePos(gridster);
toastr.success(data.message);
@ -305,14 +296,8 @@
$(document).on( "click", ".close-widget", function() {
var widget_id = $(this).data('widget-id');
$.ajax({
type: 'POST',
url: 'ajax_form.php',
data: {
type: "update-dashboard-config",
sub_type: 'remove',
widget_id: widget_id,
dashboard_id: dashboard_id
},
type: 'DELETE',
url: '{{ route('dashboard.widget.remove', '?') }}'.replace('?', widget_id),
dataType: "json",
success: function (data) {
if (data.status == 'ok') {
@ -344,8 +329,6 @@
function updatePos(gridster) {
var s = JSON.stringify(gridster.serialize());
@if ($dashboard->dashboard_id > 0)
var dashboard_id = {{ $dashboard->dashboard_id }};
@else
@ -354,13 +337,9 @@
if (dashboard_id > 0) {
$.ajax({
type: 'POST',
url: 'ajax_form.php',
data: {
type: "update-dashboard-config",
data: s,
dashboard_id: dashboard_id
},
type: 'PUT',
url: '{{ route('dashboard.widget.update', '?') }}'.replace('?', dashboard_id),
data: {data: JSON.stringify(gridster.serialize())},
dataType: "json",
success: function (data) {
if (data.status == 'ok') {
@ -396,18 +375,14 @@
function dashboard_delete(data) {
$.ajax({
type: 'POST',
url: 'ajax_form.php',
data: {
type: 'delete-dashboard',
dashboard_id: $(data).data('dashboard')
},
type: 'DELETE',
url: '{{ route('dashboard.destroy', '?') }}'.replace('?', $(data).data('dashboard')),
dataType: "json",
success: function (data) {
if( data.status == "ok" ) {
toastr.success(data.message);
setTimeout(function (){
window.location.href = "{{ url('/') }}";
window.location.href = "{{ route('home') }}";
}, 500);
} else {
@ -433,12 +408,10 @@
}
if (dashboard_id > 0) {
$.ajax({
type: 'POST',
url: 'ajax_form.php',
type: 'PUT',
url: '{{ route('dashboard.update', '?') }}'.replace('?', dashboard_id),
data: {
type: 'edit-dashboard',
dashboard_name: data['dashboard_name'],
dashboard_id: dashboard_id,
access: data['access']
},
dataType: "json",
@ -446,7 +419,7 @@
if (data.status == "ok") {
toastr.success(data.message);
setTimeout(function (){
window.location.href = "{{ url('/?dashboard=') }}" + dashboard_id;
window.location.href = '{{ route('dashboard.show', '?') }}'.replace('?', dashboard_id);
}, 500);
}
else {
@ -468,14 +441,14 @@
}
$.ajax({
type: 'POST',
url: 'ajax_form.php',
data: {type: 'add-dashboard', dashboard_name: data['dashboard_name']},
url: '{{ route('dashboard.store') }}',
data: {dashboard_name: data['dashboard_name']},
dataType: "json",
success: function (data) {
if( data.status == "ok" ) {
toastr.success(data.message);
setTimeout(function (){
window.location.href = "{{ url('/?dashboard=') }}" + data.dashboard_id;
window.location.href = '{{ route('dashboard.show', '?') }}'.replace('?', data.dashboard_id);
}, 500);
}
else {
@ -511,8 +484,8 @@
$.ajax({
type: 'POST',
url: '{{ url('/ajax/form/copy-dashboard') }}',
data: {target_user_id: target_user_id, dashboard_id: dashboard_id},
url: '{{ route('dashboard.copy', '?') }}'.replace('?', dashboard_id),
data: {target_user_id: target_user_id},
dataType: "json",
success: function (data) {
if( data.status == "ok" ) {
@ -589,7 +562,7 @@
if(widget_id > 0 && widget_settings != {}) {
$.ajax({
type: 'PUT',
url: '{{ url('/ajax/form/widget-settings/') }}/' + widget_id,
url: '{{ route('dashboard.widget.settings', '?') }}/'.replace('?', widget_id),
data: { settings: widget_settings },
dataType: "json",
success: function (data) {

View File

@ -66,6 +66,15 @@ Route::group(['middleware' => ['auth'], 'guard' => 'auth'], function () {
Route::get('devicedependency', 'DeviceDependencyController@dependencyMap');
});
// dashboard
Route::resource('dashboard', 'DashboardController')->except(['create', 'edit']);
Route::post('dashboard/{dashboard}/copy', 'DashboardController@copy')->name('dashboard.copy');
Route::post('dashboard/{dashboard}/widgets', 'DashboardWidgetController@add')->name('dashboard.widget.add');
Route::delete('dashboard/{dashboard}/widgets', 'DashboardWidgetController@clear')->name('dashboard.widget.clear');
Route::put('dashboard/{dashboard}/widgets', 'DashboardWidgetController@update')->name('dashboard.widget.update');
Route::delete('dashboard/widgets/{widget}', 'DashboardWidgetController@remove')->name('dashboard.widget.remove');
Route::put('dashboard/widgets/{widget}', 'WidgetSettingsController@update')->name('dashboard.widget.settings');
// Push notifications
Route::group(['prefix' => 'push'], function () {
Route::get('token', [\App\Http\Controllers\PushNotificationController::class, 'token'])->name('push.token');
@ -132,12 +141,6 @@ Route::group(['middleware' => ['auth'], 'guard' => 'auth'], function () {
Route::get('settings/list', 'SettingsController@listAll')->name('settings.list');
// form ajax handlers, perhaps should just be page controllers
Route::group(['prefix' => 'form', 'namespace' => 'Form'], function () {
Route::resource('widget-settings', 'WidgetSettingsController');
Route::post('copy-dashboard', 'CopyDashboardController@store');
});
// js select2 data controllers
Route::group(['prefix' => 'select', 'namespace' => 'Select'], function () {
Route::get('application', 'ApplicationController')->name('ajax.select.application');