Started work on global map

This commit is contained in:
Ylian Saint-Hilaire 2017-08-28 15:57:25 -07:00
parent 41125c66ee
commit 95f88d1125
2 changed files with 135 additions and 114 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "meshcentral", "name": "meshcentral",
"version": "0.0.6-p", "version": "0.0.6-q",
"keywords": [ "keywords": [
"Remote Management", "Remote Management",
"Intel AMT", "Intel AMT",

View File

@ -102,29 +102,32 @@
<div id=p1 style=display:none> <div id=p1 style=display:none>
<h1>My Devices</h1> <h1>My Devices</h1>
<div style=width:100%;height:24px;background-color:#d3d9d6> <div style=width:100%;height:24px;background-color:#d3d9d6>
<div class=style7 style=width:84px;height:100%;float:left>&nbsp;</div>
<div class=h1 style=height:100%;float:left>&nbsp;</div> <div class=h1 style=height:100%;float:left>&nbsp;</div>
<div class=style14 style=height:100%;float:left> <div id=devListToolbar class=style14 style=height:100%;float:left>
&nbsp;&nbsp;<input type="button" id="SelectAllButton" onclick="selectallButtonFunction();" value="Select All" />&nbsp; &nbsp;&nbsp;<input type="button" id="SelectAllButton" onclick="selectallButtonFunction();" value="Select All" />&nbsp;
<input type="button" id="GroupActionButton" disabled="disabled" value="Group Action" onclick="groupActionFunction();" />&nbsp; <input type="button" id="GroupActionButton" disabled="disabled" value="Group Action" onclick="groupActionFunction();" />&nbsp;
<input id="SearchInput" type="text" style=width:120px placeholder=Search onchange="onSearchInputChanged()" onkeyup="onSearchInputChanged()" autocomplete=off onfocus="onSearchFocus(1)" onblur="onSearchFocus(0)" />&nbsp; <input id="SearchInput" type="text" style=width:120px placeholder=Search onchange="onSearchInputChanged()" onkeyup="onSearchInputChanged()" autocomplete=off onfocus="onSearchFocus(1)" onblur="onSearchFocus(0)" />&nbsp;
<input type="checkbox" id="HostnameCheckBox" onclick="onHostnameCheckBox()" /><span title="Show device hostnames">Hostname</span> <input type="checkbox" id="HostnameCheckBox" onclick="onHostnameCheckBox()" /><span title="Show device hostnames">Hostname</span>
</div> </div>
<div class="auto-style1" style="height: 100%; float: right"> <div class="auto-style1" style="height: 100%; float: right">
<div style="height: 100%; width: 4px; float: right; background-color: #ffffff"></div> <div style="height:100%;width:4px;float:right;background-color:#ffffff"></div>
<div class="h2" style="height: 100%; float: right;">&nbsp;</div> <div class=h2 style="height:100%;float:right">&nbsp;</div>
<div style="float: right"> <div style=float:right>
View
<select id=viewselect onchange=onDeviceViewChange()>
<option value=1>3 wide</option>
<option value=2>List</option>
<option value=3>Map</option>
</select>
</div>
<div style=float:right id=devListToolbarSort>
Sort Sort
<select id=sortselect onchange=onSortSelectChange()> <select id=sortselect onchange=onSortSelectChange()>
<option>Mesh</option> <option>Mesh</option>
<option>Power</option> <option>Power</option>
<option>Device</option> <option>Device</option>
</select> </select>
&nbsp;View &nbsp;
<select id=viewselect onchange=onDeviceViewChange()>
<option value=1>3 wide</option>
<option value=2>List</option>
</select>
</div> </div>
</div> </div>
</div> </div>
@ -142,6 +145,7 @@
<p></p> <p></p>
</div> </div>
<div id="xdevices" style="max-height:calc(100vh - 228px);overflow-y:auto;-webkit-overflow-scrolling:touch"></div> <div id="xdevices" style="max-height:calc(100vh - 228px);overflow-y:auto;-webkit-overflow-scrolling:touch"></div>
<div id="xdevicesmap" style="height:500px;width:100%;overflow:hidden"></div>
</div> </div>
<div id=p2 style=display:none> <div id=p2 style=display:none>
<h1>My Account</h1> <h1>My Account</h1>
@ -596,6 +600,7 @@
var features = {{{features}}}; var features = {{{features}}};
var serverPublicNamePort = "{{{serverDnsName}}}:{{{serverPublicPort}}}"; var serverPublicNamePort = "{{{serverDnsName}}}:{{{serverPublicPort}}}";
var amtScanResults = null; var amtScanResults = null;
var xxmap = null;
function startup() { function startup() {
// Guard against other site's top frames (web bugs). // Guard against other site's top frames (web bugs).
@ -657,6 +662,13 @@
var x = ''; var x = '';
for (var c = 1; c < 27; c++) x += "<option value='" + c + "'>Ctrl-" + String.fromCharCode(64 + c) + " (" + c + ")</option>"; for (var c = 1; c < 27; c++) x += "<option value='" + c + "'>Ctrl-" + String.fromCharCode(64 + c) + " (" + c + ")</option>";
QH('specialkeylist', x); QH('specialkeylist', x);
// Setup the map
xxmap = new ol.Map({
target: 'xdevicesmap',
layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ],
view: new ol.View({ center: ol.proj.fromLonLat([0, 0]), zoom: 1.8, minZoom: 1.8 })
});
} }
function getNodeFromId(id) { function getNodeFromId(id) {
@ -1134,119 +1146,128 @@
var deviceHeaderId = 0; var deviceHeaderId = 0;
var deviceHeaderCount; var deviceHeaderCount;
var deviceHeaders = {}; var deviceHeaders = {};
function updateDevices() { function updateDevices() {
var r = "", c = 0, current = null, count = 0, displayedMeshes = {}, view = Q('viewselect').value; var r = "", c = 0, current = null, count = 0, displayedMeshes = {}, view = Q('viewselect').value;
deviceHeaderId = 0; QV('xdevices', view < 3);
deviceHeaderCount = {}; QV('xdevicesmap', view == 3);
deviceHeaderTotal = 0; QV('devListToolbar', view < 3);
deviceHeaders = {}; QV('devListToolbarSort', view < 3);
deviceHeadersTitles = {}; if (view == 3) {
setTimeout( function() { xxmap.updateSize();}, 200);
// TODO
} else {
// 3 wide or list view
deviceHeaderId = 0;
deviceHeaderCount = {};
deviceHeaderTotal = 0;
deviceHeaders = {};
deviceHeadersTitles = {};
// Save the list of currently checked nodeid's // Save the list of currently checked nodeid's
var checkedNodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0; var checkedNodeids = [], elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
for (var i in elements) { if (elements[i].checked) { checkedNodeids.push(elements[i].value); } } for (var i in elements) { if (elements[i].checked) { checkedNodeids.push(elements[i].value); } }
// Go thru the list of nodes and display them // Go thru the list of nodes and display them
for (var i in nodes) { for (var i in nodes) {
if (nodes[i].v == false) continue; if (nodes[i].v == false) continue;
var mesh2 = meshes[nodes[i].meshid], meshlinks = mesh2.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()]; var mesh2 = meshes[nodes[i].meshid], meshlinks = mesh2.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()];
if (meshlinks == undefined) continue; if (meshlinks == undefined) continue;
if (sort == 0) { if (sort == 0) {
// Mesh header // Mesh header
if (nodes[i].meshid != current) { if (nodes[i].meshid != current) {
deviceHeaderSet(); deviceHeaderSet();
var extra = ''; var extra = '';
if (meshes[nodes[i].meshid].mtype == 1) { extra = '<span class=devHeaderx>, Intel&reg; AMT only</span>'; } if (meshes[nodes[i].meshid].mtype == 1) { extra = '<span class=devHeaderx>, Intel&reg; AMT only</span>'; }
var meshrights = meshlinks.rights; var meshrights = meshlinks.rights;
if ((view == 1) && (current != null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } r += '</tr></table>'; } if ((view == 1) && (current != null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } r += '</tr></table>'; }
r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt><span style=float:right>';
r += getMeshActions(mesh2, meshrights);
r += '</span><span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + nodes[i].meshid + '")>' + EscapeHtml(meshes[nodes[i].meshid].name) + '</span>' + extra + '<span id=DevxHeader' + deviceHeaderId + ' class=devHeaderx></span></td></tr><tr>';
current = nodes[i].meshid;
displayedMeshes[current] = 1;
c = 0;
}
} else if (sort == 1) {
// Power header
if (nodes[i].pwr !== current) {
deviceHeaderSet();
if ((view == 1) && (current !== null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } r += '</tr></table>'; }
r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt><span>' + PowerStateStr2(nodes[i].pwr) + '</span><span id=DevxHeader' + deviceHeaderId + ' class="devHeaderx"></span></td></tr><tr>';
current = nodes[i].pwr;
c = 0;
}
} else if (sort == 2) {
// Device header
if (current == null) { r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr>'; current = '1'; }
}
// Node positioning
if ((view == 1) && (c > 2)) { r += '</tr><tr>'; c = 0; }
c++;
count++;
var title = EscapeHtml(nodes[i].name);
if (title.length == 0) { title = '<i>None</i>'; }
if ((nodes[i].host != undefined) && (nodes[i].host.length > 0)) { title += " / " + EscapeHtml(nodes[i].host); }
var name = EscapeHtml(nodes[i].name);
if (showHostnames == true && nodes[i].host != undefined) name = EscapeHtml(nodes[i].host);
if (name.length == 0) { name = '<i>None</i>'; }
// Node
var icon = nodes[i].icon;
var nodestate = NodeStateStr(nodes[i]);
if ((!nodes[i].conn) || (nodes[i].conn == 0)) { icon += ' gray'; }
if (view == 1) {
r += '<td><div id=devs style=width:301px;height:50px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + nodes[i].meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + nodes[i]._id + ' type=checkbox></div><div style=height:100%;cursor:pointer onclick=gotoDevice(\'' + nodes[i]._id + '\')><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 title="' + title + '">' + name + '</div><div>' + nodestate + '</div></div><div class=g2></div></div></div></div></td>';
} else {
r += '<td><div id=devs style=width:924px;height:20px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:2px><input class="' + nodes[i].meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + nodes[i]._id + ' type=checkbox></div><div style=height:100%;cursor:pointer onclick=gotoDevice(\'' + nodes[i]._id + '\')><div class="j' + icon + '" style=width:16px;float:left;margin-top:3px></div><div style=height:100%><div class=g1></div><div class=e2 style=width:858px><div style=float:right;margin-top:1px>' + nodestate + '</div><div style=margin-top:1px title="' + title + '">' + name + '</div></div><div class=g2></div></div></div></div></td></tr><tr>';
}
deviceHeaderTotal++;
if (typeof deviceHeaderCount[nodes[i].state] == 'undefined') { deviceHeaderCount[nodes[i].state] = 1; } else { deviceHeaderCount[nodes[i].state]++; }
}
if ((view == 1) && (c == 2)) r += '<td><div style=width:301px></div></td>'; // Adds device padding
// Display all empty meshes, we need to do this because users can add devices to these at any time.
if (sort == 0 && Q('SearchInput').value == '') {
for (var i in meshes) {
var mesh = meshes[i], meshlink = mesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()];
if (meshlink != undefined) {
var meshrights = meshlink.rights;
if (displayedMeshes[mesh._id] == undefined) {
if (current != '') { r += '</tr></table>'; }
r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt><span style=float:right>'; r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt><span style=float:right>';
r += getMeshActions(mesh, meshrights); r += getMeshActions(mesh2, meshrights);
r += '</span><span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span></td></tr><tr>'; r += '</span><span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + nodes[i].meshid + '")>' + EscapeHtml(meshes[nodes[i].meshid].name) + '</span>' + extra + '<span id=DevxHeader' + deviceHeaderId + ' class=devHeaderx></span></td></tr><tr>';
if (mesh.mtype == 1) { current = nodes[i].meshid;
r += '<td><div style=padding:10px><i>No Intel&reg; AMT devices in this mesh'; displayedMeshes[current] = 1;
if ((meshrights & 4) != 0) { r += ', <a style=cursor:pointer onclick=addDeviceToMesh(\"' + mesh._id + '\")>add one</a>'; } c = 0;
}
} else if (sort == 1) {
// Power header
if (nodes[i].pwr !== current) {
deviceHeaderSet();
if ((view == 1) && (current !== null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } r += '</tr></table>'; }
r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt><span>' + PowerStateStr2(nodes[i].pwr) + '</span><span id=DevxHeader' + deviceHeaderId + ' class="devHeaderx"></span></td></tr><tr>';
current = nodes[i].pwr;
c = 0;
}
} else if (sort == 2) {
// Device header
if (current == null) { r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr>'; current = '1'; }
}
// Node positioning
if ((view == 1) && (c > 2)) { r += '</tr><tr>'; c = 0; }
c++;
count++;
var title = EscapeHtml(nodes[i].name);
if (title.length == 0) { title = '<i>None</i>'; }
if ((nodes[i].host != undefined) && (nodes[i].host.length > 0)) { title += " / " + EscapeHtml(nodes[i].host); }
var name = EscapeHtml(nodes[i].name);
if (showHostnames == true && nodes[i].host != undefined) name = EscapeHtml(nodes[i].host);
if (name.length == 0) { name = '<i>None</i>'; }
// Node
var icon = nodes[i].icon;
var nodestate = NodeStateStr(nodes[i]);
if ((!nodes[i].conn) || (nodes[i].conn == 0)) { icon += ' gray'; }
if (view == 1) {
r += '<td><div id=devs style=width:301px;height:50px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + nodes[i].meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + nodes[i]._id + ' type=checkbox></div><div style=height:100%;cursor:pointer onclick=gotoDevice(\'' + nodes[i]._id + '\')><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 title="' + title + '">' + name + '</div><div>' + nodestate + '</div></div><div class=g2></div></div></div></div></td>';
} else {
r += '<td><div id=devs style=width:924px;height:20px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:2px><input class="' + nodes[i].meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + nodes[i]._id + ' type=checkbox></div><div style=height:100%;cursor:pointer onclick=gotoDevice(\'' + nodes[i]._id + '\')><div class="j' + icon + '" style=width:16px;float:left;margin-top:3px></div><div style=height:100%><div class=g1></div><div class=e2 style=width:858px><div style=float:right;margin-top:1px>' + nodestate + '</div><div style=margin-top:1px title="' + title + '">' + name + '</div></div><div class=g2></div></div></div></div></td></tr><tr>';
}
deviceHeaderTotal++;
if (typeof deviceHeaderCount[nodes[i].state] == 'undefined') { deviceHeaderCount[nodes[i].state] = 1; } else { deviceHeaderCount[nodes[i].state]++; }
}
if ((view == 1) && (c == 2)) r += '<td><div style=width:301px></div></td>'; // Adds device padding
// Display all empty meshes, we need to do this because users can add devices to these at any time.
if (sort == 0 && Q('SearchInput').value == '') {
for (var i in meshes) {
var mesh = meshes[i], meshlink = mesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()];
if (meshlink != undefined) {
var meshrights = meshlink.rights;
if (displayedMeshes[mesh._id] == undefined) {
if (current != '') { r += '</tr></table>'; }
r += '<table style=width:100%;padding-top:4px cellpadding=0 cellspacing=0><tr><td colspan=3 class=DevSt><span style=float:right>';
r += getMeshActions(mesh, meshrights);
r += '</span><span id=MxMESH style=cursor:pointer onclick=gotoMesh("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span></td></tr><tr>';
if (mesh.mtype == 1) {
r += '<td><div style=padding:10px><i>No Intel&reg; AMT devices in this mesh';
if ((meshrights & 4) != 0) { r += ', <a style=cursor:pointer onclick=addDeviceToMesh(\"' + mesh._id + '\")>add one</a>'; }
}
if (mesh.mtype == 2) {
r += '<td><div style=padding:10px><i>No devices in this mesh';
if ((meshrights & 4) != 0) { r += ', <a style=cursor:pointer onclick=addAgentToMesh(\"' + mesh._id + '\")>add one</a>'; }
}
r += '.</i></div></td>';
current = mesh._id;
count++;
} }
if (mesh.mtype == 2) {
r += '<td><div style=padding:10px><i>No devices in this mesh';
if ((meshrights & 4) != 0) { r += ', <a style=cursor:pointer onclick=addAgentToMesh(\"' + mesh._id + '\")>add one</a>'; }
}
r += '.</i></div></td>';
current = mesh._id;
count++;
} }
} }
} }
r += '</tr></table><div style=height:1px></div>'; // This height of 1 div fixes a problem in Linux firefox browsers
QH('xdevices', r);
deviceHeaderSet();
QV('NoNodesPanel', count == 0);
// Re-check nodeid's
var elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
for (var i in elements) { elements[i].checked = (checkedNodeids.indexOf(elements[i].value) >= 0); }
for (var i in deviceHeaders) { QH(i, deviceHeaders[i]); }
for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
p1updateInfo();
} }
r += '</tr></table><div style=height:1px></div>'; // This height of 1 div fixes a problem in Linux firefox browsers
QH('xdevices', r);
deviceHeaderSet();
QV('NoNodesPanel', count == 0);
// Re-check nodeid's
var elements = document.getElementsByClassName("DeviceCheckbox"), checkcount = 0;
for (var i in elements) { elements[i].checked = (checkedNodeids.indexOf(elements[i].value) >= 0); }
for (var i in deviceHeaders) { QH(i, deviceHeaders[i]); }
for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
p1updateInfo();
} }
function getMeshActions(mesh, meshrights) { function getMeshActions(mesh, meshrights) {