mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Widget hot refresh & worldmap cleanup (#16053)
* Iterate in javascript and separate processing * Widget refresh/destroy events * Remove old dom and unbind events * fix whitespace * Fix up bootgrid tables, they inserted a div before the first div breaking event propagation switch to regular js function to scope variables instead of jquery * Handle settings the same way as the normal widget * Use standard init_map and add layer control * May need L.Control.Locate now * Set maxZoom for marker cluster * Try setMaxZoom * worldmap size 100 and resize on refresh/widget resize * Add resize event (and throttle it a bit) * Further worldmap cleanup * Move most javascript to common js, will cause js errors until page is reloaded, but better in the long run
This commit is contained in:
@@ -26,8 +26,10 @@
|
|||||||
namespace App\Http\Controllers\Widgets;
|
namespace App\Http\Controllers\Widgets;
|
||||||
|
|
||||||
use App\Models\Device;
|
use App\Models\Device;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use LibreNMS\Config;
|
use LibreNMS\Config;
|
||||||
|
use LibreNMS\Util\Url;
|
||||||
|
|
||||||
class WorldMapController extends WidgetController
|
class WorldMapController extends WidgetController
|
||||||
{
|
{
|
||||||
@@ -37,11 +39,11 @@ class WorldMapController extends WidgetController
|
|||||||
{
|
{
|
||||||
$this->defaults = [
|
$this->defaults = [
|
||||||
'title' => null,
|
'title' => null,
|
||||||
'title_url' => Config::get('leaflet.tile_url', '{s}.tile.openstreetmap.org'),
|
'init_lat' => Config::get('leaflet.default_lat'),
|
||||||
'init_lat' => Config::get('leaflet.default_lat', 51.4800),
|
'init_lng' => Config::get('leaflet.default_lng'),
|
||||||
'init_lng' => Config::get('leaflet.default_lng', 0),
|
'init_zoom' => Config::get('leaflet.default_zoom'),
|
||||||
'init_zoom' => Config::get('leaflet.default_zoom', 2),
|
'init_layer' => Config::get('geoloc.layer'),
|
||||||
'group_radius' => Config::get('leaflet.group_radius', 80),
|
'group_radius' => Config::get('leaflet.group_radius'),
|
||||||
'status' => '0,1',
|
'status' => '0,1',
|
||||||
'device_group' => null,
|
'device_group' => null,
|
||||||
];
|
];
|
||||||
@@ -50,17 +52,39 @@ class WorldMapController extends WidgetController
|
|||||||
public function getView(Request $request)
|
public function getView(Request $request)
|
||||||
{
|
{
|
||||||
$settings = $this->getSettings();
|
$settings = $this->getSettings();
|
||||||
$status = explode(',', $settings['status']);
|
|
||||||
|
|
||||||
$settings['dimensions'] = $request->get('dimensions');
|
$settings['dimensions'] = $request->get('dimensions');
|
||||||
|
$settings['status'] = array_map('intval', explode(',', $settings['status']));
|
||||||
|
$settings['map_config'] = [
|
||||||
|
'engine' => Config::get('geoloc.engine'),
|
||||||
|
'api_key' => Config::get('geoloc.api_key'),
|
||||||
|
'tile_url' => Config::get('leaflet.tile_url'),
|
||||||
|
'lat' => $settings['init_lat'],
|
||||||
|
'lng' => $settings['init_lng'],
|
||||||
|
'zoom' => $settings['init_zoom'],
|
||||||
|
'layer' => $settings['init_layer'],
|
||||||
|
];
|
||||||
|
|
||||||
$devices = Device::hasAccess($request->user())
|
return view('widgets.worldmap', $settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getData(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
$this->validate($request, [
|
||||||
|
'status' => 'array',
|
||||||
|
'status.*' => 'int',
|
||||||
|
'device_group' => 'int',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return response()->json($this->getMarkerData($request, $request->status ?? [0, 1], $request->device_group ?? 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMarkerData(Request $request, array $status, int $device_group_id): array
|
||||||
|
{
|
||||||
|
return Device::hasAccess($request->user())
|
||||||
->with('location')
|
->with('location')
|
||||||
->isActive()
|
->isActive()
|
||||||
->whereIn('status', $status)
|
->whereIn('status', $status)
|
||||||
->when($settings['device_group'], function ($query) use ($settings) {
|
->when($device_group_id, fn ($q) => $q->inDeviceGroup($device_group_id))
|
||||||
$query->inDeviceGroup($settings['device_group']);
|
|
||||||
})
|
|
||||||
->get()
|
->get()
|
||||||
->filter(function ($device) use ($status) {
|
->filter(function ($device) use ($status) {
|
||||||
/** @var Device $device */
|
/** @var Device $device */
|
||||||
@@ -68,31 +92,23 @@ class WorldMapController extends WidgetController
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add extra data
|
// hide devices under maintenance if only showing down devices
|
||||||
/** @phpstan-ignore-next-line */
|
if ($status == [0] && $device->isUnderMaintenance()) {
|
||||||
$device->markerIcon = 'greenMarker';
|
return false;
|
||||||
/** @phpstan-ignore-next-line */
|
|
||||||
$device->zOffset = 0;
|
|
||||||
|
|
||||||
if ($device->status == 0) {
|
|
||||||
$device->markerIcon = 'redMarker';
|
|
||||||
$device->zOffset = 10000;
|
|
||||||
|
|
||||||
if ($device->isUnderMaintenance()) {
|
|
||||||
if (in_array(0, $status)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$device->markerIcon = 'blueMarker';
|
|
||||||
$device->zOffset = 5000;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
})->map(function (Device $device) {
|
||||||
|
return [
|
||||||
$settings['devices'] = $devices;
|
'name' => $device->displayName(),
|
||||||
|
'lat' => $device->location->lat,
|
||||||
return view('widgets.worldmap', $settings);
|
'lng' => $device->location->lng,
|
||||||
|
'icon' => $device->icon,
|
||||||
|
'url' => Url::deviceUrl($device),
|
||||||
|
// status: 0 = down, 1 = up, 3 = down + under maintenance
|
||||||
|
'status' => (int) ($device->status ?: ($device->isUnderMaintenance() ? 3 : 0)),
|
||||||
|
];
|
||||||
|
})->values()->all();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSettingsView(Request $request)
|
public function getSettingsView(Request $request)
|
||||||
|
@@ -47,6 +47,7 @@
|
|||||||
'path' => storage_path('debugbar'), // For file driver
|
'path' => storage_path('debugbar'), // For file driver
|
||||||
'connection' => null, // Leave null for default connection (Redis/PDO)
|
'connection' => null, // Leave null for default connection (Redis/PDO)
|
||||||
'provider' => '', // Instance of StorageInterface for custom driver
|
'provider' => '', // Instance of StorageInterface for custom driver
|
||||||
|
'open' => true,
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -1776,10 +1776,8 @@ tr.search:nth-child(odd) {
|
|||||||
background-color: #000000;
|
background-color: #000000;
|
||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
-webkit-border-top-left-radius: 4px;
|
border-top-left-radius: 4px;
|
||||||
-moz-border-top-right-radius: 4px;
|
border-top-right-radius: 4px;
|
||||||
border-top-left-radius: 4px;
|
|
||||||
border-top-right-radius: 4px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.mapTooltip {
|
.mapTooltip {
|
||||||
@@ -1966,10 +1964,12 @@ label {
|
|||||||
.edit-widget, .close-widget { cursor: pointer; }
|
.edit-widget, .close-widget { cursor: pointer; }
|
||||||
.widget_body {
|
.widget_body {
|
||||||
padding: 0.8em;
|
padding: 0.8em;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100% - 38px);
|
height: calc(100% - 2.6em);
|
||||||
cursor: auto;
|
cursor: auto;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
@@ -2016,6 +2016,20 @@ label {
|
|||||||
margin:-8px;
|
margin:-8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.widget_body:has(> .worldmap_widget) {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.worldmap_widget {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-bottom-right-radius: 4px;
|
||||||
|
}
|
||||||
|
.worldmap_widget a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
.report-up {
|
.report-up {
|
||||||
color:#5CB85C;
|
color:#5CB85C;
|
||||||
}
|
}
|
||||||
|
@@ -303,6 +303,7 @@ function init_map(id, config = {}) {
|
|||||||
let baseMaps = {};
|
let baseMaps = {};
|
||||||
|
|
||||||
if (config.engine === 'google' && config.api_key) {
|
if (config.engine === 'google' && config.api_key) {
|
||||||
|
leaflet.setMaxZoom(21);
|
||||||
loadjs('https://maps.googleapis.com/maps/api/js?key=' + config.api_key, function () {
|
loadjs('https://maps.googleapis.com/maps/api/js?key=' + config.api_key, function () {
|
||||||
loadjs('js/Leaflet.GoogleMutant.js', function () {
|
loadjs('js/Leaflet.GoogleMutant.js', function () {
|
||||||
const roads = L.gridLayer.googleMutant({
|
const roads = L.gridLayer.googleMutant({
|
||||||
@@ -322,6 +323,7 @@ function init_map(id, config = {}) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else if (config.engine === 'bing' && config.api_key) {
|
} else if (config.engine === 'bing' && config.api_key) {
|
||||||
|
leaflet.setMaxZoom(18);
|
||||||
loadjs('js/leaflet-bing-layer.min.js', function () {
|
loadjs('js/leaflet-bing-layer.min.js', function () {
|
||||||
const roads = L.tileLayer.bing({
|
const roads = L.tileLayer.bing({
|
||||||
bingMapsKey: config.api_key,
|
bingMapsKey: config.api_key,
|
||||||
@@ -341,6 +343,7 @@ function init_map(id, config = {}) {
|
|||||||
leaflet.layerControl._container.style.display = (config.readonly ? 'none' : 'block');
|
leaflet.layerControl._container.style.display = (config.readonly ? 'none' : 'block');
|
||||||
});
|
});
|
||||||
} else if (config.engine === 'mapquest' && config.api_key) {
|
} else if (config.engine === 'mapquest' && config.api_key) {
|
||||||
|
leaflet.setMaxZoom(20);
|
||||||
loadjs('https://www.mapquestapi.com/sdk/leaflet/v2.2/mq-map.js?key=' + config.api_key, function () {
|
loadjs('https://www.mapquestapi.com/sdk/leaflet/v2.2/mq-map.js?key=' + config.api_key, function () {
|
||||||
const roads = MQ.mapLayer();
|
const roads = MQ.mapLayer();
|
||||||
const satellite = MQ.hybridLayer();
|
const satellite = MQ.hybridLayer();
|
||||||
@@ -354,22 +357,12 @@ function init_map(id, config = {}) {
|
|||||||
leaflet.layerControl._container.style.display = (config.readonly ? 'none' : 'block');
|
leaflet.layerControl._container.style.display = (config.readonly ? 'none' : 'block');
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
leaflet.setMaxZoom(20);
|
||||||
const tile_url = config.tile_url ? config.tile_url : '{s}.tile.openstreetmap.org';
|
const tile_url = config.tile_url ? config.tile_url : '{s}.tile.openstreetmap.org';
|
||||||
const osm = L.tileLayer('//' + tile_url + '/{z}/{x}/{y}.png', {
|
L.tileLayer('//' + tile_url + '/{z}/{x}/{y}.png', {
|
||||||
maxZoom: 19,
|
maxZoom: 19,
|
||||||
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||||
});
|
}).addTo(leaflet);
|
||||||
|
|
||||||
// var esri = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
|
|
||||||
// attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// baseMaps = {
|
|
||||||
// "OpenStreetMap": osm,
|
|
||||||
// "Satellite": esri
|
|
||||||
// };
|
|
||||||
// leaflet.layerControl = L.control.layers(baseMaps, null, {position: 'bottomleft'}).addTo(leaflet);
|
|
||||||
osm.addTo(leaflet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// disable all interaction
|
// disable all interaction
|
||||||
@@ -399,6 +392,83 @@ function destroy_map(id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function populate_map_markers(map_id, group_radius = 10, status = [0,1], device_group = 0) {
|
||||||
|
$.ajax({
|
||||||
|
type: "GET",
|
||||||
|
url: ajax_url + '/dash/worldmap',
|
||||||
|
dataType: "json",
|
||||||
|
data: { status: status, device_group: device_group },
|
||||||
|
success: function (data) {
|
||||||
|
var redMarker = L.AwesomeMarkers.icon({
|
||||||
|
icon: 'server',
|
||||||
|
markerColor: 'red', prefix: 'fa', iconColor: 'white'
|
||||||
|
});
|
||||||
|
var blueMarker = L.AwesomeMarkers.icon({
|
||||||
|
icon: 'server',
|
||||||
|
markerColor: 'blue', prefix: 'fa', iconColor: 'white'
|
||||||
|
});
|
||||||
|
var greenMarker = L.AwesomeMarkers.icon({
|
||||||
|
icon: 'server',
|
||||||
|
markerColor: 'green', prefix: 'fa', iconColor: 'white'
|
||||||
|
});
|
||||||
|
|
||||||
|
var markers = data.map((device) => {
|
||||||
|
var markerData = {title: device.name};
|
||||||
|
switch (device.status) {
|
||||||
|
case 0: // down
|
||||||
|
markerData.icon = redMarker;
|
||||||
|
markerData.zIndexOffset = 5000;
|
||||||
|
break;
|
||||||
|
case 3: // down + maintenance
|
||||||
|
markerData.icon = blueMarker;
|
||||||
|
markerData.zIndexOffset = 10000;
|
||||||
|
break;
|
||||||
|
default: // up
|
||||||
|
markerData.icon = greenMarker;
|
||||||
|
markerData.zIndexOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var marker = L.marker(new L.LatLng(device.lat, device.lng), markerData);
|
||||||
|
marker.bindPopup(`<a href="${device.url}"><img src="${device.icon}" width="32" height="32" alt=""> ${device.name}</a>`);
|
||||||
|
return marker;
|
||||||
|
});
|
||||||
|
|
||||||
|
var map = get_map(map_id);
|
||||||
|
if (! map.markerCluster) {
|
||||||
|
map.markerCluster = L.markerClusterGroup({
|
||||||
|
maxClusterRadius: group_radius,
|
||||||
|
iconCreateFunction: function (cluster) {
|
||||||
|
var markers = cluster.getAllChildMarkers();
|
||||||
|
var color = "green";
|
||||||
|
var newClass = "Cluster marker-cluster marker-cluster-small leaflet-zoom-animated leaflet-clickable";
|
||||||
|
for (var i = 0; i < markers.length; i++) {
|
||||||
|
if (markers[i].options.icon.options.markerColor == "blue" && color != "red") {
|
||||||
|
color = "blue";
|
||||||
|
}
|
||||||
|
if (markers[i].options.icon.options.markerColor == "red") {
|
||||||
|
color = "red";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return L.divIcon({
|
||||||
|
html: cluster.getChildCount(),
|
||||||
|
className: color + newClass,
|
||||||
|
iconSize: L.point(40, 40)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
map.addLayer(map.markerCluster);
|
||||||
|
}
|
||||||
|
|
||||||
|
map.markerCluster.clearLayers();
|
||||||
|
map.markerCluster.addLayers(markers);
|
||||||
|
},
|
||||||
|
error: function(error){
|
||||||
|
toastr.error(error.statusText);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function disable_map_interaction(leaflet) {
|
function disable_map_interaction(leaflet) {
|
||||||
leaflet.zoomControl?.remove();
|
leaflet.zoomControl?.remove();
|
||||||
delete leaflet.zoomControl;
|
delete leaflet.zoomControl;
|
||||||
|
@@ -763,6 +763,10 @@ return [
|
|||||||
'description' => 'Attempt to Geocode Locations',
|
'description' => 'Attempt to Geocode Locations',
|
||||||
'help' => 'Try to lookup latitude and longitude via geocoding API during polling',
|
'help' => 'Try to lookup latitude and longitude via geocoding API during polling',
|
||||||
],
|
],
|
||||||
|
'layer' => [
|
||||||
|
'description' => 'Initial Map Layer',
|
||||||
|
'help' => 'Initial map layer to display when showing various Geo Maps',
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'graphite' => [
|
'graphite' => [
|
||||||
'enable' => [
|
'enable' => [
|
||||||
|
@@ -1875,6 +1875,26 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"geoloc.layer": {
|
||||||
|
"default": "Streets",
|
||||||
|
"group": "external",
|
||||||
|
"section": "location",
|
||||||
|
"order": 7,
|
||||||
|
"type": "select",
|
||||||
|
"options": {
|
||||||
|
"Streets": "Streets",
|
||||||
|
"Sattelite": "Sattelite"
|
||||||
|
},
|
||||||
|
"when": {
|
||||||
|
"setting": "geoloc.engine",
|
||||||
|
"operator": "in",
|
||||||
|
"value": [
|
||||||
|
"google",
|
||||||
|
"mapquest",
|
||||||
|
"bing"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"github_api": {
|
"github_api": {
|
||||||
"default": "https://api.github.com/repos/librenms/librenms/",
|
"default": "https://api.github.com/repos/librenms/librenms/",
|
||||||
"type": "text"
|
"type": "text"
|
||||||
|
@@ -42,7 +42,7 @@
|
|||||||
<link href="{{ asset('css/query-builder.default.min.css') }}" rel="stylesheet">
|
<link href="{{ asset('css/query-builder.default.min.css') }}" rel="stylesheet">
|
||||||
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
|
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
|
||||||
<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet">
|
<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet">
|
||||||
<link href="{{ asset(LibreNMS\Config::get('stylesheet', 'css/styles.css')) }}?ver=20230928" rel="stylesheet">
|
<link href="{{ asset(LibreNMS\Config::get('stylesheet', 'css/styles.css')) }}?ver=22052024" rel="stylesheet">
|
||||||
<link href="{{ asset('css/' . LibreNMS\Config::get('applied_site_style', 'light') . '.css?ver=632417643') }}" rel="stylesheet">
|
<link href="{{ asset('css/' . LibreNMS\Config::get('applied_site_style', 'light') . '.css?ver=632417643') }}" rel="stylesheet">
|
||||||
@foreach(LibreNMS\Config::get('webui.custom_css', []) as $custom_css)
|
@foreach(LibreNMS\Config::get('webui.custom_css', []) as $custom_css)
|
||||||
<link href="{{ $custom_css }}" rel="stylesheet">
|
<link href="{{ $custom_css }}" rel="stylesheet">
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
});
|
});
|
||||||
var ajax_url = "{{ url('/ajax') }}";
|
var ajax_url = "{{ url('/ajax') }}";
|
||||||
</script>
|
</script>
|
||||||
<script src="{{ asset('js/librenms.js?ver=12052024') }}"></script>
|
<script src="{{ asset('js/librenms.js?ver=22052024') }}"></script>
|
||||||
<script type="text/javascript" src="{{ asset('js/overlib_mini.js') }}"></script>
|
<script type="text/javascript" src="{{ asset('js/overlib_mini.js') }}"></script>
|
||||||
<script type="text/javascript" src="{{ asset('js/flasher.min.js?ver=0.6.1') }}"></script>
|
<script type="text/javascript" src="{{ asset('js/flasher.min.js?ver=0.6.1') }}"></script>
|
||||||
<script type="text/javascript" src="{{ asset('js/toastr.min.js?ver=05072021') }}"></script>
|
<script type="text/javascript" src="{{ asset('js/toastr.min.js?ver=05072021') }}"></script>
|
||||||
|
@@ -322,7 +322,7 @@
|
|||||||
} else {
|
} else {
|
||||||
obj.data('settings','1');
|
obj.data('settings','1');
|
||||||
}
|
}
|
||||||
widget_reload(obj.attr('id'),obj.data('type'));
|
widget_reload(obj.attr('id'), obj.data('type'), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -582,18 +582,14 @@
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function widget_reload(id, data_type, forceDomInject) {
|
function widget_reload(id, data_type, forceDomInject = false) {
|
||||||
const $widget_body = $('#widget_body_' + id);
|
const $widget_body = $('#widget_body_' + id);
|
||||||
const $widget_bootgrid = $('#widget_body_' + id + ' .bootgrid-table');
|
const $widget = $widget_body.children().first();
|
||||||
const settings = $widget_body.parent().data('settings') == 1 ? 1 : 0;
|
|
||||||
|
|
||||||
if (settings === 1 || forceDomInject) {
|
// skip html reload and sned refresh event instead
|
||||||
$widget_bootgrid.bootgrid('destroy');
|
if (!forceDomInject && $widget.data('reload') === false) {
|
||||||
$('#widget_body_' + id + ' *').off();
|
$widget.trigger('refresh', $widget); // send refresh event
|
||||||
} else if ($widget_bootgrid[0] && $widget_bootgrid.data('ajax') === true) {
|
return; // skip html reload
|
||||||
// Check to see if a bootgrid already exists and has ajax reloading enabled.
|
|
||||||
// If so, use bootgrid to refresh the data instead of injecting the DOM in request.
|
|
||||||
return $widget_bootgrid.bootgrid('reload');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@@ -602,11 +598,14 @@
|
|||||||
data: {
|
data: {
|
||||||
id: id,
|
id: id,
|
||||||
dimensions: {x: $widget_body.width(), y: $widget_body.height()},
|
dimensions: {x: $widget_body.width(), y: $widget_body.height()},
|
||||||
settings: settings
|
settings: $widget_body.parent().data('settings') == 1 ? 1 : 0
|
||||||
},
|
},
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
if (data.status === 'ok') {
|
if (data.status === 'ok') {
|
||||||
|
$widget.trigger('destroy', $widget); // send destroy event
|
||||||
|
$widget_body.children().unbind().html("").remove(); // clear old contents and unbind events
|
||||||
|
|
||||||
$('#widget_title_' + id).html(data.title);
|
$('#widget_title_' + id).html(data.title);
|
||||||
$widget_body.html(data.html);
|
$widget_body.html(data.html);
|
||||||
$widget_body.parent().data('settings', data.show_settings).data('refresh', data.settings.refresh);
|
$widget_body.parent().data('settings', data.show_settings).data('refresh', data.settings.refresh);
|
||||||
@@ -621,19 +620,25 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function grab_data(id, data_type) {
|
function grab_data(id, data_type) {
|
||||||
const $parent = $('#widget_body_' + id).parent();
|
const refresh = $('#widget_body_' + id).parent().data('refresh');
|
||||||
|
widget_reload(id, data_type);
|
||||||
if($parent.data('settings') == 0) {
|
|
||||||
widget_reload(id, data_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
grab_data(id, data_type);
|
grab_data(id, data_type);
|
||||||
}, ($parent.data('refresh') > 0 ? $parent.data('refresh') : 60) * 1000);
|
}, (refresh > 0 ? refresh : 60) * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure gridster stays disabled when the window is resized
|
// make sure gridster stays disabled when the window is resized
|
||||||
|
var resizeTrigger = null;
|
||||||
addEvent(window, "resize", function(event) {
|
addEvent(window, "resize", function(event) {
|
||||||
|
// emit resize event, but only once every 100ms
|
||||||
|
if (resizeTrigger === null) {
|
||||||
|
resizeTrigger = setTimeout(() => {
|
||||||
|
resizeTrigger = null;
|
||||||
|
$('.widget_body').children().first().trigger('resize');
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
if(!gridster_state) {
|
if(!gridster_state) {
|
||||||
gridster.disable();
|
gridster.disable();
|
||||||
|
@@ -1,59 +1,64 @@
|
|||||||
<div class="table-responsive">
|
<div id="alertlog_container-{{ $id }}" data-reload="false">
|
||||||
<table id="alertlog_{{ $id }}" class="table table-hover table-condensed alerts" data-ajax="true">
|
<div class="table-responsive">
|
||||||
<thead>
|
<table id="alertlog_{{ $id }}" class="table table-hover table-condensed alerts">
|
||||||
<tr>
|
<thead>
|
||||||
<th data-column-id="status" data-sortable="false"></th>
|
<tr>
|
||||||
<th data-column-id="time_logged" data-order="desc">{{ __('Timestamp') }}</th>
|
<th data-column-id="status" data-sortable="false"></th>
|
||||||
<th data-column-id="details" data-sortable="false"> </th>
|
<th data-column-id="time_logged" data-order="desc">{{ __('Timestamp') }}</th>
|
||||||
<th data-column-id="hostname">{{ __('Device') }}</th>
|
<th data-column-id="details" data-sortable="false"> </th>
|
||||||
<th data-column-id="alert">{{ __('Alert') }}</th>
|
<th data-column-id="hostname">{{ __('Device') }}</th>
|
||||||
</tr>
|
<th data-column-id="alert">{{ __('Alert') }}</th>
|
||||||
</thead>
|
</tr>
|
||||||
</table>
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
var grid = $("#alertlog_{{ $id }}").bootgrid({
|
(function () {
|
||||||
ajax: true,
|
var grid = $("#alertlog_{{ $id }}").bootgrid({
|
||||||
rowCount: [50, 100, 250, -1],
|
ajax: true,
|
||||||
navigation: ! {{ $hidenavigation }},
|
rowCount: [50, 100, 250, -1],
|
||||||
post: function () {
|
navigation: ! {{ $hidenavigation }},
|
||||||
return {
|
post: function () {
|
||||||
id: "alertlog",
|
return {
|
||||||
device_id: "",
|
id: "alertlog",
|
||||||
device_group: "{{ $device_group }}",
|
device_id: "",
|
||||||
state: '{{ $state }}',
|
device_group: "{{ $device_group }}",
|
||||||
min_severity: '{{ $min_severity }}',
|
state: '{{ $state }}',
|
||||||
};
|
min_severity: '{{ $min_severity }}',
|
||||||
},
|
};
|
||||||
url: "ajax_table.php"
|
},
|
||||||
}).on("loaded.rs.jquery.bootgrid", function () {
|
url: "ajax_table.php"
|
||||||
|
}).on("loaded.rs.jquery.bootgrid", function () {
|
||||||
var results = $("div.infos").text().split(" ");
|
grid.find(".incident-toggle").each(function () {
|
||||||
low = results[1] - 1;
|
$(this).parent().addClass('incident-toggle-td');
|
||||||
high = results[3];
|
}).on("click", function (e) {
|
||||||
max = high - low;
|
var target = $(this).data("target");
|
||||||
search = $('.search-field').val();
|
$(target).collapse('toggle');
|
||||||
|
$(this).toggleClass('fa-plus fa-minus');
|
||||||
grid.find(".incident-toggle").each(function () {
|
});
|
||||||
$(this).parent().addClass('incident-toggle-td');
|
grid.find(".incident").each(function () {
|
||||||
}).on("click", function (e) {
|
$(this).parent().addClass('col-lg-4 col-md-4 col-sm-4 col-xs-4');
|
||||||
var target = $(this).data("target");
|
$(this).parent().parent().on("mouseenter", function () {
|
||||||
$(target).collapse('toggle');
|
$(this).find(".incident-toggle").fadeIn(200);
|
||||||
$(this).toggleClass('fa-plus fa-minus');
|
}).on("mouseleave", function () {
|
||||||
});
|
$(this).find(".incident-toggle").fadeOut(200);
|
||||||
grid.find(".incident").each(function () {
|
}).on("click", "td:not(.incident-toggle-td)", function () {
|
||||||
$(this).parent().addClass('col-lg-4 col-md-4 col-sm-4 col-xs-4');
|
var target = $(this).parent().find(".incident-toggle").data("target");
|
||||||
$(this).parent().parent().on("mouseenter", function () {
|
if ($(this).parent().find(".incident-toggle").hasClass('fa-plus')) {
|
||||||
$(this).find(".incident-toggle").fadeIn(200);
|
$(this).parent().find(".incident-toggle").toggleClass('fa-plus fa-minus');
|
||||||
}).on("mouseleave", function () {
|
$(target).collapse('toggle');
|
||||||
$(this).find(".incident-toggle").fadeOut(200);
|
}
|
||||||
}).on("click", "td:not(.incident-toggle-td)", function () {
|
});
|
||||||
var target = $(this).parent().find(".incident-toggle").data("target");
|
|
||||||
if ($(this).parent().find(".incident-toggle").hasClass('fa-plus')) {
|
|
||||||
$(this).parent().find(".incident-toggle").toggleClass('fa-plus fa-minus');
|
|
||||||
$(target).collapse('toggle');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
$('#alertlog_container-{{ $id }}').on('refresh', function (event) {
|
||||||
|
grid.bootgrid('reload');
|
||||||
|
});
|
||||||
|
$('#alertlog_container-{{ $id }}').on('destroy', function (event) {
|
||||||
|
grid.bootgrid('destroy');
|
||||||
|
delete grid;
|
||||||
|
});
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
@@ -1,27 +1,39 @@
|
|||||||
<div class="table-responsive">
|
<div id="alertlog_stats_container-{{ $id }}" data-reload="false">
|
||||||
<table id="alertlog-stats_{{ $id }}" class="table table-hover table-condensed table-striped" data-ajax="true">
|
<div class="table-responsive">
|
||||||
<thead>
|
<table id="alertlog_stats-{{ $id }}" class="table table-hover table-condensed table-striped">
|
||||||
<tr>
|
<thead>
|
||||||
<th data-column-id="count">{{ __('Count') }}</th>
|
<tr>
|
||||||
<th data-column-id="hostname">{{ __('Device') }}</th>
|
<th data-column-id="count">{{ __('Count') }}</th>
|
||||||
<th data-column-id="alert_rule">{{ __('Alert rule') }}</th>
|
<th data-column-id="hostname">{{ __('Device') }}</th>
|
||||||
</tr>
|
<th data-column-id="alert_rule">{{ __('Alert rule') }}</th>
|
||||||
</thead>
|
</tr>
|
||||||
</table>
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
$("#alertlog-stats_{{ $id }}").bootgrid({
|
(function () {
|
||||||
ajax: true,
|
var grid = $("#alertlog_stats-{{ $id }}").bootgrid({
|
||||||
rowCount: [50, 100, 250, -1],
|
ajax: true,
|
||||||
navigation: ! {{ $hidenavigation }},
|
rowCount: [50, 100, 250, -1],
|
||||||
post: function () {
|
navigation: ! {{ $hidenavigation }},
|
||||||
return {
|
post: function () {
|
||||||
id: "alertlog-stats",
|
return {
|
||||||
device_id: "",
|
id: "alertlog-stats",
|
||||||
min_severity: '{{ $min_severity }}',
|
device_id: "",
|
||||||
time_interval: '{{ $time_interval }}'
|
min_severity: '{{ $min_severity }}',
|
||||||
};
|
time_interval: '{{ $time_interval }}'
|
||||||
},
|
};
|
||||||
url: "ajax_table.php"
|
},
|
||||||
});
|
url: "ajax_table.php"
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#alertlog_stats_container-{{ $id }}').on('refresh', function (event) {
|
||||||
|
grid.bootgrid('reload');
|
||||||
|
});
|
||||||
|
$('#alertlog_stats_container-{{ $id }}').on('destroy', function (event) {
|
||||||
|
grid.bootgrid('destroy');
|
||||||
|
delete grid;
|
||||||
|
});
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
@@ -1,75 +1,87 @@
|
|||||||
<div class="table-responsive">
|
<div id="alerts_container-{{ $id }}" data-reload="false">
|
||||||
<table id="alerts_{{ $id }}" class="table table-hover table-condensed alerts" data-ajax="true">
|
<div class="table-responsive">
|
||||||
<thead>
|
<table id="alerts-{{ $id }}" class="table table-hover table-condensed alerts">
|
||||||
<tr>
|
<thead>
|
||||||
<th data-column-id="severity"></th>
|
<tr>
|
||||||
<th data-column-id="timestamp">{{ __('Timestamp') }}</th>
|
<th data-column-id="severity"></th>
|
||||||
<th data-column-id="rule">{{ __('Rule') }}</th>
|
<th data-column-id="timestamp">{{ __('Timestamp') }}</th>
|
||||||
<th data-column-id="details" data-sortable="false"></th>
|
<th data-column-id="rule">{{ __('Rule') }}</th>
|
||||||
<th data-column-id="hostname">{{ __('Hostname') }}</th>
|
<th data-column-id="details" data-sortable="false"></th>
|
||||||
<th data-column-id="location" data-visible="{{ $location ? 'true' : 'false' }}">{{ __('Location') }}</th>
|
<th data-column-id="hostname">{{ __('Hostname') }}</th>
|
||||||
<th data-column-id="ack_ico" data-sortable="false">{{ __('ACK') }}</th>
|
<th data-column-id="location" data-visible="{{ $location ? 'true' : 'false' }}">{{ __('Location') }}</th>
|
||||||
<th data-column-id="notes" data-sortable="false">{{ __('Notes') }}</th>
|
<th data-column-id="ack_ico" data-sortable="false">{{ __('ACK') }}</th>
|
||||||
<th data-column-id="proc" data-sortable="false" data-visible="{{ $proc ? 'true' : 'false' }}">URL</th>
|
<th data-column-id="notes" data-sortable="false">{{ __('Notes') }}</th>
|
||||||
</tr>
|
<th data-column-id="proc" data-sortable="false" data-visible="{{ $proc ? 'true' : 'false' }}">URL</th>
|
||||||
</thead>
|
</tr>
|
||||||
</table>
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
var alerts_grid = $("#alerts_{{ $id }}").bootgrid({
|
(function () {
|
||||||
ajax: true,
|
var alerts_grid = $("#alerts-{{ $id }}").bootgrid({
|
||||||
requestHandler: request => ({
|
ajax: true,
|
||||||
...request,
|
requestHandler: request => ({
|
||||||
id: "alerts",
|
...request,
|
||||||
acknowledged: '{{ $acknowledged }}',
|
id: "alerts",
|
||||||
unreachable: '{{ $unreachable }}',
|
acknowledged: '{{ $acknowledged }}',
|
||||||
fired: '{{ $fired }}',
|
unreachable: '{{ $unreachable }}',
|
||||||
min_severity: '{{ $min_severity }}',
|
fired: '{{ $fired }}',
|
||||||
group: '{{ $device_group }}',
|
min_severity: '{{ $min_severity }}',
|
||||||
proc: '{{ $proc }}',
|
group: '{{ $device_group }}',
|
||||||
sort: '{{ $sort }}',
|
proc: '{{ $proc }}',
|
||||||
uncollapse_key_count: '{{ $uncollapse_key_count }}',
|
sort: '{{ $sort }}',
|
||||||
device_id: '{{ $device }}'
|
uncollapse_key_count: '{{ $uncollapse_key_count }}',
|
||||||
}),
|
device_id: '{{ $device }}'
|
||||||
responseHandler: response => {
|
}),
|
||||||
$("#widget_title_counter_{{ $id }}").text(response.total ? ` (${response.total})` : '')
|
responseHandler: response => {
|
||||||
|
$("#widget_title_counter_{{ $id }}").text(response.total ? ` (${response.total})` : '')
|
||||||
|
|
||||||
return response
|
return response
|
||||||
},
|
},
|
||||||
url: "ajax_table.php",
|
url: "ajax_table.php",
|
||||||
navigation: ! {{ $hidenavigation }},
|
navigation: ! {{ $hidenavigation }},
|
||||||
rowCount: [50, 100, 250, -1]
|
rowCount: [50, 100, 250, -1]
|
||||||
}).on("loaded.rs.jquery.bootgrid", function() {
|
}).on("loaded.rs.jquery.bootgrid", function() {
|
||||||
alerts_grid = $(this);
|
alerts_grid = $(this);
|
||||||
alerts_grid.find(".incident-toggle").each( function() {
|
alerts_grid.find(".incident-toggle").each( function() {
|
||||||
$(this).parent().addClass('incident-toggle-td');
|
$(this).parent().addClass('incident-toggle-td');
|
||||||
}).on("click", function(e) {
|
}).on("click", function(e) {
|
||||||
var target = $(this).data("target");
|
var target = $(this).data("target");
|
||||||
$(target).collapse('toggle');
|
$(target).collapse('toggle');
|
||||||
$(this).toggleClass('fa-plus fa-minus');
|
$(this).toggleClass('fa-plus fa-minus');
|
||||||
});
|
});
|
||||||
alerts_grid.find(".incident").each( function() {
|
alerts_grid.find(".incident").each( function() {
|
||||||
$(this).parent().addClass('col-lg-4 col-md-4 col-sm-4 col-xs-4');
|
$(this).parent().addClass('col-lg-4 col-md-4 col-sm-4 col-xs-4');
|
||||||
$(this).parent().parent().on("mouseenter", function() {
|
$(this).parent().parent().on("mouseenter", function() {
|
||||||
$(this).find(".incident-toggle").fadeIn(200);
|
$(this).find(".incident-toggle").fadeIn(200);
|
||||||
}).on("mouseleave", function() {
|
}).on("mouseleave", function() {
|
||||||
$(this).find(".incident-toggle").fadeOut(200);
|
$(this).find(".incident-toggle").fadeOut(200);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
alerts_grid.find(".command-ack-alert").on("click", function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var alert_state = $(this).data("alert_state");
|
||||||
|
var alert_id = $(this).data('alert_id');
|
||||||
|
$('#ack_alert_id').val(alert_id);
|
||||||
|
$('#ack_alert_state').val(alert_state);
|
||||||
|
$('#ack_msg').val('');
|
||||||
|
$("#alert_ack_modal").modal('show');
|
||||||
|
});
|
||||||
|
alerts_grid.find(".command-alert-note").on("click", function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var alert_id = $(this).data('alert_id');
|
||||||
|
$('#alert_id').val(alert_id);
|
||||||
|
$("#alert_notes_modal").modal('show');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
alerts_grid.find(".command-ack-alert").on("click", function(e) {
|
|
||||||
e.preventDefault();
|
$('#alerts_container-{{ $id }}').on('refresh', function (event) {
|
||||||
var alert_state = $(this).data("alert_state");
|
alerts_grid.bootgrid('reload');
|
||||||
var alert_id = $(this).data('alert_id');
|
|
||||||
$('#ack_alert_id').val(alert_id);
|
|
||||||
$('#ack_alert_state').val(alert_state);
|
|
||||||
$('#ack_msg').val('');
|
|
||||||
$("#alert_ack_modal").modal('show');
|
|
||||||
});
|
});
|
||||||
alerts_grid.find(".command-alert-note").on("click", function(e) {
|
$('#alerts_container-{{ $id }}').on('destroy', function (event) {
|
||||||
e.preventDefault();
|
alerts_grid.bootgrid('destroy');
|
||||||
var alert_id = $(this).data('alert_id');
|
delete alerts_grid;
|
||||||
$('#alert_id').val(alert_id);
|
|
||||||
$("#alert_notes_modal").modal('show');
|
|
||||||
});
|
});
|
||||||
});
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
@@ -1,29 +1,41 @@
|
|||||||
<div class="table-responsive">
|
<div id="eventlog_container-{{ $id }}" data-reload="false">
|
||||||
<table id="eventlog" class="table table-hover table-condensed table-striped" data-ajax="true">
|
<div class="table-responsive">
|
||||||
<thead>
|
<table id="eventlog-{{ $id }}" class="table table-hover table-condensed table-striped">
|
||||||
<tr>
|
<thead>
|
||||||
<th data-column-id="datetime" data-order="desc">{{ __('Timestamp') }}</th>
|
<tr>
|
||||||
<th data-column-id="type">{{ __('Type') }}</th>
|
<th data-column-id="datetime" data-order="desc">{{ __('Timestamp') }}</th>
|
||||||
<th data-column-id="device_id">{{ __('Hostname') }}</th>
|
<th data-column-id="type">{{ __('Type') }}</th>
|
||||||
<th data-column-id="message">{{ __('Message') }}</th>
|
<th data-column-id="device_id">{{ __('Hostname') }}</th>
|
||||||
<th data-column-id="username">{{ __('User') }}</th>
|
<th data-column-id="message">{{ __('Message') }}</th>
|
||||||
</tr>
|
<th data-column-id="username">{{ __('User') }}</th>
|
||||||
</thead>
|
</tr>
|
||||||
</table>
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
$("#eventlog").bootgrid({
|
$(function () {
|
||||||
ajax: true,
|
var grid = $("#eventlog-{{ $id }}").bootgrid({
|
||||||
rowCount: [50, 100, 250, -1],
|
ajax: true,
|
||||||
navigation: ! {{ $hidenavigation }},
|
rowCount: [50, 100, 250, -1],
|
||||||
post: function ()
|
navigation: ! {{ $hidenavigation }},
|
||||||
{
|
post: function ()
|
||||||
return {
|
{
|
||||||
device: "{{ $device }}",
|
return {
|
||||||
device_group: "{{ $device_group }}",
|
device: "{{ $device }}",
|
||||||
eventtype: "{{ $eventtype }}"
|
device_group: "{{ $device_group }}",
|
||||||
};
|
eventtype: "{{ $eventtype }}"
|
||||||
},
|
};
|
||||||
url: "{{ url('/ajax/table/eventlog') }}"
|
},
|
||||||
|
url: "{{ url('/ajax/table/eventlog') }}"
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#eventlog_container-{{ $id }}').on('refresh', function (event) {
|
||||||
|
grid.bootgrid('reload');
|
||||||
|
});
|
||||||
|
$('#eventlog_container-{{ $id }}').on('destroy', function (event) {
|
||||||
|
grid.bootgrid('destroy');
|
||||||
|
delete grid;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@@ -1,42 +1,54 @@
|
|||||||
<div class="table-responsive">
|
<div id="graylog_container-{{ $id }}" data-reload="false">
|
||||||
<table id="graylog-{{ $id }}" class="table table-hover table-condensed graylog" data-ajax="true">
|
<div class="table-responsive">
|
||||||
<thead>
|
<table id="graylog-{{ $id }}" class="table table-hover table-condensed graylog">
|
||||||
<tr>
|
<thead>
|
||||||
<th data-column-id="severity" data-sortable="false"></th>
|
<tr>
|
||||||
<th data-column-id="origin">{{ __('Origin') }}</th>
|
<th data-column-id="severity" data-sortable="false"></th>
|
||||||
<th data-column-id="timestamp" data-formatter="browserTime">{{ __('Timestamp') }}</th>
|
<th data-column-id="origin">{{ __('Origin') }}</th>
|
||||||
<th data-column-id="level" data-sortable="false">{{ __('Level') }}</th>
|
<th data-column-id="timestamp" data-formatter="browserTime">{{ __('Timestamp') }}</th>
|
||||||
<th data-column-id="source">{{ __('Source') }}</th>
|
<th data-column-id="level" data-sortable="false">{{ __('Level') }}</th>
|
||||||
<th data-column-id="message" data-sortable="false">{{ __('Message') }}</th>
|
<th data-column-id="source">{{ __('Source') }}</th>
|
||||||
<th data-column-id="facility" data-sortable="false">{{ __('Facility') }}</th>
|
<th data-column-id="message" data-sortable="false">{{ __('Message') }}</th>
|
||||||
</tr>
|
<th data-column-id="facility" data-sortable="false">{{ __('Facility') }}</th>
|
||||||
</thead>
|
</tr>
|
||||||
</table>
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
$("#graylog-{{ $id }}").bootgrid({
|
(function () {
|
||||||
ajax: true,
|
var grid = $("#graylog-{{ $id }}").bootgrid({
|
||||||
rowCount: ['{{ $limit }}', 25,50,100,250,-1],
|
ajax: true,
|
||||||
navigation: ! {{ $hidenavigation }},
|
rowCount: ['{{ $limit }}', 25,50,100,250,-1],
|
||||||
formatters: {
|
navigation: ! {{ $hidenavigation }},
|
||||||
"browserTime": function(column, row) {
|
formatters: {
|
||||||
@config('graylog.timezone')
|
"browserTime": function(column, row) {
|
||||||
return row.timestamp;
|
@config('graylog.timezone')
|
||||||
@else
|
return row.timestamp;
|
||||||
return moment.parseZone(row.timestamp).local().format("YYYY-MM-DD HH:MM:SS");
|
@else
|
||||||
@endconfig
|
return moment.parseZone(row.timestamp).local().format("YYYY-MM-DD HH:MM:SS");
|
||||||
}
|
@endconfig
|
||||||
},
|
}
|
||||||
post: function ()
|
},
|
||||||
{
|
post: function ()
|
||||||
return {
|
{
|
||||||
stream: "{{ $stream }}",
|
return {
|
||||||
device: "{{ $device }}",
|
stream: "{{ $stream }}",
|
||||||
range: "{{ $range }}",
|
device: "{{ $device }}",
|
||||||
loglevel: "{{ $loglevel }}"
|
range: "{{ $range }}",
|
||||||
};
|
loglevel: "{{ $loglevel }}"
|
||||||
},
|
};
|
||||||
url: "{{ url('/ajax/table/graylog') }}"
|
},
|
||||||
});
|
url: "{{ url('/ajax/table/graylog') }}"
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#graylog_container-{{ $id }}').on('refresh', function (event) {
|
||||||
|
grid.bootgrid('reload');
|
||||||
|
});
|
||||||
|
$('#graylog_container-{{ $id }}').on('destroy', function (event) {
|
||||||
|
grid.bootgrid('destroy');
|
||||||
|
delete grid;
|
||||||
|
});
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<form role="form" class="dashboard-widget-settings" onsubmit="widget_settings(this); return false;">
|
<form role="form" class="dashboard-widget-settings" onsubmit="widget_settings(this); return false;" data-reload="false">
|
||||||
@csrf
|
@csrf
|
||||||
@yield('form')
|
@yield('form')
|
||||||
|
|
||||||
|
@@ -22,6 +22,14 @@
|
|||||||
<input class="form-control" name="init_zoom" id="init_zoom-{{ $id }}" type="number" min="0" max="18" step="0.1" value="{{ $init_zoom }}" placeholder="{{ __('ie. 5.8') }}">
|
<input class="form-control" name="init_zoom" id="init_zoom-{{ $id }}" type="number" min="0" max="18" step="0.1" value="{{ $init_zoom }}" placeholder="{{ __('ie. 5.8') }}">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="init_layer-{{ $id }}" class="control-label">{{ __('Initial Layer') }}</label>
|
||||||
|
<select class="form-control" name="init_layer" id="init_layer-{{ $id }}">
|
||||||
|
<option value="Streets" @if($init_layer == 'Streets') selected @endif>{{ __('Streets') }}</option>
|
||||||
|
<option value="Satellite" @if($init_layer == 'Satellite') selected @endif>{{ __('Satellite') }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="group_radius-{{ $id }}" class="control-label">{{ __('Grouping radius') }}</label>
|
<label for="group_radius-{{ $id }}" class="control-label">{{ __('Grouping radius') }}</label>
|
||||||
<input class="form-control" name="group_radius" id="group_radius-{{ $id }}" type="number" value="{{ $group_radius }}" placeholder="{{ __('default 80') }}">
|
<input class="form-control" name="group_radius" id="group_radius-{{ $id }}" type="number" value="{{ $group_radius }}" placeholder="{{ __('default 80') }}">
|
||||||
|
@@ -1,31 +1,43 @@
|
|||||||
<div class="table-responsive">
|
<div id="syslog_container-{{ $id }}" data-reload="false">
|
||||||
<table id="syslog" class="table table-hover table-condensed table-striped" data-ajax="true">
|
<div class="table-responsive">
|
||||||
<thead>
|
<table id="syslog-{{ $id }}" class="table table-hover table-condensed table-striped">
|
||||||
<tr>
|
<thead>
|
||||||
<th data-column-id="label"></th>
|
<tr>
|
||||||
<th data-column-id="timestamp" data-order="desc">{{ __('Timestamp') }}</th>
|
<th data-column-id="label"></th>
|
||||||
<th data-column-id="level">{{ __('Level') }}</th>
|
<th data-column-id="timestamp" data-order="desc">{{ __('Timestamp') }}</th>
|
||||||
<th data-column-id="device_id">{{ __('Hostname') }}</th>
|
<th data-column-id="level">{{ __('Level') }}</th>
|
||||||
<th data-column-id="program">{{ __('Program') }}</th>
|
<th data-column-id="device_id">{{ __('Hostname') }}</th>
|
||||||
<th data-column-id="msg">{{ __('Message') }}</th>
|
<th data-column-id="program">{{ __('Program') }}</th>
|
||||||
<th data-column-id="priority">{{ __('Priority') }}</th>
|
<th data-column-id="msg">{{ __('Message') }}</th>
|
||||||
</tr>
|
<th data-column-id="priority">{{ __('Priority') }}</th>
|
||||||
</thead>
|
</tr>
|
||||||
</table>
|
</thead>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
$("#syslog").bootgrid({
|
(function () {
|
||||||
ajax: true,
|
var grid = $("#syslog-{{ $id }}").bootgrid({
|
||||||
rowCount: [50, 100, 250, -1],
|
ajax: true,
|
||||||
navigation: ! {{ $hidenavigation }},
|
rowCount: [50, 100, 250, -1],
|
||||||
post: function ()
|
navigation: ! {{ $hidenavigation }},
|
||||||
{
|
post: function ()
|
||||||
return {
|
{
|
||||||
device: '{{ $device ?: '' }}',
|
return {
|
||||||
device_group: '{{ $device_group }}',
|
device: '{{ $device ?: '' }}',
|
||||||
level: '{{ $level }}'
|
device_group: '{{ $device_group }}',
|
||||||
};
|
level: '{{ $level }}'
|
||||||
},
|
};
|
||||||
url: "{{ url('/ajax/table/syslog') }}"
|
},
|
||||||
});
|
url: "{{ url('/ajax/table/syslog') }}"
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#syslog_container-{{ $id }}').on('refresh', function (event) {
|
||||||
|
grid.bootgrid('reload');
|
||||||
|
});
|
||||||
|
$('#syslog_container-{{ $id }}').on('destroy', function (event) {
|
||||||
|
grid.bootgrid('destroy');
|
||||||
|
delete grid;
|
||||||
|
});
|
||||||
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
@@ -1,63 +1,36 @@
|
|||||||
<div id="leaflet-map-{{ $id }}" style="width: {{ $dimensions['x'] }}px; height: {{ $dimensions['y'] }}px;"></div>
|
<div id="worldmap_widget-{{ $id }}" class="worldmap_widget" data-reload="false"></div>
|
||||||
|
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
loadjs('js/leaflet.js', function() {
|
(function () {
|
||||||
loadjs('js/leaflet.markercluster.js', function () {
|
const map_id = 'worldmap_widget-{{ $id }}';
|
||||||
loadjs('js/leaflet.awesome-markers.min.js', function () {
|
const status = {{ Js::from($status) }};
|
||||||
var map = L.map('leaflet-map-{{ $id }}', { zoomSnap: 0.1 } ).setView(['{{ $init_lat }}', '{{ $init_lng }}'], '{{ sprintf('%01.1f', $init_zoom) }}');
|
const device_group = {{ (int) $device_group }};
|
||||||
L.tileLayer('//{{ $title_url }}/{z}/{x}/{y}.png', {
|
const map_config = {{ Js::from($map_config) }};
|
||||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
const group_radius = {{ (int) $group_radius }};
|
||||||
}).addTo(map);
|
|
||||||
|
|
||||||
var markers = L.markerClusterGroup({
|
loadjs('js/leaflet.js', function () {
|
||||||
maxClusterRadius: '{{ $group_radius }}',
|
loadjs('js/leaflet.markercluster.js', function () {
|
||||||
iconCreateFunction: function (cluster) {
|
loadjs('js/leaflet.awesome-markers.min.js', function () {
|
||||||
var markers = cluster.getAllChildMarkers();
|
loadjs('js/L.Control.Locate.min.js', function () {
|
||||||
var color = "green";
|
init_map(map_id, map_config).scrollWheelZoom.disable();
|
||||||
var newClass = "Cluster marker-cluster marker-cluster-small leaflet-zoom-animated leaflet-clickable";
|
populate_map_markers(map_id, group_radius, status, device_group);
|
||||||
for (var i = 0; i < markers.length; i++) {
|
|
||||||
if (markers[i].options.icon.options.markerColor == "blue" && color != "red") {
|
|
||||||
color = "blue";
|
|
||||||
}
|
|
||||||
if (markers[i].options.icon.options.markerColor == "red") {
|
|
||||||
color = "red";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return L.divIcon({ html: cluster.getChildCount(), className: color+newClass, iconSize: L.point(40, 40) });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var redMarker = L.AwesomeMarkers.icon({
|
|
||||||
icon: 'server',
|
|
||||||
markerColor: 'red', prefix: 'fa', iconColor: 'white'
|
|
||||||
});
|
|
||||||
var blueMarker = L.AwesomeMarkers.icon({
|
|
||||||
icon: 'server',
|
|
||||||
markerColor: 'blue', prefix: 'fa', iconColor: 'white'
|
|
||||||
});
|
|
||||||
var greenMarker = L.AwesomeMarkers.icon({
|
|
||||||
icon: 'server',
|
|
||||||
markerColor: 'green', prefix: 'fa', iconColor: 'white'
|
|
||||||
});
|
|
||||||
|
|
||||||
@foreach($devices as $device)
|
// register listeners
|
||||||
@if($status != '0' or !$device->isUnderMaintenance())
|
$('#' + map_id).on('click', function (event) {
|
||||||
var title = '<a href="@deviceUrl($device)"><img src="{{ $device->icon }}" width="32" height="32" alt=""> {{ $device->displayName() }}</a>';
|
get_map(map_id).scrollWheelZoom.enable();
|
||||||
var tooltip = '{{ $device->displayName() }}';
|
}).on('mouseleave', function (event) {
|
||||||
var marker = L.marker(new L.LatLng('{{ $device->location->lat }}', '{{ $device->location->lng }}'), {title: tooltip, icon: {{ $device->markerIcon }}, zIndexOffset: {{ $device->zOffset }}});
|
get_map(map_id).scrollWheelZoom.disable();
|
||||||
marker.bindPopup(title);
|
}).on('resize', function (event) {
|
||||||
markers.addLayer(marker);
|
get_map(map_id).invalidateSize();
|
||||||
@endif
|
}).on('refresh', function (event) {
|
||||||
@endforeach
|
get_map(map_id).invalidateSize();
|
||||||
|
populate_map_markers(map_id, group_radius, status, device_group);
|
||||||
map.addLayer(markers);
|
}).on('destroy', function (event) {
|
||||||
map.scrollWheelZoom.disable();
|
destroy_map(map_id);
|
||||||
$(document).ready(function() {
|
});
|
||||||
$("#leaflet-map-{{ $id }}").on("click", function (event) {
|
});
|
||||||
map.scrollWheelZoom.enable();
|
});
|
||||||
}).on("mouseleave", function (event) {
|
|
||||||
map.scrollWheelZoom.disable();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
})();
|
||||||
});});});
|
|
||||||
</script>
|
</script>
|
||||||
|
@@ -237,7 +237,8 @@ Route::middleware(['auth'])->group(function () {
|
|||||||
Route::post('top-devices', 'TopDevicesController');
|
Route::post('top-devices', 'TopDevicesController');
|
||||||
Route::post('top-interfaces', 'TopInterfacesController');
|
Route::post('top-interfaces', 'TopInterfacesController');
|
||||||
Route::post('top-errors', 'TopErrorsController');
|
Route::post('top-errors', 'TopErrorsController');
|
||||||
Route::post('worldmap', 'WorldMapController');
|
Route::post('worldmap', 'WorldMapController')->name('widget.worldmap');
|
||||||
|
Route::get('worldmap', 'WorldMapController@getData')->name('widget.worldmap.data');
|
||||||
Route::post('alertlog-stats', 'AlertlogStatsController');
|
Route::post('alertlog-stats', 'AlertlogStatsController');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user