Added different location support to map

Ylian Saint-Hilaire committed Sep 25, 2017 at 15:28 UTC 0b86ecefa5356995799fda790700ac32086f3c6a
9 files changed +175 -49
mesherrors.txt
+57
@@ -50,3 +50,60 @@ TypeError: socket.getPeerCertificate is not a function
50 at TCP.onconnection (net.js:1452:8)
51
52
53 +-------- 9/25/2017, 1:57:36 PM --------
54 +
55 +C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:1589
56 + if ((node.userloc) && (node.userloc.length != 2)) return;
57 + ^
58 +
59 +ReferenceError: node is not defined
60 + at WebSocket.<anonymous> (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:1589:34)
61 + at emitTwo (events.js:106:13)
62 + at WebSocket.emit (events.js:191:7)
63 + at Receiver.ontext (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\ws\lib\WebSocket.js:841:10)
64 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\ws\lib\Receiver.js:536:18
65 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\ws\lib\Receiver.js:368:7
66 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\ws\lib\PerMessageDeflate.js:249:5
67 + at afterWrite (_stream_writable.js:360:3)
68 + at onwrite (_stream_writable.js:351:7)
69 + at WritableState.onwrite (_stream_writable.js:89:5)
70 +
71 +
72 +-------- 9/25/2017, 2:01:16 PM --------
73 +
74 +C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:1616
75 + command.userloc.push((Math.floor((new Date(iploc.date)) / 1000)));
76 + ^
77 +
78 +ReferenceError: iploc is not defined
79 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:1616:88
80 + at newArguments.(anonymous function) (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\executor.js:29:17)
81 + at Cursor.execFn (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:484:12)
82 + at callback (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:126:19)
83 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:193:12
84 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:329:14
85 + at Object.async.eachSeries (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:130:20)
86 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:323:11
87 + at fn (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:582:34)
88 + at Immediate._onImmediate (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:498:34)
89 +
90 +
91 +-------- 9/25/2017, 2:02:08 PM --------
92 +
93 +C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:1617
94 + node.userloc = command.join(',');
95 + ^
96 +
97 +TypeError: command.join is not a function
98 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\webserver.js:1617:68
99 + at newArguments.(anonymous function) (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\executor.js:29:17)
100 + at Cursor.execFn (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:484:12)
101 + at callback (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:126:19)
102 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\cursor.js:193:12
103 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:329:14
104 + at Object.async.eachSeries (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:130:20)
105 + at C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\nedb\lib\datastore.js:323:11
106 + at fn (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:582:34)
107 + at Immediate._onImmediate (C:\Users\Default.DESKTOP-M9I88C9\Desktop\AmtWebApp\meshcentral\node_modules\async\lib\async.js:498:34)
108 +
109 +
package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "meshcentral",
3 - "version": "0.0.8-d",
3 + "version": "0.0.8-e",
4 "keywords": [
5 "Remote Management",
6 "Intel AMT",
public/images/mapmarker-gps.png
Binary files /dev/null and b/public/images/mapmarker-gps.png differ
public/images/mapmarker-ip.png
Binary files /dev/null and b/public/images/mapmarker-ip.png differ
public/images/mapmarker-user.png
Binary files /dev/null and b/public/images/mapmarker-user.png differ
public/images/mapmarker-wifi.png
Binary files /dev/null and b/public/images/mapmarker-wifi.png differ
public/styles/ol3-contextmenu.min.css new
+7
@@ -0,0 +1,7 @@
1 +/*!
2 + * ol3-contextmenu - v2.5.0
3 + * Custom Context Menu for Openlayers
4 + * https://github.com/jonataswalker/ol3-contextmenu
5 + * Built: Fri Feb 24 2017 15:11:23 GMT-0300 (BRT)
6 + */
7 +.ol-ctx-menu-container{position:absolute;padding:8px;background:#fff;color:#222;font-size:13px;border-radius:5px;box-shadow:3px 3px 5px rgba(0,0,0,.2);box-sizing:border-box}.ol-ctx-menu-container a,.ol-ctx-menu-container div,.ol-ctx-menu-container img,.ol-ctx-menu-container li,.ol-ctx-menu-container span,.ol-ctx-menu-container ul{margin:0;padding:0;border:0;font:inherit;font-size:100%;vertical-align:baseline}.ol-ctx-menu-container a img{border:none}.ol-ctx-menu-container *,.ol-ctx-menu-container :after,.ol-ctx-menu-container :before{box-sizing:inherit}.ol-ctx-menu-container.ol-ctx-menu-hidden{opacity:0;visibility:hidden;-webkit-transition:visibility 0s linear .3s,opacity .3s;transition:visibility 0s linear .3s,opacity .3s}.ol-ctx-menu-container ul{list-style:none}.ol-ctx-menu-container li{position:relative;line-height:20px;padding:2px 5px}.ol-ctx-menu-container li:not(.ol-ctx-menu-separator):hover{cursor:pointer;background-color:#333;color:#eee}.ol-ctx-menu-container li.ol-ctx-menu-submenu .ol-ctx-menu-container{border:1px solid #eee;padding:8px;top:0;opacity:0;visibility:hidden;-webkit-transition:visibility 0s linear .3s,opacity .3s;transition:visibility 0s linear .3s,opacity .3s}.ol-ctx-menu-container li.ol-ctx-menu-submenu:hover .ol-ctx-menu-container{opacity:1;visibility:visible;-webkit-transition-delay:0s;transition-delay:0s}.ol-ctx-menu-container li.ol-ctx-menu-submenu:after{position:absolute;top:7px;right:10px;content:"";display:inline-block;width:.6em;height:.6em;border-right:.3em solid #222;border-top:.3em solid #222;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.ol-ctx-menu-container li.ol-ctx-menu-submenu:hover:after{border-color:#eee}.ol-ctx-menu-container li.ol-ctx-menu-separator{padding:0}.ol-ctx-menu-container li.ol-ctx-menu-separator hr{border:0;height:1px;background-image:-webkit-linear-gradient(right,transparent,rgba(0,0,0,.75),transparent);background-image:linear-gradient(270deg,transparent,rgba(0,0,0,.75),transparent)}.ol-ctx-menu-icon{text-indent:20px;background-size:20px auto;background-repeat:no-repeat;background-position:0}.ol-ctx-menu-zoom-in{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABaUlEQVQ4T72U7VHCQBCGn90GtAMuNGCswFiBWIFQgWMFxg6wArECsQKhArEBiB1Qwa1zgQn5IAYcxv13k71n3919L8KJQ07M47+BzgG9TRfZ/JBuWhS6BJFHRJICYrZGZIz3z5Ct2+B7gG6I6kt+wewdkQVwjtkAkR5mC8yu26A1oItR/cTsOweQBdgutD8G7jGm2PJ2n8oqUKIpIjd4HxTM8gvaT/F+AlmWnyWaIXKF95eNguFzTYFhNsdWu9kFgFlaFMANUH3D8wDLoLgSTSD2il8NCe2ZXQBxWDGwxmyUzzOMBZ7wy7Qb2K0wQfXjMOBuhlFpZtNty5sFaTQBuTusZdymeqs1SpYKcO9HkE3KbTd9WFijMHJQ5hBNEAYNq5Qd0dhyke0GiE4QzjqfW23mHT8Hl4DG4Lce3FPE7AtbBSdsbNqpoJLgYkRnNeUV+xwJDHTnUEkxHGbhBXUs5TjJjew/KPy94g+NRaIVRYmMXwAAAABJRU5ErkJggg==")}.ol-ctx-menu-container li:hover.ol-ctx-menu-zoom-in{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABc0lEQVQ4T71U21ECQRDsJgGdvQDECMQIxAjECMQILCPwzAAjECIQI0AiEDPQAPaWCBhrcKHuCUcV5f7dY3v6tUscefHIePhfwBBCF8CZqRCReRs1tQxDCH1VfQLQz4EsSY4AvIjIsgm8AhhCGKrqa9zwrqoLAKckB5HtguR1E2gBMITQU9VPAD8GICIGtl3e+xHJBwBT59xtHcsCYJZlUwA3kcGHbfDep51OZywi3/acZZm9vyJ5WR5o38uACmDunNt6ZwAkUxFZDwghDFT1jeSjiJinhVUBVNVJkiTDKO8CQA+AsbNQ7s1Ps0VVn5MkSfcCtmBoDZi1Bdx4eJ7zbBolrwPy3o9J3rWSHPs3A1BbjVKlYBaIyDgvu9LDXDU2RTZmXVW1oKyLxRD+OrkOrJLy5mVM0iaftDhuhVbsvBzMglzKUNW6IV/OOWtCM8MmVvEkmbwt83LaB19fdgOtVquUZJeknaDdobTwbOcvBzPcN/AXH1DFFWP7u9oAAAAASUVORK5CYII=")}.ol-ctx-menu-zoom-out{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABU0lEQVQ4T72U7VECMRRFz3sNaAdkacC1AtcKxApcKnCsQOwAK3CtQKxAqEBsANYOqCDPyTIC+8WCw5jfybn33dxEOPGSE/P4b6BzQG89RT47ZJoWhy5B5BGRZAMxWyEyxvtnyFdt8AagS1F9KQ6YvSMyB84xGyDSw2yO2XUbtAJ0MaqfmH0XAPIA2y7tj4F7jAm2uG1yWQZKNEHkBu+Dg2njWBJNEbnC+8uaIFRuWfuG2QxbbrOrUd0A1Tc8D7AIjkur7DAAsVf8MiWMZ3ZR2m02LPIMscATfjHqBnY7TFD9OAy4zTCCPG/MUKMM5O6wkXFr9dZq7FQqqHk/hDzbFa73cFONTZFDdRyiCcKg5rrSiLaXkiI6RjjrfG6VzDs+B5eAxuDXeYpmNRGzL2wZ/wof+du4GNFpBVqqz5HA4MM5VEYYDrOs+1I6Q9u/4Q8O9wN/AGgWjBVqQjjgAAAAAElFTkSuQmCC")}.ol-ctx-menu-container li:hover.ol-ctx-menu-zoom-out{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAABYklEQVQ4T72U4VHCQBCF36tA91KAWIFYgViBWIFYgWMFYgdYgVCBWAFSgdiBFpAsFWSdxcDkQoBkhnF/ZjbfvX377ogjF4/Mw/8CVbUD4MynEJF5k2lqFapqz8yeAPRKkCXJEYAXEVnugm8BVXVgZq/FD+9mtgBwSrJfqF2QvN4FjYCq2jWzTwA/DhARh20qTdMRyQcA0xDCbZ3KCJhl2RTATaHgo+6HLMv8+xXJy+qB3l8FGoB5CKHsXcRV1b6ZvZF8FBH3NKotoJlNkiQZFONdlLtJ3rufbouZPSdJMjwIbKDQEzBrClx7eC4i33Uepmk6JnnXaOQifzMAtdGoRApugYiMI1uqKkrRWAfZo9MxM1+UZzFewl8mN4nYdVM83L7BkwbXLUrF3sfBLQDQBbDy08x8vOohXyEE71lVq9emuEk+3gZa3XYroCvwFyjP8yHJDsnxwaU08GxvS2uFhw78BbzWrxXgMbsHAAAAAElFTkSuQmCC")}
\ No newline at end of file
views/default.handlebars
+97 -47
@@ -8,6 +8,7 @@
8 <meta name="format-detection" content="telephone=no" />
9 <link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS" />
10 <link type="text/css" href="styles/ol.css" media="screen" rel="stylesheet" title="CSS" />
11 + <link type="text/css" href="styles/ol3-contextmenu.min.css" media="screen" rel="stylesheet" title="CSS" />
12 <script type="text/javascript" src="scripts/common-0.0.1.js"></script>
13 <script type="text/javascript" src="scripts/meshcentral.js"></script>
14 <script type="text/javascript" src="scripts/amt-0.2.0.js"></script>
@@ -21,6 +22,7 @@
22 <script type="text/javascript" src="scripts/agent-desktop-0.0.2.js"></script>
23 <script type="text/javascript" src="scripts/filesaver.1.1.20151003.js"></script>
24 <script type="text/javascript" src="scripts/ol.js"></script>
25 + <script type="text/javascript" src="scripts/ol3-contextmenu.js"></script>
26 <title>MeshCentral</title>
27 </head>
28
@@ -1003,6 +1005,9 @@
1005 node.desc = message.event.node.desc;
1006 node.publicip = message.event.node.publicip;
1007 node.iploc = message.event.node.iploc;
1008 + node.wifiloc = message.event.node.wifiloc;
1009 + node.gpsloc = message.event.node.gpsloc;
1010 + node.userloc = message.event.node.userloc;
1011 if (message.event.node.agent != undefined) {
1012 if (node.agent == undefined) node.agent = {};
1013 if (message.event.node.agent.ver != undefined) { node.agent.ver = message.event.node.agent.ver; }
@@ -1027,6 +1032,8 @@
1032 drawNotifications();
1033 refreshDevice(node._id);
1034 updateMapMarkers();
1035 +
1036 + if ((currentNode == node) && (xxdialogMode != null) && (xxdialogTag == '@xxmap')) { p10showNodeLocationDialog(); }
1037 }
1038 break;
1039 }
@@ -1673,16 +1680,15 @@
1680 var boundingBox = null;
1681 for (var i in nodes) {
1682 var loc = map_parseNodeLoc(nodes[i]);
1676 - if (loc) { // Draw markers for devices with locations
1683 + var feature = xxmap.markersSource.getFeatureById(nodes[i]._id); // Remove if present
1684 + if ((loc != null) && ((nodes[i].meshid == selectedMesh) || (selectedMesh == undefined))) { // Draw markers for devices with locations
1685 lat = loc[0];
1686 lon = loc[1];
1687 + var type = loc[2];
1688 if (boundingBox == null) { boundingBox = [ lat, lon, lat, lon, 0 ]; } else { if (lat < boundingBox[0]) { boundingBox[0] = lat; } if (lon < boundingBox[1]) { boundingBox[1] = lon; } if (lat > boundingBox[2]) { boundingBox[2] = lat; } if (lon > boundingBox[3]) { boundingBox[3] = lon; } }
1680 - var feature = xxmap.markersSource.getFeatureById(nodes[i]._id);
1681 - if (nodes[i].meshid == selectedMesh || selectedMesh == undefined) {
1682 - if (feature == null || feature == undefined) { addFeature(nodes[i]); boundingBox[4] = 1; } else { updateFeature(nodes[i], feature); } // Update Feature
1683 - } else {
1684 - if (feature) { xxmap.markersSource.removeFeature(feature); } // Remove if it does not belong to that mesh
1685 - }
1689 + if (feature == null) { addFeature(nodes[i]); boundingBox[4] = 1; } else { updateFeature(nodes[i], feature); feature.setStyle(markerStyle(nodes[i], loc[2])); } // Update Feature
1690 + } else {
1691 + if (feature) { xxmap.markersSource.removeFeature(feature); }
1692 }
1693 }
1694 return boundingBox;
@@ -1692,10 +1698,15 @@
1698 var map_cm_popup = new ol.Overlay({ element: Q('xmap-info-window'), positioning: 'bottom-center', stopEvent: false });
1699
1700 // Edit Marker item
1695 - var map_cm_editMarker = { text: "Modify Node location", callback: function (obj) { modifyMarkerloc(obj.data); } };
1701 + var map_cm_editMarker = { text: "Modify node location", callback: function (obj) { modifyMarkerloc(obj.data); } };
1702 +
1703 + // Clear Marker item
1704 + var map_cm_clearMarker = { text: "Remove node location", callback: function (obj) {
1705 + meshserver.Send({ action: 'changedevice', nodeid: obj.data.a, userloc: [] }); // Clear the user position marker
1706 + }};
1707
1708 // Save Marker item
1698 - var map_cm_saveMarker = { text: "Save Node location", callback: function (obj) { saveMarkerloc(obj.data); } };
1709 + var map_cm_saveMarker = { text: "Save node location", callback: function (obj) { saveMarkerloc(obj.data); } };
1710
1711 // Build a context menu for a feature
1712 var map_cm_nodemenu_items = [
@@ -1724,9 +1735,14 @@
1735
1736 // Get the lat/lon from a node
1737 function map_parseNodeLoc(node) {
1727 - if (!node.iploc) return;
1728 - var loc = node.iploc.split(',');
1729 - return [parseFloat(loc[0]) + (stringToIntHash(node._id.substring(0, 20)) / 100000000000), parseFloat(loc[1]) + (stringToIntHash(node._id.substring(20)) / 100000000000)]
1738 + var loc = null, t = 0;
1739 + if (node.iploc) { loc = node.iploc; t = 1; }
1740 + if (node.wifiloc) { loc = node.wifiloc; t = 2; }
1741 + if (node.gpsloc) { loc = node.gpsloc; t = 3; }
1742 + if (node.userloc) { loc = node.userloc; t = 4; }
1743 + if ((loc == null) || (typeof loc != 'string')) return;
1744 + loc = loc.split(',');
1745 + return [ parseFloat(loc[0]) + (stringToIntHash(node._id.substring(0, 20)) / 100000000000), parseFloat(loc[1]) + (stringToIntHash(node._id.substring(20)) / 100000000000), t ]
1746 }
1747
1748 // Load the entire map
@@ -1792,7 +1808,6 @@
1808 }
1809 });
1810
1795 - /*
1811 // Initialize context menu for openlayers
1812 contextmenu = new ContextMenu({
1813 width: 160,
@@ -1805,20 +1820,18 @@
1820 var feature = xxmap.map.forEachFeatureAtPixel(evt.pixel, function(ft, l){ return ft; });
1821 xxmap.contextmenu.clear(); //Clear the context menu
1822 if (feature) {
1808 - var featId=feature.getId();
1809 - if (featId) { // Node feature will have an id
1810 - addContextMenuItems(feature);
1811 - }
1823 + var featId = feature.getId();
1824 + if (featId) { addContextMenuItems(feature); } // Node feature will have an id
1825 else { // If the feature is a pointer, Get its corresponding Node feature
1813 - var nodeFeature= getCorrespondingFeature(feature); //return the node feature associated to pointer.
1826 + var nodeFeature = getCorrespondingFeature(feature); //return the node feature associated to pointer.
1827 if (nodeFeature) { addContextMenuItems(nodeFeature); }
1828 else{ xxmap.contextmenu.extend(contextmenu_items); }
1829 }
1830 }
1831 else { xxmap.contextmenu.extend(contextmenu_items); }
1832 });
1833 + if (xxmap.contextmenu == null) { xxmap.contextmenu = contextmenu; }
1834 xxmap.map.addControl(xxmap.contextmenu);
1821 - */
1835 //addMeshOptions(); // Adds Mesh names to mesh dropdown
1836 } catch (e) {
1837 QV('viewselectmapoption', false);
@@ -1827,24 +1840,24 @@
1840 }
1841
1842 // Add feature on to Map for a Node
1830 - function addFeature(node, lat, lon){
1843 + function addFeature(node, lat, lon) {
1844 var existingfeature = getModifiedFeature(node._id); // Check if Corresponding feature was Modified ( Modifed feature are in active interactions list)
1845 if (existingfeature) { xxmap.markersSource.addFeature(existingfeature); } // Add that existing feature
1846 else { // Add new feature for this node
1847 if (!lat && !lon) { var loc = map_parseNodeLoc(node); lat = loc[0]; lon = loc[1]; }
1835 - var feature = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.transform([lon, lat], 'EPSG:4326','EPSG:3857')), name: node.name, status: node.conn, lat: lat, lon: lon });
1836 - feature.setId(node._id); // Set id for the device as nodeid
1837 - feature.setStyle(markerStyle(node));
1838 - xxmap.markersSource.addFeature(feature); // Add the feature to Marker Source
1848 + if ((lat < 90) && (lat > -90) && (lon < 180) && (lon > -180)) { // Check valid lat/lon
1849 + var feature = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.transform([lon, lat], 'EPSG:4326','EPSG:3857')), name: node.name, status: node.conn, lat: lat, lon: lon });
1850 + feature.setId(node._id); // Set id for the device as nodeid
1851 + feature.setStyle(markerStyle(node));
1852 + xxmap.markersSource.addFeature(feature); // Add the feature to Marker Source
1853 + }
1854 }
1855 }
1856
1857 // Removing any feature from map
1858 function removeFeature(node) {
1844 - if (node.iploc) {
1845 - var feature = xxmap.markersSource.getFeatureById(node._id);
1846 - if (feature) { xxmap.markersSource.removeFeature(feature); }
1847 - }
1859 + var feature = xxmap.markersSource.getFeatureById(node._id);
1860 + if (feature) { xxmap.markersSource.removeFeature(feature); }
1861 }
1862
1863 // Update feature
@@ -1870,6 +1883,7 @@
1883 function modifyMarkerloc(ft){
1884 var featid = ft.getId();
1885 if (featid) {
1886 + ft.setStyle(markerStyle(getNodeFromId(ft.a), 4)); // Switch to a user marker
1887 if ( !getActiveInteractions(ft)) {
1888 var dragInteration = new ol.interaction.Modify({
1889 features: new ol.Collection([ft]),
@@ -1891,16 +1905,25 @@
1905 removeInteraction(featid);
1906 var coord = ft.getGeometry().getCoordinates();
1907 var v = ol.proj.transform(coord, 'EPSG:3857', 'EPSG:4326');
1894 - meshserver.Send({ action: 'changelocation', nodeid: featid, value: v }); // Send them to server to save changes
1908 + var vx = [ v[1], v[0] ]; // Flip the coordinates around, lat/long
1909 + meshserver.Send({ action: 'changedevice', nodeid: featid, userloc: vx }); // Send them to server to save changes
1910 }
1911 }
1912 }
1913
1914 // Style the Markers
1900 - function markerStyle(node) {
1915 + function markerStyle(node, type) {
1916 + if (type == null) {
1917 + type = 0;
1918 + if (node.iploc) { type = 1; }
1919 + if (node.wifiloc) { type = 2; }
1920 + if (node.gpsloc) { type = 3; }
1921 + if (node.userloc) { type = 4; }
1922 + }
1923 + var types = ['', '-ip','-wifi','-gps','-user'];
1924 var color = connStateColor(node);
1925 var style = new ol.style.Style({
1903 - image: new ol.style.Icon({ color: color, anchor: [0.5, 1], src: 'images/mapmarker.png' })
1926 + image: new ol.style.Icon({ color: color, anchor: [0.5, 1], src: 'images/mapmarker' + types[type] + '.png' })
1927 //stroke: new ol.style.Stroke({ color: '#000', width: 20 })
1928 //text: new ol.style.Text({ text: 'bob!', textAlign: 'right', offsetX: -10, fill: new ol.style.Fill({ color: '#000' }), stroke: new ol.style.Stroke({ color: '#fff', width: 2 }) })
1929 });
@@ -1935,6 +1958,11 @@
1958 } else {
1959 map_cm_editMarker.data = feature;
1960 xxmap.contextmenu.push(map_cm_editMarker);
1961 + var node = getNodeFromId(feature.a);
1962 + if (node.userloc) {
1963 + map_cm_clearMarker.data = feature;
1964 + xxmap.contextmenu.push(map_cm_clearMarker);
1965 + }
1966 }
1967 map_cm_nodemenu_items.forEach(function (item){
1968 if (item.text == 'Zoom-in to extent' || item.text == 'Zoom-out to extent') { item.data = feature; }
@@ -2047,6 +2075,7 @@
2075 if (node) {
2076 var feature = markersSource.getFeatureById(i);
2077 var v = ol.proj.transform(coords, 'EPSG:3857', 'EPSG:4326');
2078 + var vx = [ v[1], v[0] ]; // Flip the coordinates around, lat/long
2079 if (button == 2) {
2080 if (feature) {
2081 feature.getGeometry().setCoordinates(coords);
@@ -2054,10 +2083,10 @@
2083 if (activeInteraction) {
2084 saveMarkerloc(feature);
2085 } else { // If this feature is not modified, then send updated coords to server.
2057 - meshserver.Send({ action: 'changelocation', nodeid: node._id, value: v }); // Send them to server to save changes
2086 + meshserver.Send({ action: 'changedevice', nodeid: node._id, value: vx }); // Send them to server to save changes
2087 }
2088 } else {
2060 - meshserver.Send({ action: 'changelocation', nodeid: node._id, value: v }); // This Node is not yet added to maps.
2089 + meshserver.Send({ action: 'changedevice', nodeid: node._id, value: vx }); // This Node is not yet added to maps.
2090 }
2091 }
2092 else if (button == 1) {
@@ -2065,11 +2094,11 @@
2094 feature.getGeometry().setCoordinates(coords);
2095 modifyMarkerloc(feature);
2096 } else {
2068 - if (!node.iploc) {
2097 + //if (map_parseNodeLoc(node.iploc) != null) {
2098 addFeature(node, v[0], v[1]);
2099 var newFeature = markersSource.getFeatureById(node._id);
2100 modifyMarkerloc(newFeature);
2072 - }
2101 + //}
2102 }
2103 }
2104 }
@@ -2438,7 +2467,7 @@
2467 if ((meshrights & 4) != 0) x += '<a style=cursor:pointer onclick=p10showDeleteNodeDialog("' + node._id + '")>Delete Device</a>';
2468 x += '</div><div style=font-size:x-small>';
2469 if (mesh.mtype == 2) x += '<a style=cursor:pointer onclick=p10showNodeNetInfoDialog("' + node._id + '")>Interfaces</a>&nbsp;';
2441 - if ((node.iploc) && (xxmap != null)) x += '<a style=cursor:pointer onclick=p10showNodeLocationDialog("' + node._id + '")>Location</a>&nbsp;';
2470 + if (xxmap != null) x += '<a style=cursor:pointer onclick=p10showNodeLocationDialog("' + node._id + '")>Location</a>&nbsp;';
2471 x += '</div><br>'
2472
2473 QH('p10html3', x);
@@ -2650,26 +2679,47 @@
2679 // Show current location
2680 var d2map = null;
2681 function p10showNodeLocationDialog() {
2653 - if (xxdialogMode) return;
2654 - var loc = currentNode.iploc.split(',');
2655 - var lat = parseFloat(loc[0]);
2656 - var lng = parseFloat(loc[1]);
2657 - //var x = '<div><a href="https://www.google.com/maps/preview/@' + lat + ',' + lng + ',12z" target=_blank>Open in Google maps</a></div>';
2658 - var x = '<div id=d2map style=width:100%;height:300px></div>';
2659 - setDialogMode(2, "Device Location", 1, null, x);
2682 + if ((xxdialogMode != null) && (xxdialogTag == '@xxmap')) { setDialogMode(0); } else { if (xxdialogMode) return; }
2683 + var markers = [], types = ['iploc', 'wifiloc', 'gpsloc', 'userloc'], boundingBox = null;
2684 +
2685 + for (var loctype in types) {
2686 + if (currentNode[types[loctype]] != null) {
2687 + var loc = currentNode[types[loctype]].split(','), lat = parseFloat(loc[0]), lon = parseFloat(loc[1]);
2688 + if ((lat < 90) && (lat > -90) && (lon < 180) && (lon > -180)) { // Check valid lat/lon
2689 + var deviceMark = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.fromLonLat([lon, lat])) });
2690 + deviceMark.setStyle(markerStyle(currentNode, parseInt(loctype) + 1));
2691 + markers.push(deviceMark);
2692 +
2693 + if (boundingBox == null) { boundingBox = [ lat, lon, lat, lon, 0 ]; } else { if (lat < boundingBox[0]) { boundingBox[0] = lat; } if (lon < boundingBox[1]) { boundingBox[1] = lon; } if (lat > boundingBox[2]) { boundingBox[2] = lat; } if (lon > boundingBox[3]) { boundingBox[3] = lon; } }
2694 + }
2695 + }
2696 + }
2697
2698 // Setup the device mark layer
2662 - var deviceMark = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.fromLonLat([lng, lat])) });
2663 - deviceMark.setStyle(markerStyle(currentNode));
2664 - var vectorSource = new ol.source.Vector({ features: [deviceMark] });
2699 + var vectorSource = new ol.source.Vector({ features: markers });
2700 var vectorLayer = new ol.layer.Vector({ source: vectorSource });
2701
2702 + //var x = '<div><a href="https://www.google.com/maps/preview/@' + lat + ',' + lng + ',12z" target=_blank>Open in Google maps</a></div>';
2703 + var x = '<div id=d2map style=width:100%;height:300px></div>';
2704 + setDialogMode(2, "Device Location", 1, null, x, '@xxmap');
2705 +
2706 + var clng = 0, clat = 0, zoom = 8;
2707 + if (boundingBox != null) {
2708 + var clat = (boundingBox[0] + boundingBox[2]) / 2;
2709 + var clng = (boundingBox[1] + boundingBox[3]) / 2;
2710 + var cscale = Math.max(Math.abs(boundingBox[0] - boundingBox[2]), Math.abs(boundingBox[1] - boundingBox[3]));
2711 + var i = 360, zoom = -2;
2712 + while (i > cscale) { zoom++; i = i / 2; }
2713 + }
2714 +
2715 + if (markers.length == 1) { zoom = 8; }
2716 +
2717 // Setup the map
2718 d2map = new ol.Map({
2719 target: 'd2map',
2720 interactions: ol.interaction.defaults({dragPan:false, mouseWheelZoom:false}),
2721 layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), vectorLayer ],
2672 - view: new ol.View({ center: ol.proj.fromLonLat([lng, lat]), zoom: 8 })
2722 + view: new ol.View({ center: ol.proj.fromLonLat([clng, clat]), zoom: zoom })
2723 });
2724 }
2725
webserver.js
+13 -1
@@ -1586,7 +1586,8 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
1586 {
1587 // Argument validation
1588 if ((command.nodeid == null) || (typeof command.nodeid != 'string') || (command.nodeid.split('/').length != 3) || (command.nodeid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
1589 -
1589 + if ((command.userloc) && (command.userloc.length != 2) && (command.userloc.length != 0)) return;
1590 +
1591 // Change the device
1592 obj.db.Get(command.nodeid, function (err, nodes) {
1593 if (nodes.length != 1) return;
@@ -1606,6 +1607,17 @@ module.exports.CreateWebServer = function (parent, db, args, secret, certificate
1607 if (command.icon && (command.icon != node.icon)) { change = 1; node.icon = command.icon; changes.push('icon'); }
1608 if (command.name && (command.name != node.name)) { change = 1; node.name = command.name; changes.push('name'); }
1609 if (command.host && (command.host != node.host)) { change = 1; node.host = command.host; changes.push('host'); }
1610 + if (command.userloc && ((node.userloc == null) || (command.userloc[0] != node.userloc[0]) || (command.userloc[1] != node.userloc[1]))) {
1611 + change = 1;
1612 + if ((command.userloc.length == 0) && (node.userloc)) {
1613 + delete node.userloc;
1614 + changes.push('location removed');
1615 + } else {
1616 + command.userloc.push((Math.floor((new Date()) / 1000)));
1617 + node.userloc = command.userloc.join(',');
1618 + changes.push('location');
1619 + }
1620 + }
1621 if (command.desc != null && (command.desc != node.desc)) { change = 1; node.desc = command.desc; changes.push('description'); }
1622 if (command.intelamt != null) {
1623 if ((command.intelamt.user != null) && (command.intelamt.pass != undefined) && ((command.intelamt.user != node.intelamt.user) || (command.intelamt.pass != node.intelamt.pass))) { change = 1; node.intelamt.user = command.intelamt.user; node.intelamt.pass = command.intelamt.pass; changes.push('Intel AMT credentials'); }