mirror of
https://github.com/librenms/librenms.git
synced 2024-09-21 10:28:13 +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:
parent
df6a42f2a3
commit
f0966f4d23
@ -26,8 +26,10 @@
|
||||
namespace App\Http\Controllers\Widgets;
|
||||
|
||||
use App\Models\Device;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use LibreNMS\Config;
|
||||
use LibreNMS\Util\Url;
|
||||
|
||||
class WorldMapController extends WidgetController
|
||||
{
|
||||
@ -37,11 +39,11 @@ class WorldMapController extends WidgetController
|
||||
{
|
||||
$this->defaults = [
|
||||
'title' => null,
|
||||
'title_url' => Config::get('leaflet.tile_url', '{s}.tile.openstreetmap.org'),
|
||||
'init_lat' => Config::get('leaflet.default_lat', 51.4800),
|
||||
'init_lng' => Config::get('leaflet.default_lng', 0),
|
||||
'init_zoom' => Config::get('leaflet.default_zoom', 2),
|
||||
'group_radius' => Config::get('leaflet.group_radius', 80),
|
||||
'init_lat' => Config::get('leaflet.default_lat'),
|
||||
'init_lng' => Config::get('leaflet.default_lng'),
|
||||
'init_zoom' => Config::get('leaflet.default_zoom'),
|
||||
'init_layer' => Config::get('geoloc.layer'),
|
||||
'group_radius' => Config::get('leaflet.group_radius'),
|
||||
'status' => '0,1',
|
||||
'device_group' => null,
|
||||
];
|
||||
@ -50,17 +52,39 @@ class WorldMapController extends WidgetController
|
||||
public function getView(Request $request)
|
||||
{
|
||||
$settings = $this->getSettings();
|
||||
$status = explode(',', $settings['status']);
|
||||
|
||||
$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')
|
||||
->isActive()
|
||||
->whereIn('status', $status)
|
||||
->when($settings['device_group'], function ($query) use ($settings) {
|
||||
$query->inDeviceGroup($settings['device_group']);
|
||||
})
|
||||
->when($device_group_id, fn ($q) => $q->inDeviceGroup($device_group_id))
|
||||
->get()
|
||||
->filter(function ($device) use ($status) {
|
||||
/** @var Device $device */
|
||||
@ -68,31 +92,23 @@ class WorldMapController extends WidgetController
|
||||
return false;
|
||||
}
|
||||
|
||||
// add extra data
|
||||
/** @phpstan-ignore-next-line */
|
||||
$device->markerIcon = 'greenMarker';
|
||||
/** @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;
|
||||
}
|
||||
// hide devices under maintenance if only showing down devices
|
||||
if ($status == [0] && $device->isUnderMaintenance()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
$settings['devices'] = $devices;
|
||||
|
||||
return view('widgets.worldmap', $settings);
|
||||
})->map(function (Device $device) {
|
||||
return [
|
||||
'name' => $device->displayName(),
|
||||
'lat' => $device->location->lat,
|
||||
'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)
|
||||
|
@ -47,6 +47,7 @@
|
||||
'path' => storage_path('debugbar'), // For file driver
|
||||
'connection' => null, // Leave null for default connection (Redis/PDO)
|
||||
'provider' => '', // Instance of StorageInterface for custom driver
|
||||
'open' => true,
|
||||
],
|
||||
|
||||
/*
|
||||
|
@ -1776,10 +1776,8 @@ tr.search:nth-child(odd) {
|
||||
background-color: #000000;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
-webkit-border-top-left-radius: 4px;
|
||||
-moz-border-top-right-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
|
||||
.mapTooltip {
|
||||
@ -1966,10 +1964,12 @@ label {
|
||||
.edit-widget, .close-widget { cursor: pointer; }
|
||||
.widget_body {
|
||||
padding: 0.8em;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
width: 100%;
|
||||
height: calc(100% - 38px);
|
||||
height: calc(100% - 2.6em);
|
||||
cursor: auto;
|
||||
text-align: center;
|
||||
}
|
||||
@ -2016,6 +2016,20 @@ label {
|
||||
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 {
|
||||
color:#5CB85C;
|
||||
}
|
||||
|
@ -303,6 +303,7 @@ function init_map(id, config = {}) {
|
||||
let baseMaps = {};
|
||||
|
||||
if (config.engine === 'google' && config.api_key) {
|
||||
leaflet.setMaxZoom(21);
|
||||
loadjs('https://maps.googleapis.com/maps/api/js?key=' + config.api_key, function () {
|
||||
loadjs('js/Leaflet.GoogleMutant.js', function () {
|
||||
const roads = L.gridLayer.googleMutant({
|
||||
@ -322,6 +323,7 @@ function init_map(id, config = {}) {
|
||||
});
|
||||
});
|
||||
} else if (config.engine === 'bing' && config.api_key) {
|
||||
leaflet.setMaxZoom(18);
|
||||
loadjs('js/leaflet-bing-layer.min.js', function () {
|
||||
const roads = L.tileLayer.bing({
|
||||
bingMapsKey: config.api_key,
|
||||
@ -341,6 +343,7 @@ function init_map(id, config = {}) {
|
||||
leaflet.layerControl._container.style.display = (config.readonly ? 'none' : 'block');
|
||||
});
|
||||
} 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 () {
|
||||
const roads = MQ.mapLayer();
|
||||
const satellite = MQ.hybridLayer();
|
||||
@ -354,22 +357,12 @@ function init_map(id, config = {}) {
|
||||
leaflet.layerControl._container.style.display = (config.readonly ? 'none' : 'block');
|
||||
});
|
||||
} else {
|
||||
leaflet.setMaxZoom(20);
|
||||
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,
|
||||
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
});
|
||||
|
||||
// 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);
|
||||
}).addTo(leaflet);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
leaflet.zoomControl?.remove();
|
||||
delete leaflet.zoomControl;
|
||||
|
@ -763,6 +763,10 @@ return [
|
||||
'description' => 'Attempt to Geocode Locations',
|
||||
'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' => [
|
||||
'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": {
|
||||
"default": "https://api.github.com/repos/librenms/librenms/",
|
||||
"type": "text"
|
||||
|
@ -42,7 +42,7 @@
|
||||
<link href="{{ asset('css/query-builder.default.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('css/app.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">
|
||||
@foreach(LibreNMS\Config::get('webui.custom_css', []) as $custom_css)
|
||||
<link href="{{ $custom_css }}" rel="stylesheet">
|
||||
@ -76,7 +76,7 @@
|
||||
});
|
||||
var ajax_url = "{{ url('/ajax') }}";
|
||||
</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/flasher.min.js?ver=0.6.1') }}"></script>
|
||||
<script type="text/javascript" src="{{ asset('js/toastr.min.js?ver=05072021') }}"></script>
|
||||
|
@ -322,7 +322,7 @@
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
function widget_reload(id, data_type, forceDomInject) {
|
||||
function widget_reload(id, data_type, forceDomInject = false) {
|
||||
const $widget_body = $('#widget_body_' + id);
|
||||
const $widget_bootgrid = $('#widget_body_' + id + ' .bootgrid-table');
|
||||
const settings = $widget_body.parent().data('settings') == 1 ? 1 : 0;
|
||||
const $widget = $widget_body.children().first();
|
||||
|
||||
if (settings === 1 || forceDomInject) {
|
||||
$widget_bootgrid.bootgrid('destroy');
|
||||
$('#widget_body_' + id + ' *').off();
|
||||
} else if ($widget_bootgrid[0] && $widget_bootgrid.data('ajax') === true) {
|
||||
// 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');
|
||||
// skip html reload and sned refresh event instead
|
||||
if (!forceDomInject && $widget.data('reload') === false) {
|
||||
$widget.trigger('refresh', $widget); // send refresh event
|
||||
return; // skip html reload
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
@ -602,11 +598,14 @@
|
||||
data: {
|
||||
id: id,
|
||||
dimensions: {x: $widget_body.width(), y: $widget_body.height()},
|
||||
settings: settings
|
||||
settings: $widget_body.parent().data('settings') == 1 ? 1 : 0
|
||||
},
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
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_body.html(data.html);
|
||||
$widget_body.parent().data('settings', data.show_settings).data('refresh', data.settings.refresh);
|
||||
@ -621,19 +620,25 @@
|
||||
}
|
||||
|
||||
function grab_data(id, data_type) {
|
||||
const $parent = $('#widget_body_' + id).parent();
|
||||
|
||||
if($parent.data('settings') == 0) {
|
||||
widget_reload(id, data_type);
|
||||
}
|
||||
const refresh = $('#widget_body_' + id).parent().data('refresh');
|
||||
widget_reload(id, data_type);
|
||||
|
||||
setTimeout(function () {
|
||||
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
|
||||
var resizeTrigger = null;
|
||||
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(){
|
||||
if(!gridster_state) {
|
||||
gridster.disable();
|
||||
|
@ -1,59 +1,64 @@
|
||||
<div class="table-responsive">
|
||||
<table id="alertlog_{{ $id }}" class="table table-hover table-condensed alerts" data-ajax="true">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="status" data-sortable="false"></th>
|
||||
<th data-column-id="time_logged" data-order="desc">{{ __('Timestamp') }}</th>
|
||||
<th data-column-id="details" data-sortable="false"> </th>
|
||||
<th data-column-id="hostname">{{ __('Device') }}</th>
|
||||
<th data-column-id="alert">{{ __('Alert') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<div id="alertlog_container-{{ $id }}" data-reload="false">
|
||||
<div class="table-responsive">
|
||||
<table id="alertlog_{{ $id }}" class="table table-hover table-condensed alerts">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="status" data-sortable="false"></th>
|
||||
<th data-column-id="time_logged" data-order="desc">{{ __('Timestamp') }}</th>
|
||||
<th data-column-id="details" data-sortable="false"> </th>
|
||||
<th data-column-id="hostname">{{ __('Device') }}</th>
|
||||
<th data-column-id="alert">{{ __('Alert') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var grid = $("#alertlog_{{ $id }}").bootgrid({
|
||||
ajax: true,
|
||||
rowCount: [50, 100, 250, -1],
|
||||
navigation: ! {{ $hidenavigation }},
|
||||
post: function () {
|
||||
return {
|
||||
id: "alertlog",
|
||||
device_id: "",
|
||||
device_group: "{{ $device_group }}",
|
||||
state: '{{ $state }}',
|
||||
min_severity: '{{ $min_severity }}',
|
||||
};
|
||||
},
|
||||
url: "ajax_table.php"
|
||||
}).on("loaded.rs.jquery.bootgrid", function () {
|
||||
|
||||
var results = $("div.infos").text().split(" ");
|
||||
low = results[1] - 1;
|
||||
high = results[3];
|
||||
max = high - low;
|
||||
search = $('.search-field').val();
|
||||
|
||||
grid.find(".incident-toggle").each(function () {
|
||||
$(this).parent().addClass('incident-toggle-td');
|
||||
}).on("click", function (e) {
|
||||
var target = $(this).data("target");
|
||||
$(target).collapse('toggle');
|
||||
$(this).toggleClass('fa-plus fa-minus');
|
||||
});
|
||||
grid.find(".incident").each(function () {
|
||||
$(this).parent().addClass('col-lg-4 col-md-4 col-sm-4 col-xs-4');
|
||||
$(this).parent().parent().on("mouseenter", function () {
|
||||
$(this).find(".incident-toggle").fadeIn(200);
|
||||
}).on("mouseleave", function () {
|
||||
$(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');
|
||||
}
|
||||
(function () {
|
||||
var grid = $("#alertlog_{{ $id }}").bootgrid({
|
||||
ajax: true,
|
||||
rowCount: [50, 100, 250, -1],
|
||||
navigation: ! {{ $hidenavigation }},
|
||||
post: function () {
|
||||
return {
|
||||
id: "alertlog",
|
||||
device_id: "",
|
||||
device_group: "{{ $device_group }}",
|
||||
state: '{{ $state }}',
|
||||
min_severity: '{{ $min_severity }}',
|
||||
};
|
||||
},
|
||||
url: "ajax_table.php"
|
||||
}).on("loaded.rs.jquery.bootgrid", function () {
|
||||
grid.find(".incident-toggle").each(function () {
|
||||
$(this).parent().addClass('incident-toggle-td');
|
||||
}).on("click", function (e) {
|
||||
var target = $(this).data("target");
|
||||
$(target).collapse('toggle');
|
||||
$(this).toggleClass('fa-plus fa-minus');
|
||||
});
|
||||
grid.find(".incident").each(function () {
|
||||
$(this).parent().addClass('col-lg-4 col-md-4 col-sm-4 col-xs-4');
|
||||
$(this).parent().parent().on("mouseenter", function () {
|
||||
$(this).find(".incident-toggle").fadeIn(200);
|
||||
}).on("mouseleave", function () {
|
||||
$(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>
|
||||
|
@ -1,27 +1,39 @@
|
||||
<div class="table-responsive">
|
||||
<table id="alertlog-stats_{{ $id }}" class="table table-hover table-condensed table-striped" data-ajax="true">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="count">{{ __('Count') }}</th>
|
||||
<th data-column-id="hostname">{{ __('Device') }}</th>
|
||||
<th data-column-id="alert_rule">{{ __('Alert rule') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<div id="alertlog_stats_container-{{ $id }}" data-reload="false">
|
||||
<div class="table-responsive">
|
||||
<table id="alertlog_stats-{{ $id }}" class="table table-hover table-condensed table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="count">{{ __('Count') }}</th>
|
||||
<th data-column-id="hostname">{{ __('Device') }}</th>
|
||||
<th data-column-id="alert_rule">{{ __('Alert rule') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$("#alertlog-stats_{{ $id }}").bootgrid({
|
||||
ajax: true,
|
||||
rowCount: [50, 100, 250, -1],
|
||||
navigation: ! {{ $hidenavigation }},
|
||||
post: function () {
|
||||
return {
|
||||
id: "alertlog-stats",
|
||||
device_id: "",
|
||||
min_severity: '{{ $min_severity }}',
|
||||
time_interval: '{{ $time_interval }}'
|
||||
};
|
||||
},
|
||||
url: "ajax_table.php"
|
||||
});
|
||||
(function () {
|
||||
var grid = $("#alertlog_stats-{{ $id }}").bootgrid({
|
||||
ajax: true,
|
||||
rowCount: [50, 100, 250, -1],
|
||||
navigation: ! {{ $hidenavigation }},
|
||||
post: function () {
|
||||
return {
|
||||
id: "alertlog-stats",
|
||||
device_id: "",
|
||||
min_severity: '{{ $min_severity }}',
|
||||
time_interval: '{{ $time_interval }}'
|
||||
};
|
||||
},
|
||||
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>
|
||||
|
@ -1,75 +1,87 @@
|
||||
<div class="table-responsive">
|
||||
<table id="alerts_{{ $id }}" class="table table-hover table-condensed alerts" data-ajax="true">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="severity"></th>
|
||||
<th data-column-id="timestamp">{{ __('Timestamp') }}</th>
|
||||
<th data-column-id="rule">{{ __('Rule') }}</th>
|
||||
<th data-column-id="details" data-sortable="false"></th>
|
||||
<th data-column-id="hostname">{{ __('Hostname') }}</th>
|
||||
<th data-column-id="location" data-visible="{{ $location ? 'true' : 'false' }}">{{ __('Location') }}</th>
|
||||
<th data-column-id="ack_ico" data-sortable="false">{{ __('ACK') }}</th>
|
||||
<th data-column-id="notes" data-sortable="false">{{ __('Notes') }}</th>
|
||||
<th data-column-id="proc" data-sortable="false" data-visible="{{ $proc ? 'true' : 'false' }}">URL</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<div id="alerts_container-{{ $id }}" data-reload="false">
|
||||
<div class="table-responsive">
|
||||
<table id="alerts-{{ $id }}" class="table table-hover table-condensed alerts">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="severity"></th>
|
||||
<th data-column-id="timestamp">{{ __('Timestamp') }}</th>
|
||||
<th data-column-id="rule">{{ __('Rule') }}</th>
|
||||
<th data-column-id="details" data-sortable="false"></th>
|
||||
<th data-column-id="hostname">{{ __('Hostname') }}</th>
|
||||
<th data-column-id="location" data-visible="{{ $location ? 'true' : 'false' }}">{{ __('Location') }}</th>
|
||||
<th data-column-id="ack_ico" data-sortable="false">{{ __('ACK') }}</th>
|
||||
<th data-column-id="notes" data-sortable="false">{{ __('Notes') }}</th>
|
||||
<th data-column-id="proc" data-sortable="false" data-visible="{{ $proc ? 'true' : 'false' }}">URL</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
var alerts_grid = $("#alerts_{{ $id }}").bootgrid({
|
||||
ajax: true,
|
||||
requestHandler: request => ({
|
||||
...request,
|
||||
id: "alerts",
|
||||
acknowledged: '{{ $acknowledged }}',
|
||||
unreachable: '{{ $unreachable }}',
|
||||
fired: '{{ $fired }}',
|
||||
min_severity: '{{ $min_severity }}',
|
||||
group: '{{ $device_group }}',
|
||||
proc: '{{ $proc }}',
|
||||
sort: '{{ $sort }}',
|
||||
uncollapse_key_count: '{{ $uncollapse_key_count }}',
|
||||
device_id: '{{ $device }}'
|
||||
}),
|
||||
responseHandler: response => {
|
||||
$("#widget_title_counter_{{ $id }}").text(response.total ? ` (${response.total})` : '')
|
||||
(function () {
|
||||
var alerts_grid = $("#alerts-{{ $id }}").bootgrid({
|
||||
ajax: true,
|
||||
requestHandler: request => ({
|
||||
...request,
|
||||
id: "alerts",
|
||||
acknowledged: '{{ $acknowledged }}',
|
||||
unreachable: '{{ $unreachable }}',
|
||||
fired: '{{ $fired }}',
|
||||
min_severity: '{{ $min_severity }}',
|
||||
group: '{{ $device_group }}',
|
||||
proc: '{{ $proc }}',
|
||||
sort: '{{ $sort }}',
|
||||
uncollapse_key_count: '{{ $uncollapse_key_count }}',
|
||||
device_id: '{{ $device }}'
|
||||
}),
|
||||
responseHandler: response => {
|
||||
$("#widget_title_counter_{{ $id }}").text(response.total ? ` (${response.total})` : '')
|
||||
|
||||
return response
|
||||
},
|
||||
url: "ajax_table.php",
|
||||
navigation: ! {{ $hidenavigation }},
|
||||
rowCount: [50, 100, 250, -1]
|
||||
}).on("loaded.rs.jquery.bootgrid", function() {
|
||||
alerts_grid = $(this);
|
||||
alerts_grid.find(".incident-toggle").each( function() {
|
||||
$(this).parent().addClass('incident-toggle-td');
|
||||
}).on("click", function(e) {
|
||||
var target = $(this).data("target");
|
||||
$(target).collapse('toggle');
|
||||
$(this).toggleClass('fa-plus fa-minus');
|
||||
});
|
||||
alerts_grid.find(".incident").each( function() {
|
||||
$(this).parent().addClass('col-lg-4 col-md-4 col-sm-4 col-xs-4');
|
||||
$(this).parent().parent().on("mouseenter", function() {
|
||||
$(this).find(".incident-toggle").fadeIn(200);
|
||||
}).on("mouseleave", function() {
|
||||
$(this).find(".incident-toggle").fadeOut(200);
|
||||
return response
|
||||
},
|
||||
url: "ajax_table.php",
|
||||
navigation: ! {{ $hidenavigation }},
|
||||
rowCount: [50, 100, 250, -1]
|
||||
}).on("loaded.rs.jquery.bootgrid", function() {
|
||||
alerts_grid = $(this);
|
||||
alerts_grid.find(".incident-toggle").each( function() {
|
||||
$(this).parent().addClass('incident-toggle-td');
|
||||
}).on("click", function(e) {
|
||||
var target = $(this).data("target");
|
||||
$(target).collapse('toggle');
|
||||
$(this).toggleClass('fa-plus fa-minus');
|
||||
});
|
||||
alerts_grid.find(".incident").each( function() {
|
||||
$(this).parent().addClass('col-lg-4 col-md-4 col-sm-4 col-xs-4');
|
||||
$(this).parent().parent().on("mouseenter", function() {
|
||||
$(this).find(".incident-toggle").fadeIn(200);
|
||||
}).on("mouseleave", function() {
|
||||
$(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();
|
||||
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_container-{{ $id }}').on('refresh', function (event) {
|
||||
alerts_grid.bootgrid('reload');
|
||||
});
|
||||
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_container-{{ $id }}').on('destroy', function (event) {
|
||||
alerts_grid.bootgrid('destroy');
|
||||
delete alerts_grid;
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
@ -1,29 +1,41 @@
|
||||
<div class="table-responsive">
|
||||
<table id="eventlog" class="table table-hover table-condensed table-striped" data-ajax="true">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="datetime" data-order="desc">{{ __('Timestamp') }}</th>
|
||||
<th data-column-id="type">{{ __('Type') }}</th>
|
||||
<th data-column-id="device_id">{{ __('Hostname') }}</th>
|
||||
<th data-column-id="message">{{ __('Message') }}</th>
|
||||
<th data-column-id="username">{{ __('User') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<div id="eventlog_container-{{ $id }}" data-reload="false">
|
||||
<div class="table-responsive">
|
||||
<table id="eventlog-{{ $id }}" class="table table-hover table-condensed table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="datetime" data-order="desc">{{ __('Timestamp') }}</th>
|
||||
<th data-column-id="type">{{ __('Type') }}</th>
|
||||
<th data-column-id="device_id">{{ __('Hostname') }}</th>
|
||||
<th data-column-id="message">{{ __('Message') }}</th>
|
||||
<th data-column-id="username">{{ __('User') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$("#eventlog").bootgrid({
|
||||
ajax: true,
|
||||
rowCount: [50, 100, 250, -1],
|
||||
navigation: ! {{ $hidenavigation }},
|
||||
post: function ()
|
||||
{
|
||||
return {
|
||||
device: "{{ $device }}",
|
||||
device_group: "{{ $device_group }}",
|
||||
eventtype: "{{ $eventtype }}"
|
||||
};
|
||||
},
|
||||
url: "{{ url('/ajax/table/eventlog') }}"
|
||||
$(function () {
|
||||
var grid = $("#eventlog-{{ $id }}").bootgrid({
|
||||
ajax: true,
|
||||
rowCount: [50, 100, 250, -1],
|
||||
navigation: ! {{ $hidenavigation }},
|
||||
post: function ()
|
||||
{
|
||||
return {
|
||||
device: "{{ $device }}",
|
||||
device_group: "{{ $device_group }}",
|
||||
eventtype: "{{ $eventtype }}"
|
||||
};
|
||||
},
|
||||
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>
|
||||
|
@ -1,42 +1,54 @@
|
||||
<div class="table-responsive">
|
||||
<table id="graylog-{{ $id }}" class="table table-hover table-condensed graylog" data-ajax="true">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="severity" data-sortable="false"></th>
|
||||
<th data-column-id="origin">{{ __('Origin') }}</th>
|
||||
<th data-column-id="timestamp" data-formatter="browserTime">{{ __('Timestamp') }}</th>
|
||||
<th data-column-id="level" data-sortable="false">{{ __('Level') }}</th>
|
||||
<th data-column-id="source">{{ __('Source') }}</th>
|
||||
<th data-column-id="message" data-sortable="false">{{ __('Message') }}</th>
|
||||
<th data-column-id="facility" data-sortable="false">{{ __('Facility') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<div id="graylog_container-{{ $id }}" data-reload="false">
|
||||
<div class="table-responsive">
|
||||
<table id="graylog-{{ $id }}" class="table table-hover table-condensed graylog">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="severity" data-sortable="false"></th>
|
||||
<th data-column-id="origin">{{ __('Origin') }}</th>
|
||||
<th data-column-id="timestamp" data-formatter="browserTime">{{ __('Timestamp') }}</th>
|
||||
<th data-column-id="level" data-sortable="false">{{ __('Level') }}</th>
|
||||
<th data-column-id="source">{{ __('Source') }}</th>
|
||||
<th data-column-id="message" data-sortable="false">{{ __('Message') }}</th>
|
||||
<th data-column-id="facility" data-sortable="false">{{ __('Facility') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$("#graylog-{{ $id }}").bootgrid({
|
||||
ajax: true,
|
||||
rowCount: ['{{ $limit }}', 25,50,100,250,-1],
|
||||
navigation: ! {{ $hidenavigation }},
|
||||
formatters: {
|
||||
"browserTime": function(column, row) {
|
||||
@config('graylog.timezone')
|
||||
return row.timestamp;
|
||||
@else
|
||||
return moment.parseZone(row.timestamp).local().format("YYYY-MM-DD HH:MM:SS");
|
||||
@endconfig
|
||||
}
|
||||
},
|
||||
post: function ()
|
||||
{
|
||||
return {
|
||||
stream: "{{ $stream }}",
|
||||
device: "{{ $device }}",
|
||||
range: "{{ $range }}",
|
||||
loglevel: "{{ $loglevel }}"
|
||||
};
|
||||
},
|
||||
url: "{{ url('/ajax/table/graylog') }}"
|
||||
});
|
||||
(function () {
|
||||
var grid = $("#graylog-{{ $id }}").bootgrid({
|
||||
ajax: true,
|
||||
rowCount: ['{{ $limit }}', 25,50,100,250,-1],
|
||||
navigation: ! {{ $hidenavigation }},
|
||||
formatters: {
|
||||
"browserTime": function(column, row) {
|
||||
@config('graylog.timezone')
|
||||
return row.timestamp;
|
||||
@else
|
||||
return moment.parseZone(row.timestamp).local().format("YYYY-MM-DD HH:MM:SS");
|
||||
@endconfig
|
||||
}
|
||||
},
|
||||
post: function ()
|
||||
{
|
||||
return {
|
||||
stream: "{{ $stream }}",
|
||||
device: "{{ $device }}",
|
||||
range: "{{ $range }}",
|
||||
loglevel: "{{ $loglevel }}"
|
||||
};
|
||||
},
|
||||
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>
|
||||
|
@ -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
|
||||
@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') }}">
|
||||
</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">
|
||||
<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') }}">
|
||||
|
@ -1,31 +1,43 @@
|
||||
<div class="table-responsive">
|
||||
<table id="syslog" class="table table-hover table-condensed table-striped" data-ajax="true">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="label"></th>
|
||||
<th data-column-id="timestamp" data-order="desc">{{ __('Timestamp') }}</th>
|
||||
<th data-column-id="level">{{ __('Level') }}</th>
|
||||
<th data-column-id="device_id">{{ __('Hostname') }}</th>
|
||||
<th data-column-id="program">{{ __('Program') }}</th>
|
||||
<th data-column-id="msg">{{ __('Message') }}</th>
|
||||
<th data-column-id="priority">{{ __('Priority') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
<div id="syslog_container-{{ $id }}" data-reload="false">
|
||||
<div class="table-responsive">
|
||||
<table id="syslog-{{ $id }}" class="table table-hover table-condensed table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="label"></th>
|
||||
<th data-column-id="timestamp" data-order="desc">{{ __('Timestamp') }}</th>
|
||||
<th data-column-id="level">{{ __('Level') }}</th>
|
||||
<th data-column-id="device_id">{{ __('Hostname') }}</th>
|
||||
<th data-column-id="program">{{ __('Program') }}</th>
|
||||
<th data-column-id="msg">{{ __('Message') }}</th>
|
||||
<th data-column-id="priority">{{ __('Priority') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script type="application/javascript">
|
||||
$("#syslog").bootgrid({
|
||||
ajax: true,
|
||||
rowCount: [50, 100, 250, -1],
|
||||
navigation: ! {{ $hidenavigation }},
|
||||
post: function ()
|
||||
{
|
||||
return {
|
||||
device: '{{ $device ?: '' }}',
|
||||
device_group: '{{ $device_group }}',
|
||||
level: '{{ $level }}'
|
||||
};
|
||||
},
|
||||
url: "{{ url('/ajax/table/syslog') }}"
|
||||
});
|
||||
(function () {
|
||||
var grid = $("#syslog-{{ $id }}").bootgrid({
|
||||
ajax: true,
|
||||
rowCount: [50, 100, 250, -1],
|
||||
navigation: ! {{ $hidenavigation }},
|
||||
post: function ()
|
||||
{
|
||||
return {
|
||||
device: '{{ $device ?: '' }}',
|
||||
device_group: '{{ $device_group }}',
|
||||
level: '{{ $level }}'
|
||||
};
|
||||
},
|
||||
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>
|
||||
|
@ -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">
|
||||
loadjs('js/leaflet.js', function() {
|
||||
loadjs('js/leaflet.markercluster.js', function () {
|
||||
loadjs('js/leaflet.awesome-markers.min.js', function () {
|
||||
var map = L.map('leaflet-map-{{ $id }}', { zoomSnap: 0.1 } ).setView(['{{ $init_lat }}', '{{ $init_lng }}'], '{{ sprintf('%01.1f', $init_zoom) }}');
|
||||
L.tileLayer('//{{ $title_url }}/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
}).addTo(map);
|
||||
(function () {
|
||||
const map_id = 'worldmap_widget-{{ $id }}';
|
||||
const status = {{ Js::from($status) }};
|
||||
const device_group = {{ (int) $device_group }};
|
||||
const map_config = {{ Js::from($map_config) }};
|
||||
const group_radius = {{ (int) $group_radius }};
|
||||
|
||||
var markers = 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) });
|
||||
}
|
||||
});
|
||||
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'
|
||||
});
|
||||
loadjs('js/leaflet.js', function () {
|
||||
loadjs('js/leaflet.markercluster.js', function () {
|
||||
loadjs('js/leaflet.awesome-markers.min.js', function () {
|
||||
loadjs('js/L.Control.Locate.min.js', function () {
|
||||
init_map(map_id, map_config).scrollWheelZoom.disable();
|
||||
populate_map_markers(map_id, group_radius, status, device_group);
|
||||
|
||||
@foreach($devices as $device)
|
||||
@if($status != '0' or !$device->isUnderMaintenance())
|
||||
var title = '<a href="@deviceUrl($device)"><img src="{{ $device->icon }}" width="32" height="32" alt=""> {{ $device->displayName() }}</a>';
|
||||
var tooltip = '{{ $device->displayName() }}';
|
||||
var marker = L.marker(new L.LatLng('{{ $device->location->lat }}', '{{ $device->location->lng }}'), {title: tooltip, icon: {{ $device->markerIcon }}, zIndexOffset: {{ $device->zOffset }}});
|
||||
marker.bindPopup(title);
|
||||
markers.addLayer(marker);
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
map.addLayer(markers);
|
||||
map.scrollWheelZoom.disable();
|
||||
$(document).ready(function() {
|
||||
$("#leaflet-map-{{ $id }}").on("click", function (event) {
|
||||
map.scrollWheelZoom.enable();
|
||||
}).on("mouseleave", function (event) {
|
||||
map.scrollWheelZoom.disable();
|
||||
// register listeners
|
||||
$('#' + map_id).on('click', function (event) {
|
||||
get_map(map_id).scrollWheelZoom.enable();
|
||||
}).on('mouseleave', function (event) {
|
||||
get_map(map_id).scrollWheelZoom.disable();
|
||||
}).on('resize', function (event) {
|
||||
get_map(map_id).invalidateSize();
|
||||
}).on('refresh', function (event) {
|
||||
get_map(map_id).invalidateSize();
|
||||
populate_map_markers(map_id, group_radius, status, device_group);
|
||||
}).on('destroy', function (event) {
|
||||
destroy_map(map_id);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});});});
|
||||
})();
|
||||
</script>
|
||||
|
@ -237,7 +237,8 @@ Route::middleware(['auth'])->group(function () {
|
||||
Route::post('top-devices', 'TopDevicesController');
|
||||
Route::post('top-interfaces', 'TopInterfacesController');
|
||||
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');
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user