Skip to content
This repository was archived by the owner on Oct 7, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions mapadroid/madmin/api/apiHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ def entrypoint(self, *args, **kwargs):
headers = {
'X-Status': 'Support Content-Types: %s' % (sorted(global_variables.SUPPORTED_FORMATS))
}
self._logger.debug2('Invalid content-type recieved: {}', flask.request.headers.get('Content-Type'))
return apiResponse.APIResponse(self._logger, self.api_req)(None, 422, headers=headers)
self._logger.debug2('Invalid content-type received: {}', flask.request.headers.get('Content-Type'))
return apiResponse.APIResponse(self._logger, self.api_req)(None, 415, headers=headers)
except apiException.FormattingError as err:
headers = {
'X-Status': err.reason
Expand Down
2 changes: 1 addition & 1 deletion mapadroid/madmin/api/apiRequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def parse_data(self):

def process_request(self):
# Determine the content-type of the request and convert accordingly
content_type = self._request.headers.get('Content-type')
content_type = self._request.mimetype
if not content_type:
content_type = global_variables.DEFAULT_FORMAT.lower()
else:
Expand Down
24 changes: 22 additions & 2 deletions mapadroid/madmin/routes/map.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from flask_caching import Cache
from mapadroid.data_manager import DataManagerException
from mapadroid.db.DbWrapper import DbWrapper
from mapadroid.geofence.geofenceHelper import GeofenceHelper
from mapadroid.madmin.functions import (
auth_required, get_coord_float, get_bound_params, get_geofences, generate_coords_from_geofence
)
Expand Down Expand Up @@ -39,7 +40,8 @@ def add_route(self):
routes = [
("/map", self.map),
("/get_workers", self.get_workers),
("/get_geofence", self.get_geofence),
("/get_geofences", self.get_geofences),
("/get_areas", self.get_areas),
("/get_route", self.get_route),
("/get_prioroute", self.get_prioroute),
("/get_spawns", self.get_spawns),
Expand Down Expand Up @@ -81,7 +83,25 @@ def get_workers(self):
return jsonify(positions)

@auth_required
def get_geofence(self):
def get_geofences(self):
geofences = self._data_manager.get_root_resource("geofence")
export = []

for geofence_id, geofence in geofences.items():
geofence_helper = GeofenceHelper(geofence, None, geofence["name"])
if len(geofence_helper.geofenced_areas) == 1:
geofenced_area = geofence_helper.geofenced_areas[0]
if "polygon" in geofenced_area:
export.append({
"id": geofence_id,
"name": geofence["name"],
"coordinates": geofenced_area["polygon"]
})

return jsonify(export)

@auth_required
def get_areas(self):
areas = self._mapping_manager.get_areas()
areas_sorted = sorted(areas, key=lambda x: areas[x]['name'])
geofences = get_geofences(self._mapping_manager, self._data_manager)
Expand Down
150 changes: 150 additions & 0 deletions static/madmin/static/js/leaflet-event-forwarder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
"use strict";

// Allows forwarding events from one pane to another (with preferCanvas=true)
// See https://github.com/Leaflet/Leaflet/issues/6205 for details.
// Originally based on https://github.com/danwild/leaflet-event-forwarder but almost rewritten completely since.
const EventForwarder = L.Class.extend({

initialize: function (map) {
this._map = map;
this._isDraggingMap = false;
this._previousMousePane = null;
this.isEnabled = true;

map.on("dragstart", this._onDragStart, this);
map.on("dragend", this._onDragEnd, this);

L.DomEvent.on(map, "click", this._preventReentrancy(this._onClick), this);
L.DomEvent.on(map, "mouseout", this._preventReentrancy(this._onMouseOut), this);
L.DomEvent.on(map, "mousemove", this._preventReentrancy(this._onMouseMove), this);
},

_preventReentrancy(fn) {
let reentrancyGuard = false;

return function() {
if (reentrancyGuard) {
return;
}

reentrancyGuard = true;
try {
return fn.apply(this, arguments);
}
finally {
reentrancyGuard = false;
}
}.bind(this);
},

_onDragStart: function () {
this._isDraggingMap = true;
},

_onDragEnd: function () {
this._isDraggingMap = false;
},

_onClick: function (event) {
this._propagateEvent(event);
},

_onMouseOut: function (event) {
if (!this.isEnabled || this._isDraggingMap || this._previousMousePane === null) {
return;
}

const originalTarget = event.originalEvent.target;
if (originalTarget === this._previousMousePane)
return;

this._previousMousePane.dispatchEvent(new MouseEvent("mouseout", event.originalEvent));
this._previousMousePane = null;

this._addAndRemoveMapClasses("leaflet-grab", "leaflet-interactive");
},

_onMouseMove: function (event) {
if (!this.isEnabled || this._isDraggingMap) {
return;
}

const mousePane = this._propagateEvent(event);

if (this._previousMousePane === mousePane) {
return;
}

if (this._previousMousePane !== null) {
this._previousMousePane.dispatchEvent(new MouseEvent("mouseout", event.originalEvent));
}

this._previousMousePane = mousePane;

// fix cursor
if (mousePane !== null) {
this._addAndRemoveMapClasses("leaflet-interactive", "leaflet-grab");
}
else {
this._addAndRemoveMapClasses("leaflet-grab", "leaflet-interactive");
}
},

_addAndRemoveMapClasses(classToAdd, classToRemove) {
const containerClasses = this._map.getContainer().classList;

if (!containerClasses.contains(classToAdd)) {
containerClasses.add(classToAdd);
}

containerClasses.remove(classToRemove);
},

_propagateEvent(event) {
const originalTarget = event.originalEvent.target;
if (originalTarget.nodeName.toLowerCase() !== "canvas" || originalTarget.classList.contains("leaflet-interactive")) {
return originalTarget;
}

const removedTargets = [];

function removeTarget(target) {
removedTargets.push({ target: target, oldPointerEvents: target.style.pointerEvents });
target.style.pointerEvents = "none";
}

try {
let previousTarget = originalTarget;

// propages the event until we find an interactive layer
while (true) {
removeTarget(previousTarget);

const nextTarget = document.elementFromPoint(event.originalEvent.clientX, event.originalEvent.clientY);

if (nextTarget === null
|| nextTarget.classList.contains("leaflet-container") // reached the map itself
|| nextTarget.nodeName.toLowerCase() === "body") {
return null;
}

const newEvent = new MouseEvent(event.type, event.originalEvent);
if (!nextTarget.dispatchEvent(newEvent) || nextTarget.classList.contains("leaflet-interactive")) {
return nextTarget;
}

previousTarget = nextTarget;
}
}
finally {
for (const removedTarget of removedTargets) {
removedTarget.target.style.pointerEvents = removedTarget.oldPointerEvents;
}
}
}

});

L.eventForwarder = function (map) {
return new EventForwarder(map);
};
Loading