More web application UI improvements.
Ylian Saint-Hilaire committed
Apr 15, 2020 at 19:42 UTC
e58838dfe868d619c9c2be71e6ab040b639792c3
5 files changed
+119
-95
meshcentral.js
+1
-7
@@ -2458,13 +2458,7 @@ function mainStart() {
2458
if (require('os').platform() == 'win32') { modules.push('node-windows'); if (sspi == true) { modules.push('node-sspi'); } } // Add Windows modules
2459
if (ldap == true) { modules.push('ldapauth-fork'); }
2460
if (recordingIndex == true) { modules.push('image-size'); } // Need to get the remote desktop JPEG sizes to index the recodring file.
2461
- if (config.letsencrypt != null) {
2462
- if (config.letsencrypt.lib == 'greenlock') {
2463
- if ((nodeVersion < 10) || (require('crypto').generateKeyPair == null)) { addServerWarning("Let's Encrypt support requires Node v10.12 or higher.", !args.launch); } else { modules.push('greenlock@4.0.4'); }
2464
- } else {
2465
- if (nodeVersion < 8) { addServerWarning("Let's Encrypt support requires Node v8.x or higher.", !args.launch); } else { modules.push('acme-client'); }
2466
- }
2467
- } // Add Greenlock Module or acme-client module
2461
+ if (config.letsencrypt != null) { if (nodeVersion < 8) { addServerWarning("Let's Encrypt support requires Node v8.x or higher.", !args.launch); } else { modules.push('acme-client'); } } // Add acme-client module
2462
if (config.settings.mqtt != null) { modules.push('aedes'); } // Add MQTT Modules
2463
if (config.settings.mysql != null) { modules.push('mysql'); } // Add MySQL, official driver.
2464
if (config.settings.mongodb != null) { modules.push('mongodb'); } // Add MongoDB, official driver.
meshuser.js
+6
-1
@@ -3081,7 +3081,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3081
if ((typeof command.icon == 'number') && (command.icon != node.icon)) { change = 1; node.icon = command.icon; changes.push('icon'); }
3082
if ((typeof command.name == 'string') && (command.name != node.name)) { change = 1; node.name = command.name; changes.push('name'); }
3083
if ((typeof command.host == 'string') && (command.host != node.host)) { change = 1; node.host = command.host; changes.push('host'); }
3084
- if (typeof command.consent == 'number') { if (((command.consent != 0) && ((node.consent == null) || (node.consent == 0))) || ((command.consent == 0) && (node.consent != null) && (node.consent != 0))) { change = 1; if (command.consent == 0) { delete node.consent; } else { node.consent = command.consent; } changes.push('consent'); } }
3084
+ if (typeof command.consent == 'number') {
3085
+ var oldConsent = node.consent;
3086
+ if (command.consent != node.consent) { node.consent = command.consent; }
3087
+ if (command.consent == 0) { delete node.consent; }
3088
+ if (oldConsent != node.consent) { change = 1; changes.push('consent'); }
3089
+ }
3090
3091
if ((typeof command.rdpport == 'number') && (command.rdpport > 0) && (command.rdpport < 65536)) {
3092
if ((command.rdpport == 3389) && (node.rdpport != null)) {
package.json
+1
-1
@@ -1,6 +1,6 @@
1
{
2
"name": "meshcentral",
3
- "version": "0.5.1-v",
3
+ "version": "0.5.1-w",
4
"keywords": [
5
"Remote Management",
6
"Intel AMT",
translate/translate.json
+27
-16
@@ -3924,7 +3924,12 @@
3924
},
3925
{
3926
"en": "Ask Consent",
3927
- "en": "Vraag toestemming",
3927
+ "xloc": [
3928
+ "default.handlebars->deskConnectContextMenu->cxdeskuc->0"
3929
+ ]
3930
+ },
3931
+ {
3932
+ "en": "Ask Consent + Bar",
3933
"xloc": [
3934
"default.handlebars->deskConnectContextMenu->cxdeskuc->0"
3935
]
@@ -8207,7 +8212,7 @@
8212
"en": "Devices",
8213
"nl": "Apparaten",
8214
"xloc": [
8210
- "default.handlebars->29->1441",
8215
+ "default.handlebars->29->1443",
8216
"default.handlebars->29->1465"
8217
]
8218
},
@@ -8793,18 +8798,7 @@
8798
]
8799
},
8800
{
8796
- "cs": "Duplikovat agenta",
8797
- "de": "Agent-Duplikat",
8798
- "en": "Duplicate agent",
8799
- "es": "Agente duplicado",
8800
- "fr": "Cloner l'agent",
8801
- "hi": "डुप्लीकेट एजेंट",
8802
- "ja": "重複エージェント",
8803
- "ko": "중복 에이전트",
8804
- "nl": "Duplicaat Agent",
8805
- "pt": "Agente duplicado",
8806
- "ru": "Скопировать агент",
8807
- "zh-chs": "代理重複",
8801
+ "en": "Duplicate Agent",
8802
"xloc": [
8803
"default.handlebars->29->1623"
8804
]
@@ -8843,6 +8837,20 @@
8837
"default.handlebars->29->1457"
8838
]
8839
},
8840
+ {
8841
+ "cs": "Duplikovat agenta",
8842
+ "de": "Agent-Duplikat",
8843
+ "en": "Duplicate agent",
8844
+ "es": "Agente duplicado",
8845
+ "fr": "Cloner l'agent",
8846
+ "hi": "डुप्लीकेट एजेंट",
8847
+ "ja": "重複エージェント",
8848
+ "ko": "중복 에이전트",
8849
+ "nl": "Duplicaat Agent",
8850
+ "pt": "Agente duplicado",
8851
+ "ru": "Скопировать агент",
8852
+ "zh-chs": "代理重複"
8853
+ },
8854
{
8855
"cs": "Délka trvání",
8856
"de": "Dauer",
@@ -26413,7 +26421,7 @@
26421
"ru": "Пользователи",
26422
"zh-chs": "用戶數",
26423
"xloc": [
26416
- "default.handlebars->29->1443",
26424
+ "default.handlebars->29->1441",
26425
"default.handlebars->29->1463",
26426
"default.handlebars->29->1642",
26427
"default.handlebars->container->topbar->1->1->UsersSubMenuSpan->UsersSubMenu->1->0->UsersGeneral"
@@ -26710,6 +26718,9 @@
26718
"default.handlebars->29->1028"
26719
]
26720
},
26721
+ {
26722
+ "en": "Vraag toestemming"
26723
+ },
26724
{
26725
"cs": "VAROVÁNÍ: ",
26726
"de": "WARNUNG: ",
@@ -29515,4 +29526,4 @@
29526
]
29527
}
29528
]
29518
-}
29529
+}
\ No newline at end of file
views/default.handlebars
+84
-70
@@ -70,6 +70,7 @@
70
<div id="cxtermps" class="cmtext" onclick="cmtermaction(100,event)">Login Shell</div>
71
</div>
72
<div id="deskConnectContextMenu" class="contextMenu noselect" style="display:none;min-width:0px">
73
+ <div id="cxdeskuc" class="cmtext" onclick="cmdeskaction(1,event)"><b>Ask Consent + Bar</b></div>
74
<div id="cxdeskuc" class="cmtext" onclick="cmdeskaction(1,event)"><b>Ask Consent</b></div>
75
</div>
76
<div id="altPortContextMenu" class="contextMenu noselect" style="display:none;min-width:0px">
@@ -4105,7 +4106,8 @@
4106
}
4107
4108
function cmdeskaction(action) {
4108
- if (action == 1) { connectDesktop(null, 3, null, 0x0008); } // Do remote desktop connection using consent prompt
4109
+ if (action == 1) { connectDesktop(null, 3, null, 0x0008 + 0x0040); } // Do remote desktop connection using Consent Prompt + Tool bar
4110
+ if (action == 2) { connectDesktop(null, 3, null, 0x0008); } // Do remote desktop connection using Consent Prompt
4111
}
4112
4113
function cmaltportaction(action) {
@@ -4989,7 +4991,9 @@
4991
{{{StartGeoLocationJS}}}
4992
if (xxmap != null) x += '<a href=# onclick=p10showNodeLocationDialog("' + node._id + '") title=\"' + "Show device locations information" + '\">' + "Location" + '</a> ';
4993
{{{EndGeoLocationJS}}}
4992
- if ((terminalAccess) && ((meshrights & 8) != 0) && (node.agent != null)) x += '<a href=# onclick=p10showMeshCmdDialog(1,"' + node._id + '") title=\"' + "Traffic router used to connect to a device thru this server" + '.\">' + "MeshCmd" + '</a> ';
4994
+ if ((userinfo.siteadmin == 0xFFFFFFFF) || ((userinfo.siteadmin & 128) == 0)) { // Check if we should view tools
4995
+ if ((terminalAccess) && ((meshrights & 8) != 0) && (node.agent != null)) x += '<a href=# onclick=p10showMeshCmdDialog(1,"' + node._id + '") title=\"' + "Traffic router used to connect to a device thru this server" + '.\">' + "MeshCmd" + '</a> ';
4996
+ }
4997
if ((args.xterm === 0) && (node.agent) && ((node.agent.caps & 2) != 0) && ((meshrights & 8) != 0) && ((meshrights == 0xFFFFFFFF) || ((meshrights & 512) == 0))) { x += '<a href=# onclick=p10openxterm(event,"' + node._id + '") title=\"' + "Open XTerm terminal" + '\">' + "XTerm" + '</a> '; }
4998
4999
// RDP link, show this link only of the remote machine is Windows.
@@ -5118,10 +5122,10 @@
5122
if ((meshrights & 2) != 0) {
5123
if (ugroup) {
5124
trash = '<a href=# onclick=\'return p30removeUserFromNode(event,"' + encodeURIComponent(userid) + '")\' title=\"' + "Remove user group rights to this device group" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>';
5121
- rights = '<div style=cursor:pointer onclick=p20showAddMeshUserDialog(6,\"' + encodeURIComponent(userid) + '\")>' + rights + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></div>';
5125
+ rights = '<span style=cursor:pointer onclick=p20showAddMeshUserDialog(6,\"' + encodeURIComponent(userid) + '\")>' + rights + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></span>';
5126
} else {
5127
trash = '<a href=# onclick=\'return p30removeUserFromNode(event,"' + encodeURIComponent(userid) + '")\' title=\"' + "Remove user rights to this device group" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>';
5124
- rights = '<div style=cursor:pointer onclick=p20showAddMeshUserDialog(5,\"' + encodeURIComponent(userid) + '\")>' + rights + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></div>';
5128
+ rights = '<span style=cursor:pointer onclick=p20showAddMeshUserDialog(5,\"' + encodeURIComponent(userid) + '\")>' + rights + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></span>';
5129
}
5130
}
5131
if (users != null) {
@@ -8363,7 +8367,7 @@
8367
var trash = '', r = sortedusers[i].rights, rights = makeDeviceGroupRightsString(r), icon = 2;
8368
if ((sortedusers[i].id != userinfo._id) && (meshrights == 0xFFFFFFFF || (((meshrights & 2) != 0)))) {
8369
trash = '<a href=# onclick=\'return p20deleteUser(event,"' + encodeURIComponent(sortedusers[i].id) + '")\' title=\"' + "Remove user rights to this device group" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>';
8366
- rights = '<div tabindex=0 style=cursor:pointer onclick=p20viewuser("' + encodeURIComponent(sortedusers[i].id) + '") onkeypress="if (event.key==\'Enter\') p20viewuser(\'' + encodeURIComponent(sortedusers[i].id) + '\')">' + rights + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></div>';
8370
+ rights = '<span tabindex=0 style=cursor:pointer onclick=p20viewuser("' + encodeURIComponent(sortedusers[i].id) + '") onkeypress="if (event.key==\'Enter\') p20viewuser(\'' + encodeURIComponent(sortedusers[i].id) + '\')">' + rights + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></span>';
8371
}
8372
if (sortedusers[i].id.startsWith('ugrp/')) { icon = 4; }
8373
var username = EscapeHtml(decodeURIComponent(sortedusers[i].name));
@@ -8576,44 +8580,50 @@
8580
x += addHtmlValue("User Names", '<input id=dp20username style=width:230px maxlength=32 onchange=p20validateAddMeshUserDialog() onkeyup=p20validateAddMeshUserDialog() placeholder="user1, user2, user3" />');
8581
x += '<div id=dp20usersuggest class=suggestionBox style=\'top:30px;left:130px;display:none\'></div>';
8582
x += '</div><br>';
8579
- } else if (userid === 1) {
8583
+ } else if (userid == 1) {
8584
var y = '';
8585
if (selected == null) {
8582
- for (var i in meshes) { if ((currentUser.links == null) || (currentUser.links[i] == null)) { y += '<option value=' + encodeURIComponent(i) + '>' + EscapeHtml(meshes[i].name) + '</option>'; } }
8586
+ var omeshs = getOrderedList(meshes, 'name');
8587
+ for (var i in omeshs) { if ((currentUser.links == null) || (currentUser.links[omeshs[i]._id] == null)) { y += '<option value=' + encodeURIComponent(omeshs[i]._id) + '>' + EscapeHtml(omeshs[i].name) + '</option>'; } }
8588
} else {
8589
y += '<option value=' + selected + '>' + EscapeHtml(meshes[decodeURIComponent(selected)].name) + '</option>';
8590
}
8591
x += addHtmlValue("Device Group", '<div style=width:230px;margin:0;padding:0><select onchange=p20validateAddMeshUserDialog() id=dp2groupid style=width:100%' + (selected?' disabled':'') + '>' + y + '</select></div>');
8587
- } else if (userid === 2) {
8592
+ } else if (userid == 2) {
8593
if (usergroups == null) return;
8594
var y = '';
8590
- for (var i in usergroups) { if ((currentMesh.links == null) || (currentMesh.links[i] == null)) { y += '<option value=' + encodeURIComponent(i) + '>' + EscapeHtml(usergroups[i].name) + '</option>'; } }
8595
+ var ousergroups = getOrderedList(usergroups, 'name');
8596
+ for (var i in ousergroups) { if ((currentMesh.links == null) || (currentMesh.links[ousergroups[i]._id] == null)) { y += '<option value=' + encodeURIComponent(ousergroups[i]._id) + '>' + EscapeHtml(ousergroups[i].name) + '</option>'; } }
8597
x += addHtmlValue("User Group", '<div style=width:230px;margin:0;padding:0><select onchange=p20validateAddMeshUserDialog() id=dp2groupid style=width:100%>' + y + '</select></div>');
8592
- } else if (userid === 6) {
8598
+ } else if (userid == 6) {
8599
if (usergroups == null) return;
8600
var y = '';
8601
if (selected == null) {
8596
- for (var i in usergroups) { if ((currentNode.links == null) || (currentNode.links[i] == null)) { y += '<option value=' + encodeURIComponent(i) + '>' + EscapeHtml(usergroups[i].name) + '</option>'; } }
8602
+ var ousergroups = getOrderedList(usergroups, 'name');
8603
+ for (var i in ousergroups) { if ((currentNode.links == null) || (currentNode.links[ousergroups[i]._id] == null)) { y += '<option value=' + encodeURIComponent(ousergroups[i]._id) + '>' + EscapeHtml(ousergroups[i].name) + '</option>'; } }
8604
} else {
8605
y += '<option value=' + selected + '>' + EscapeHtml(usergroups[decodeURIComponent(selected)].name) + '</option>';
8606
}
8607
x += addHtmlValue("User Group", '<div style=width:230px;margin:0;padding:0><select onchange=p20validateAddMeshUserDialog() id=dp2groupid style=width:100%' + (selected?' disabled':'') + '>' + y + '</select></div>');
8601
- } else if (userid === 3) {
8608
+ } else if (userid == 3) {
8609
var y = '';
8610
if (selected) { selected = decodeURIComponent(selected); }
8604
- for (var i in meshes) { if ((selected != null) || (currentUserGroup.links == null) || (currentUserGroup.links[i] == null)) { y += '<option value=' + encodeURIComponent(i) + ((selected == i)?' selected':' ') + '>' + EscapeHtml(meshes[i].name) + '</option>'; } }
8605
- x += addHtmlValue("Device Group", '<div style=width:230px;margin:0;padding:0><select onchange=p20validateAddMeshUserDialog() id=dp2groupid style=width:100%>' + y + '</select></div>');
8606
- } else if ((userid === 4) || (userid == 7)) {
8611
+ var omeshs = getOrderedList(meshes, 'name');
8612
+ for (var i in omeshs) { if ((selected != null) || (currentUserGroup.links == null) || (currentUserGroup.links[i] == null)) { y += '<option value=' + encodeURIComponent(omeshs[i]._id) + ((selected == omeshs[i]._id)?' selected':' ') + '>' + EscapeHtml(omeshs[i].name) + '</option>'; } }
8613
+ x += addHtmlValue("Device Group", '<div style=width:230px;margin:0;padding:0><select onchange=p20validateAddMeshUserDialog(' + userid + ') id=dp2groupid style=width:100%>' + y + '</select></div>');
8614
+ } else if ((userid == 4) || (userid == 7)) {
8615
var y = '', selectedMeshId = null, selectedNode = null;
8616
if (selected != null) { selectedNode = getNodeFromId(decodeURIComponent(selected)); if (selectedNode != null) { selectedMeshId = selectedNode.meshid; } }
8609
- for (var i in meshes) {
8610
- if ((meshes[i].links[userinfo._id] != null) && (meshes[i].links[userinfo._id].rights & 7)) { // Only show device groups that we have user administrator for.
8611
- if (selectedMeshId == null) { selectedMeshId = meshes[i]._id; } y += '<option value=' + encodeURIComponent(meshes[i]._id) + ((selectedMeshId == meshes[i]._id)?' selected':' ') + '>' + EscapeHtml(meshes[i].name) + '</option>';
8617
+ var omeshs = getOrderedList(meshes, 'name');
8618
+ for (var i in omeshs) {
8619
+ if ((omeshs[i].links[userinfo._id] != null) && (omeshs[i].links[userinfo._id].rights & 7)) { // Only show device groups that we have user administrator for.
8620
+ if (selectedMeshId == null) { selectedMeshId = omeshs[i]._id; } y += '<option value=' + encodeURIComponent(omeshs[i]._id) + ((selectedMeshId == omeshs[i]._id)?' selected':' ') + '>' + EscapeHtml(omeshs[i].name) + '</option>';
8621
}
8622
}
8623
x += addHtmlValue("Device Group", '<div style=width:230px;margin:0;padding:0><select onchange=p20changeMeshAddMeshUserDialog(' + userid + ') id=dp2meshid style=width:100%>' + y + '</select></div>');
8624
y = '';
8616
- for (var i in nodes) { if (nodes[i].meshid == selectedMeshId) { y += '<option value=' + encodeURIComponent(nodes[i]._id) + ((selectedNode == nodes[i])?' selected':' ') + '>' + EscapeHtml(nodes[i].name) + '</option>'; } }
8625
+ var onodes = getOrderedList(nodes, 'name');
8626
+ for (var i in onodes) { if (onodes[i].meshid == selectedMeshId) { y += '<option value=' + encodeURIComponent(onodes[i]._id) + ((selectedNode == onodes[i])?' selected':' ') + '>' + EscapeHtml(onodes[i].name) + '</option>'; } }
8627
x += addHtmlValue("Device", '<div style=width:230px;margin:0;padding:0><select onchange=p20validateAddMeshUserDialog(' + userid + ') id=dp2nodeid style=width:100%>' + y + '</select></div>');
8628
} else {
8629
userid = decodeURIComponent(userid);
@@ -8726,11 +8736,11 @@
8736
return false;
8737
}
8738
8729
- function p20changeMeshAddMeshUserDialog() {
8739
+ function p20changeMeshAddMeshUserDialog(userid) {
8740
var y = '', meshid = decodeURIComponent(Q('dp2meshid').value);
8741
for (var i in nodes) { if (nodes[i].meshid == meshid) { y += '<option value=' + encodeURIComponent(nodes[i]._id) + '>' + EscapeHtml(nodes[i].name) + '</option>'; } }
8742
QH('dp2nodeid', y);
8733
- p20validateAddMeshUserDialog(4);
8743
+ p20validateAddMeshUserDialog(userid);
8744
}
8745
8746
function p20setname(name) {
@@ -8749,6 +8759,7 @@
8759
if (updateId === 4) {
8760
// Update user device rights
8761
var devrights = 0, nodeid = decodeURIComponent(Q('dp2nodeid').value);
8762
+ console.log('nodeid', nodeid);
8763
if ((nodeid != '') && (currentUser.links != null) && (currentUser.links[nodeid] != null)) { devrights = currentUser.links[nodeid].rights; }
8764
Q('p20remotecontrol').checked = ((devrights & 8) != 0);
8765
Q('p20meshagentconsole').checked = ((devrights & 16) != 0);
@@ -10103,7 +10114,7 @@
10114
} else {
10115
// Display the groups using the sorted list
10116
x += '<table class=p3usersTable cellpadding=0 cellspacing=0>';
10106
- x += '<th>' + "Name" + '<th style=width:80px>' + "Devices" + '<th style=width:80px>' + "Device Groups" + '<th style=width:80px>' + "Users";
10117
+ x += '<th>' + "Name" + '<th style=width:80px>' + "Users" + '<th style=width:80px>' + "Device Groups" + '<th style=width:80px>' + "Devices";
10118
for (var i in sortedGroups) { x += addUserGroupHtml(sortedGroups[i]); }
10119
x += '</table>';
10120
QV('DuplicateUserGroupButton', true);
@@ -10127,7 +10138,7 @@
10138
x += '<div class=baricon><input class=UserGroupCheckbox value=' + encodeURIComponent(group._id) + ' onclick=p50updateInfo() type=checkbox></div>';
10139
x += '<div class=baricon onclick=gotoUserGroup(\"' + encodeURIComponent(group._id) + '\")><div class=m4></div></div>';
10140
x += '<div class=g1 onclick=gotoUserGroup(\"' + encodeURIComponent(group._id) + '\")></div><div class=g2 onclick=gotoUserGroup(\"' + encodeURIComponent(group._id) + '\")></div>';
10130
- x += '<div onclick=gotoUserGroup(\"' + encodeURIComponent(group._id) + '\")><span style=font-size:16px>' + group.name + '</span></div></div><td style=text-align:center>' + devicecount + '<td style=text-align:center>' + meshcount + '<td style=text-align:center>' + usercount;
10141
+ x += '<div onclick=gotoUserGroup(\"' + encodeURIComponent(group._id) + '\")><span style=font-size:16px>' + group.name + '</span></div></div><td style=text-align:center>' + usercount + '<td style=text-align:center>' + meshcount + '<td style=text-align:center>' + devicecount;
10142
return x;
10143
}
10144
@@ -10282,19 +10293,19 @@
10293
if ((deviceGroupCount > 0) && (newDeviceGroup)) { x += '<a href=# onclick="return p20showAddMeshUserDialog(3)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Device Group" + '</a>'; }
10294
x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "Common Device Groups" + '</th><th scope=col style=text-align:left></th></tr>';
10295
if (currentUserGroup.links) {
10285
- for (var i in currentUserGroup.links) {
10286
- if (i.startsWith('mesh/')) {
10287
- var cr = 0, r = currentUserGroup.links[i].rights, mesh = meshes[i], trash = '', rights = makeDeviceGroupRightsString(r);
10288
- if (mesh == null) { continue; }
10289
- if ((userinfo.links) && (userinfo.links[i] != null) && (userinfo.links[i].rights != null)) { cr = userinfo.links[i].rights; }
10290
- var meshname = '<i>' + "Unknown Device Group" + '</i>';
10291
- if (mesh) { meshname = '<a href=# onclick=\'gotoMesh("' + mesh._id + '");haltEvent(event);\'>' + mesh.name + '</a>'; } else {}
10292
- if ((cr & 2) != 0) {
10293
- trash = '<a href=# onclick=\'return p51removeMeshFromUserGroup(event,"' + encodeURIComponent(mesh._id) + '")\' title=\"' + "Remove user group rights to this device group" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>';
10294
- rights = '<div style=cursor:pointer onclick=p20showAddMeshUserDialog(3,\"' + encodeURIComponent(mesh._id) + '\")>' + rights + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></div>';
10295
- }
10296
- x += '<tr ' + (((++count % 2) == 0) ? 'style=background-color:#DDD' : '') + '><td style=width:30%><div title=\"' + "Device Group" + '\" class=m99></div><div> ' + meshname + '<div></div></div></td><td style=width:70%><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
10296
+ var omeshes = [];
10297
+ for (var i in currentUserGroup.links) { if (i.startsWith('mesh/')) { if (meshes[i] != null) { omeshes.push(meshes[i]); } } }
10298
+ omeshes = getOrderedList(omeshes, 'name');
10299
+ for (var i in omeshes) {
10300
+ var cr = 0, mesh = omeshes[i], r = currentUserGroup.links[mesh._id].rights, trash = '', rights = makeDeviceGroupRightsString(r);
10301
+ if ((userinfo.links) && (userinfo.links[i] != null) && (userinfo.links[i].rights != null)) { cr = userinfo.links[i].rights; }
10302
+ var meshname = '<i>' + "Unknown Device Group" + '</i>';
10303
+ if (mesh) { meshname = '<a href=# onclick=\'gotoMesh("' + mesh._id + '");haltEvent(event);\'>' + mesh.name + '</a>'; } else {}
10304
+ if ((cr & 2) != 0) {
10305
+ trash = '<a href=# onclick=\'return p51removeMeshFromUserGroup(event,"' + encodeURIComponent(mesh._id) + '")\' title=\"' + "Remove user group rights to this device group" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>';
10306
+ rights = '<span style=cursor:pointer onclick=p20showAddMeshUserDialog(3,\"' + encodeURIComponent(mesh._id) + '\")>' + rights + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></span>';
10307
}
10308
+ x += '<tr ' + (((++count % 2) == 0) ? 'style=background-color:#DDD' : '') + '><td style=width:30%><div title=\"' + "Device Group" + '\" class=m99></div><div> ' + meshname + '<div></div></div></td><td style=width:70%><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
10309
}
10310
}
10311
if (count == 1) { x += '<tr><td><div style=padding:6px> <i>' + "No device groups in common" + '</i><div></div></div></td><td></td></tr>'; }
@@ -10305,18 +10316,18 @@
10316
x += '<br /><a href=# onclick="return p20showAddMeshUserDialog(7)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Device" + '</a>';
10317
x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "Common Devices" + '</th><th scope=col style=text-align:left></th></tr>';
10318
if (currentUserGroup.links) {
10308
- for (var i in currentUserGroup.links) {
10309
- if (i.startsWith('node/')) {
10310
- var r = currentUserGroup.links[i].rights, node = getNodeFromId(i), trash = '', rights = makeUserDeviceRightsString(r), cr = GetNodeRights(node);
10311
- if (node == null) { continue; }
10312
- var nodename = '<i>' + "Unknown Device" + '</i>';
10313
- if (node) { nodename = '<a href=# onclick=\'gotoDevice("' + node._id + '");haltEvent(event);\'>' + node.name + '</a>'; } else {}
10314
- if ((cr & 2) != 0) {
10315
- trash = '<a href=# onclick=\'return p51removeDeviceFromUserGroup(event,"' + encodeURIComponent(node._id) + '")\' title=\"' + "Remove user group rights to this device" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>';
10316
- rights = '<div style=cursor:pointer onclick=p20showAddMeshUserDialog(7,\"' + encodeURIComponent(node._id) + '\")>' + rights + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></div>';
10317
- }
10318
- x += '<tr ' + (((++count % 2) == 0) ? 'style=background-color:#DDD' : '') + '><td style=width:30%><div title=\"' + "Device Group" + '\" class=m99></div><div> ' + nodename + '<div></div></div></td><td style=width:70%><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
10319
+ var onodes = [];
10320
+ for (var i in currentUserGroup.links) { if (i.startsWith('node/')) { var node = getNodeFromId(i); if (node != null) { onodes.push(node); } } }
10321
+ onodes = getOrderedList(onodes, 'name');
10322
+ for (var i in onodes) {
10323
+ var node = onodes[i], r = currentUserGroup.links[node._id].rights, trash = '', rights = makeUserDeviceRightsString(r), cr = GetNodeRights(node);
10324
+ var nodename = '<i>' + "Unknown Device" + '</i>';
10325
+ if (node) { nodename = '<a href=# onclick=\'gotoDevice("' + node._id + '");haltEvent(event);\'>' + node.name + '</a>'; } else {}
10326
+ if ((cr & 2) != 0) {
10327
+ trash = '<a href=# onclick=\'return p51removeDeviceFromUserGroup(event,"' + encodeURIComponent(node._id) + '")\' title=\"' + "Remove user group rights to this device" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>';
10328
+ rights = '<span style=cursor:pointer onclick=p20showAddMeshUserDialog(7,\"' + encodeURIComponent(node._id) + '\")>' + rights + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></span>';
10329
}
10330
+ x += '<tr ' + (((++count % 2) == 0) ? 'style=background-color:#DDD' : '') + '><td style=width:30%><div title=\"' + "Device Group" + '\" class=m99></div><div> ' + nodename + '<div></div></div></td><td style=width:70%><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
10331
}
10332
}
10333
if (count == 1) { x += '<tr><td><div style=padding:6px> <i>' + "No devices in common" + '</i><div></div></div></td><td></td></tr>'; }
@@ -10690,25 +10701,25 @@
10701
var count = 1, x = '';
10702
10703
// Display common device groups
10693
- count = 1;
10704
var deviceGroupCount = 0, newDeviceGroup = false;
10705
for (var i in meshes) { deviceGroupCount++; if ((currentUser.links == null) || (currentUser.links[i] == null)) { newDeviceGroup = true; } }
10706
if ((deviceGroupCount > 0) && (newDeviceGroup)) { x += '<a href=# onclick="return p20showAddMeshUserDialog(1)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Device Group" + '</a>'; }
10707
x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "Common Device Groups" + '</th><th scope=col style=text-align:left></th></tr>';
10708
if (currentUser.links) {
10699
- for (var i in currentUser.links) {
10700
- if (i.startsWith('mesh/')) {
10701
- var cr = 0, r = currentUser.links[i].rights, mesh = meshes[i], trash = '', rights = makeDeviceGroupRightsString(r);
10702
- if (mesh == null) { continue; }
10703
- if ((userinfo.links) && (userinfo.links[i] != null) && (userinfo.links[i].rights != null)) { cr = userinfo.links[i].rights; }
10704
- var meshname = '<i>' + "Unknown Device Group" + '</i>';
10705
- if (mesh) { meshname = '<a href=# onclick=\'gotoMesh("' + mesh._id + '");haltEvent(event);\'>' + EscapeHtml(mesh.name) + '</a>'; } else {}
10706
- if ((currentUser._id != userinfo._id) && ((cr & 2) != 0)) {
10707
- rights = '<div style=cursor:pointer onclick=p20showAddMeshUserDialog(1,\"' + encodeURIComponent(mesh._id) + '\")>' + rights + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></div>';
10708
- trash = '<a href=# onclick=\'return p30removeMeshFromUser(event,"' + encodeURIComponent(mesh._id) + '")\' title=\"' + "Remove user rights to this device group" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>';
10709
- }
10710
- x += '<tr ' + (((++count % 2) == 0) ? 'style=background-color:#DDD' : '') + '><td style=width:30%><div title=\"' + "Device Group" + '\" class=m99></div><div> ' + meshname + '<div></div></div></td><td style=width:70%><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
10709
+ var omeshes = [];
10710
+ for (var i in currentUser.links) { if (i.startsWith('mesh/')) { if (meshes[i] != null) { omeshes.push(meshes[i]); } } }
10711
+ omeshes = getOrderedList(omeshes, 'name');
10712
+ for (var i in omeshes) {
10713
+ var cr = 0, mesh = omeshes[i], r = currentUser.links[mesh._id].rights, trash = '', rights = makeDeviceGroupRightsString(r);
10714
+ if (mesh == null) { continue; }
10715
+ if ((userinfo.links) && (userinfo.links[i] != null) && (userinfo.links[i].rights != null)) { cr = userinfo.links[i].rights; }
10716
+ var meshname = '<i>' + "Unknown Device Group" + '</i>';
10717
+ if (mesh) { meshname = '<a href=# onclick=\'gotoMesh("' + mesh._id + '");haltEvent(event);\'>' + EscapeHtml(mesh.name) + '</a>'; } else {}
10718
+ if ((currentUser._id != userinfo._id) && ((cr & 2) != 0)) {
10719
+ trash = '<a href=# onclick=\'return p30removeMeshFromUser(event,"' + encodeURIComponent(mesh._id) + '")\' title=\"' + "Remove user rights to this device group" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>';
10720
+ rights = '<span style=cursor:pointer onclick=p20showAddMeshUserDialog(1,\"' + encodeURIComponent(mesh._id) + '\")>' + rights + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></span>';
10721
}
10722
+ x += '<tr ' + (((++count % 2) == 0) ? 'style=background-color:#DDD' : '') + '><td style=width:30%><div title=\"' + "Device Group" + '\" class=m99></div><div> ' + meshname + '<div></div></div></td><td style=width:70%><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
10723
}
10724
}
10725
if (count == 1) { x += '<tr><td><div style=padding:6px> <i>' + "No device groups in common" + '</i><div></div></div></td><td></td></tr>'; }
@@ -10725,17 +10736,18 @@
10736
}
10737
x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "User Group Memberships" + '</th><th scope=col style=text-align:left></th></tr>';
10738
if (currentUser.links) {
10728
- for (var i in currentUser.links) {
10729
- if (i.startsWith('ugrp/')) {
10730
- var r = currentUser.links[i].rights, group = usergroups[i], trash = '';
10731
- var groupname = '<i>' + "Unknown User Group" + '</i>';
10732
- if (group != null) {
10733
- groupname = EscapeHtml(group.name);
10734
- if (usergroups != null) { groupname = '<a href=# onclick=\'gotoUserGroup("' + encodeURIComponent(i) + '");haltEvent(event);\'>' + groupname + '</a>'; }
10735
- }
10736
- if ((userinfo.siteadmin & 256) != 0) { trash = '<a href=# onclick=\'return p30RemoveUserGroup(event,"' + encodeURIComponent(i) + '")\' title=\"' + "Remove user group membership" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
10737
- x += '<tr ' + (((++count % 2) == 0) ? 'style=background-color:#DDD' : '') + '><td><div title=\"' + "User Group" + '\" class=m4></div><div> ' + groupname + '<div></div></div></td><td><div style=float:right>' + trash + '</div></td></tr>';
10739
+ var ougroups = [];
10740
+ for (var i in currentUser.links) { if (i.startsWith('ugrp/')) { if (usergroups[i] != null) { ougroups.push(usergroups[i]); } } }
10741
+ ougroups = getOrderedList(ougroups, 'name');
10742
+ for (var i in ougroups) {
10743
+ var group = usergroups[i], r = currentUser.links[ougroups[i]._id].rights, trash = '';
10744
+ var groupname = '<i>' + "Unknown User Group" + '</i>';
10745
+ if (group != null) {
10746
+ groupname = EscapeHtml(group.name);
10747
+ if (usergroups != null) { groupname = '<a href=# onclick=\'gotoUserGroup("' + encodeURIComponent(i) + '");haltEvent(event);\'>' + groupname + '</a>'; }
10748
}
10749
+ if ((userinfo.siteadmin & 256) != 0) { trash = '<a href=# onclick=\'return p30RemoveUserGroup(event,"' + encodeURIComponent(i) + '")\' title=\"' + "Remove user group membership" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>'; }
10750
+ x += '<tr ' + (((++count % 2) == 0) ? 'style=background-color:#DDD' : '') + '><td><div title=\"' + "User Group" + '\" class=m4></div><div> ' + groupname + '<div></div></div></td><td><div style=float:right>' + trash + '</div></td></tr>';
10751
}
10752
}
10753
if (count == 1) { x += '<tr><td><div style=padding:6px> <i>' + "No user group memberships" + '</i><div></div></div></td><td></td></tr>'; }
@@ -10743,6 +10755,7 @@
10755
}
10756
10757
// Display common devices
10758
+ count = 1;
10759
x += '<br /><a href=# onclick="return p20showAddMeshUserDialog(4)" style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> ' + "Add Device" + '</a>';
10760
x += '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse" border=0 cellpadding=2 cellspacing=0 width=100%><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:left;width:430px>' + "Common Devices" + '</th><th scope=col style=text-align:left></th></tr>';
10761
if (currentUser.links) {
@@ -10755,8 +10768,8 @@
10768
if ((userinfo.links) && (userinfo.links[i] != null) && (userinfo.links[i].rights != null)) { cr = userinfo.links[i].rights; }
10769
var nodename = node?EscapeHtml(node.name):('<i>' + "Unknown Device" + '</i>');
10770
if ((cr & 2) != 0) {
10758
- rights = '<div style=cursor:pointer onclick=p20showAddMeshUserDialog(4,\"' + encodeURIComponent(node._id) + '\")>' + makeUserDeviceRightsString(r) + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></div>';
10771
trash = '<a href=# onclick=\'return p30removeNodeFromUser(event,"' + encodeURIComponent(node._id) + '")\' title=\"' + "Remove user rights to this device group" + '\" style=cursor:pointer><img src=images/trash.png border=0 height=10 width=10></a>';
10772
+ rights = '<span style=cursor:pointer onclick=p20showAddMeshUserDialog(4,\"' + encodeURIComponent(node._id) + '\")>' + makeUserDeviceRightsString(r) + ' <img class=hoverButton style=cursor:pointer src=images/link5.png></span>';
10773
}
10774
nodename = '<a href=# onclick=\'gotoDevice("' + node._id + '",10);haltEvent(event);\'>' + nodename + '</a>';
10775
x += '<tr ' + (((++count % 2) == 0) ? 'style=background-color:#DDD' : '') + '><td style=width:30%><div title=\"' + "Device" + '\" class=si' + node.icon + '></div><div> ' + nodename + '<div></div></div></td><td style=width:70%><div style=float:right>' + trash + '</div><div>' + rights + '</div></td></tr>';
@@ -11960,6 +11973,7 @@
11973
function addDetailItem(title, value, state) { return '<table style=width:100%><td>' + nobreak(title) + '<td style=text-align:right>' + value + '</table>'; }
11974
function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
11975
function addTextLink(subtext, text, link) { var i = text.toLowerCase().indexOf(subtext.toLowerCase()); if (i == -1) { return text; } return text.substring(0, i) + '<a href=\"' + link + '\">' + subtext + '</a>' + text.substring(i + subtext.length); }
11976
+ function getOrderedList(objList, oname) { var r = []; for (var i in objList) { r.push(objList[i]); } r.sort(function(a, b) { var aa = a[oname].toLowerCase(), bb = b[oname].toLowerCase(); if (aa > bb) return 1; if (aa < bb) return -1; return 0; }); return r; }
11977
function nobreak(x) { return x.split(' ').join(' '); }
11978
11979
</script>