Better geojson drag drop support, ensure contents are buffer

This commit is contained in:
Dave Conway-Jones 2020-12-07 17:37:40 +00:00
parent 821bedca20
commit 92c40bf56f
No known key found for this signature in database
GPG Key ID: 88BA2B8A411BE9FF
5 changed files with 34 additions and 21 deletions

View File

@ -1,5 +1,6 @@
### Change Log for Node-RED Worldmap ### Change Log for Node-RED Worldmap
- v2.7.1 - Also allow geojson files to be dropped, and better png handling
- v2.7.0 - Allow track and image files to be dragged onto the map, if enabled - v2.7.0 - Allow track and image files to be dragged onto the map, if enabled
- v2.6.1 - Better fit for worldmap when in ui_template - v2.6.1 - Better fit for worldmap when in ui_template
- v2.6.0 - Add route capability to draw line when online - v2.6.0 - Add route capability to draw line when online

View File

@ -11,6 +11,7 @@ map web page for plotting "things" on.
### Updates ### Updates
- v2.7.1 - Also allow geojson files to be dropped, and better png handling
- v2.7.0 - Allow track and image files to be dragged onto the map, if enabled - v2.7.0 - Allow track and image files to be dragged onto the map, if enabled
- v2.6.1 - Better fit for worldmap when in ui_template - v2.6.1 - Better fit for worldmap when in ui_template
- v2.6.0 - Add route capability to draw line when online - v2.6.0 - Add route capability to draw line when online
@ -339,13 +340,13 @@ The **worldmap in** node can be used to receive various events from the map. Exa
{ "action": "addlayer", "name": "myLayer" } // when a new map layer is added { "action": "addlayer", "name": "myLayer" } // when a new map layer is added
{ "action": "dellayer", "name": "myLayer" } // when a new map layer is deleted { "action": "dellayer", "name": "myLayer" } // when a new map layer is deleted
{ "action": "file", "name": "filename", "lat":51, "lon":-1, "content":"....."} // when a file is dropped on the map - see below. { "action": "file", "name": "myfilename", "type":"image/jpeg", "lat":51, "lon":-1, "content":"....."} // when a file is dropped on the map - see below.
{ "action": "button", "name": "My Fancy Button" } // when a user defined button is clicked { "action": "button", "name": "My Fancy Button" } // when a user defined button is clicked
{ "action": "feedback", "name": "some name", "value": "some value", "lat":51, "lon":0, "layer":"unknown" } // when a user calls the feedback function - see below { "action": "feedback", "name": "some name", "value": "some value", "lat":51, "lon":0, "layer":"unknown" } // when a user calls the feedback function - see below
If File Drop is enabled - then the map can accept files of type gpx, kml, nvg, png and jpg. Image contents will be base64 encoded for transfer. The lat, lon of the cursor drop point will be included. Tracks will be locally rendered on the map. The node-red-node-exif node can be used to extract lcoation information from a jpeg image and then geolocate it back on the map. If File Drop is enabled - then the map can accept files of type gpx, kml, nvg, jpeg, png and geojson. The file content property will always be a binary buffer. The lat, lon of the cursor drop point will be included. Tracks will be locally rendered on the map. The node-red-node-exif node can be used to extract location information from a jpeg image and then geolocate it back on the map. Png images will be located where they are dropped but can then be dragged if required.
All actions also include a `msg._sessionid` property that indicates which client session they came from. Any msg sent out that includes this property will ONLY be sent to that session - so you can target map updates to specific sessions if required. All actions also include a `msg._sessionid` property that indicates which client session they came from. Any msg sent out that includes this property will ONLY be sent to that session - so you can target map updates to specific sessions if required.

View File

@ -1,6 +1,6 @@
{ {
"name": "node-red-contrib-web-worldmap", "name": "node-red-contrib-web-worldmap",
"version": "2.7.0", "version": "2.7.1",
"description": "A Node-RED node to provide a web page of a world map for plotting things on.", "description": "A Node-RED node to provide a web page of a world map for plotting things on.",
"dependencies": { "dependencies": {
"cgi": "0.3.1", "cgi": "0.3.1",

View File

@ -1,3 +1,4 @@
/* eslint-disable no-inner-declarations */
/** /**
* Copyright 2015, 2019 IBM Corp. * Copyright 2015, 2019 IBM Corp.
* *
@ -228,6 +229,7 @@ module.exports = function(RED) {
message = JSON.parse(message); message = JSON.parse(message);
if (message.hasOwnProperty("action")) { if (message.hasOwnProperty("action")) {
if ((node.events === "files") && (message.action === "file")) { if ((node.events === "files") && (message.action === "file")) {
message.content = Buffer.from(message.content.split('base64,')[1], 'base64');
setImmediate(function() {node.send({payload:message, topic:node.path.substr(1), _sessionid:client.id})}); setImmediate(function() {node.send({payload:message, topic:node.path.substr(1), _sessionid:client.id})});
} }
else if ((node.events === "connect") && (message.action === "connected")) { else if ((node.events === "connect") && (message.action === "connected")) {

View File

@ -93,9 +93,9 @@ var connect = function() {
setTimeout(function() { connect(); }, 2500); setTimeout(function() { connect(); }, 2500);
}; };
ws.onmessage = function(e) { ws.onmessage = function(e) {
var data = JSON.parse(e.data); try { var data = JSON.parse(e.data); handleData(data); }
catch (e) { console.log("BAD DATA"); return; }
// console.log("DATA",typeof data,data); // console.log("DATA",typeof data,data);
if (data) { handleData(data); }
}; };
} }
console.log("CONNECT TO",location.pathname + 'socket'); console.log("CONNECT TO",location.pathname + 'socket');
@ -129,8 +129,8 @@ var handleData = function(data) {
} }
} }
if (data.command) { doCommand(data.command); delete data.command; } if (data.command) { doCommand(data.command); delete data.command; }
if (data.hasOwnProperty("name")) { setMarker(data); } if (data.hasOwnProperty("type")) { doGeojson("geojson",data); }
else if (data.hasOwnProperty("type")) { doGeojson("geojson",data); } else if (data.hasOwnProperty("name")) { setMarker(data); }
else { else {
console.log("SKIP",data); console.log("SKIP",data);
// if (typeof data === "string") { doDialog(data); } // if (typeof data === "string") { doDialog(data); }
@ -186,8 +186,9 @@ var readFile = function(file) {
file.type.indexOf('text') === -1 && file.type.indexOf('text') === -1 &&
file.type.indexOf('kml') === -1 && file.type.indexOf('kml') === -1 &&
file.type.indexOf('jpeg') === -1 && file.type.indexOf('jpeg') === -1 &&
file.type.indexOf('png') === -1) { file.type.indexOf('png') === -1 &&
console.log('File is not text, kml, jpeg or png.', file.type, file); file.type.indexOf('json') === -1) {
console.log('File is not text, kml, jpeg, png, or json', file.type, file);
return; return;
} }
@ -198,20 +199,28 @@ var readFile = function(file) {
if (content.indexOf("base64") !== -1) { if (content.indexOf("base64") !== -1) {
if (content.indexOf("image") === -1) { if (content.indexOf("image") === -1) {
data = atob(content.split("base64,")[1]); data = atob(content.split("base64,")[1]);
if (data.indexOf("<gpx") !== -1) { if (data.indexOf('<?xml') !== -1) {
doCommand({map:{overlay:file.name, gpx:data}}); if (data.indexOf("<gpx") !== -1) {
} doCommand({map:{overlay:file.name, gpx:data}});
else if (data.indexOf("<kml") !== -1) { }
doCommand({map:{overlay:file.name, kml:data}}); else if (data.indexOf("<kml") !== -1) {
} doCommand({map:{overlay:file.name, kml:data}});
else if (data.indexOf("<nvg") !== -1) { }
doCommand({map:{overlay:file.name, nvg:data}}); else if (data.indexOf("<nvg") !== -1) {
doCommand({map:{overlay:file.name, nvg:data}});
}
} }
else { else {
handleData(data); try {
data = JSON.parse(data);
handleData(data);
}
catch(e) {
console.log("NOT JSON DATA",data);
}
} }
} }
ws.send(JSON.stringify({action:"file", name:file.name, content:content, lat:droplatlng.lat, lon:droplatlng.lng})); ws.send(JSON.stringify({action:"file", name:file.name, type:file.type, content:content, lat:droplatlng.lat, lon:droplatlng.lng}));
} }
else { else {
console.log("NOT SURE WHAT THIS IS?",content) console.log("NOT SURE WHAT THIS IS?",content)
@ -2326,10 +2335,10 @@ function doCommand(cmd) {
// handle any incoming GEOJSON directly - may style badly // handle any incoming GEOJSON directly - may style badly
function doGeojson(n,g,l,o) { function doGeojson(n,g,l,o) {
var lay = l || "unknown"; var lay = l || g.name || "unknown";
// if (!basemaps[lay]) { // if (!basemaps[lay]) {
var opt = { style: function(feature) { var opt = { style: function(feature) {
var st = { stroke:true, color:"#910000", weight:2, fill:true, fillColor:"#910000", fillOpacity:0.3 }; var st = { stroke:true, color:"#910000", weight:1, fill:true, fillColor:"#910000", fillOpacity:0.15 };
st = Object.assign(st,o); st = Object.assign(st,o);
if (feature.hasOwnProperty("properties")) { if (feature.hasOwnProperty("properties")) {
//console.log("GPROPS", feature.properties) //console.log("GPROPS", feature.properties)