mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-12-23 21:55:52 -05:00
Improved mobile app
This commit is contained in:
parent
25b467b592
commit
53c7eae4d2
@ -467,7 +467,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
|
||||
var cmdstr = JSON.stringify(command);
|
||||
for (var userid in obj.parent.wssessions) { // Find all connected users for this mesh and send the message
|
||||
var user = obj.parent.users[userid];
|
||||
if (user) {
|
||||
if ((user != null) && (user.links != null)) {
|
||||
var rights = user.links[obj.dbMeshKey];
|
||||
if (rights != null) { // TODO: Look at what rights are needed for message routing
|
||||
var sessions = obj.parent.wssessions[userid];
|
||||
|
18
mpsserver.js
18
mpsserver.js
@ -135,7 +135,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||
if (nodes.length == 0) {
|
||||
if (mesh.mtype == 1) {
|
||||
// Node is not in the database, add it. Credentials will be empty until added by the user.
|
||||
var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: domainid, intelamt: { user: '', pass: '', tls: 0 } };
|
||||
var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: domainid, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
|
||||
obj.db.Set(device);
|
||||
|
||||
// Event the new node
|
||||
@ -152,7 +152,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||
} else {
|
||||
// Node is already present
|
||||
var node = nodes[0];
|
||||
if (node.intelamt != undefined) { socket.tag.host = node.intelamt.host; }
|
||||
if ((node.intelamt != undefined) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
|
||||
}
|
||||
|
||||
// Add the connection to the MPS connection list
|
||||
@ -249,7 +249,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||
if (nodes.length == 0) {
|
||||
if (mesh.mtype == 1) {
|
||||
// Node is not in the database, add it. Credentials will be empty until added by the user.
|
||||
var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0 } };
|
||||
var device = { type: 'node', mtype: 1, _id: socket.tag.nodeid, meshid: socket.tag.meshid, name: socket.tag.name, host: null, domain: mesh.domain, intelamt: { user: '', pass: '', tls: 0, state: 2 } };
|
||||
obj.db.Set(device);
|
||||
|
||||
// Event the new node
|
||||
@ -266,7 +266,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||
} else {
|
||||
// Node is already present
|
||||
var node = nodes[0];
|
||||
if (node.intelamt != undefined) { socket.tag.host = node.intelamt.host; }
|
||||
if ((node.intelamt != undefined) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
|
||||
}
|
||||
|
||||
// Add the connection to the MPS connection list
|
||||
@ -286,7 +286,7 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||
|
||||
// Node is present
|
||||
var node = nodes[0];
|
||||
if (node.intelamt != undefined) { socket.tag.host = node.intelamt.host; }
|
||||
if ((node.intelamt != undefined) && (node.intelamt.state == 2)) { socket.tag.host = node.intelamt.host; }
|
||||
socket.tag.nodeid = node._id;
|
||||
socket.tag.meshid = mesh._id;
|
||||
socket.tag.connectTime = Date.now();
|
||||
@ -667,7 +667,10 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||
obj.db.Get(socket.tag.nodeid, function (err, nodes) {
|
||||
if (nodes.length != 1) return;
|
||||
var node = nodes[0];
|
||||
if ((node.intelamt != undefined) && (node.intelamt.host == host)) return;
|
||||
|
||||
// See if any changes need to be made
|
||||
console.log(node.intelamt);
|
||||
if ((node.intelamt != undefined) && (node.intelamt.host == host) && (node.name != '') && (node.intelamt.state == 2)) return;
|
||||
|
||||
// Get the mesh for this device
|
||||
obj.db.Get(node.meshid, function (err, meshes) {
|
||||
@ -681,9 +684,10 @@ module.exports.CreateMpsServer = function (parent, db, args, certificates) {
|
||||
// Make the change & save
|
||||
if (node.intelamt == undefined) node.intelamt = {};
|
||||
node.intelamt.host = host;
|
||||
node.intelamt.state = 2; // Set the state to activated, since this is pretty obvious, we have a CIRA connection.
|
||||
if (node.name == '') { node.name = host.split('.')[0]; }
|
||||
obj.db.Set(node);
|
||||
|
||||
|
||||
// Event the node change
|
||||
event.msg = 'CIRA changed device ' + node.name + ' from mesh ' + mesh.name + ': ' + changes.join(', ');
|
||||
var node2 = common.Clone(node);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "meshcentral",
|
||||
"version": "0.1.7-x",
|
||||
"version": "0.1.8-a",
|
||||
"keywords": [
|
||||
"Remote Management",
|
||||
"Intel AMT",
|
||||
|
BIN
public/images/3bars-30.png
Normal file
BIN
public/images/3bars-30.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 414 B |
BIN
public/images/user-50.png
Normal file
BIN
public/images/user-50.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.4 KiB |
@ -48,18 +48,30 @@
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-color: #DDDDDD;
|
||||
}
|
||||
|
||||
.noselect {
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body onload="if (typeof(startup) !== 'undefined') startup();" style="overflow-y:hidden;margin:0;padding:0;border:0;color:black;font-size:13px;font-family:\'Trebuchet MS\', Arial, Helvetica, sans-serif">
|
||||
<div id=container>
|
||||
<div id=mastheadx></div>
|
||||
<div id=masthead style="background-color:#036;background-repeat:no-repeat;height:50px;width:100%;overflow:hidden">
|
||||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:6px">
|
||||
<strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
|
||||
</div>
|
||||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:10px">
|
||||
<strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
|
||||
<div style="width:calc(100% - 50px);overflow:hidden">
|
||||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:10px;padding-top:6px">
|
||||
<strong><font style="font-size:36px;font-family:Arial,Helvetica,sans-serif">{{{title}}}</font></strong>
|
||||
</div>
|
||||
<div style="float:left;height:66px;color:#c8c8c8;padding-left:5px;padding-top:10px">
|
||||
<strong><font style="font-size:12px;font-family:Arial,Helvetica,sans-serif">{{{title2}}}</font></strong>
|
||||
</div>
|
||||
</div>
|
||||
<img class=noselect style="position:absolute;right:0;top:10px;bottom:50px;color:#c8c8c8;font-size:44px;margin-right:8px;cursor:pointer" onclick=topMenu() src="/images/3bars-30.png" width=30 height=30 />
|
||||
</div>
|
||||
<div id=page_content style="overflow-y:scroll;position:absolute;bottom:32px;top:50px;width:100%">
|
||||
<div id=column_l style="width:100%;padding:0;position:absolute;bottom:0px;top:0px">
|
||||
@ -76,8 +88,48 @@
|
||||
<div id=p2 style=display:none>
|
||||
<div id=xdevices></div>
|
||||
</div>
|
||||
<div id=p10 style=display:none;position:absolute;bottom:0;top:0;width:100%>
|
||||
<div id=p3 style=display:none;position:absolute;bottom:0;top:0;width:100%>
|
||||
<table cellspacing=0 style="margin:0;padding:0;border-spacing:0;border:0;">
|
||||
<tr style=padding:0>
|
||||
<td style="padding:0;color:#c8c8c8;text-align:center;cursor:pointer" width=60px valign=top onclick=goBack()>
|
||||
<div style="padding:0;background-color:#036;width:10px;height:10px;float:right;border:0">
|
||||
<div style="background-color:white;width:10px;height:10px;border-radius:10px 0 0 0;border-right:1px solid white;border-bottom:1px solid white"></div>
|
||||
</div>
|
||||
<div style="padding:0;font-size:25px;background-color:#036;width:50px;border-radius:0 0 10px 0;height:36px">◀</div>
|
||||
</td>
|
||||
<td>
|
||||
<img src="/images/user-50.png" width=50 height=50 />
|
||||
</td>
|
||||
<td>
|
||||
<div style=margin-left:5px>
|
||||
<strong style="font-size:large"><span id=p3userName></span></strong><br />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div id=p3info style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%">
|
||||
<div style="margin-left:8px">
|
||||
<div id="p3AccountActions">
|
||||
<p><strong>Account actions</strong></p>
|
||||
<div style="margin-left:9px;margin-bottom:8px">
|
||||
<div style="margin-top:5px"><span id="verifyEmailId" style="display:none"><a onclick="account_showVerifyEmail()" style="cursor:pointer">Verify email</a></span></div>
|
||||
<div style="margin-top:5px"><a onclick="account_showChangeEmail()" style="cursor:pointer">Change email address</a></div>
|
||||
<div style="margin-top:5px"><a onclick="account_showChangePassword()" style="cursor:pointer">Change password</a></div>
|
||||
<div style="margin-top:5px"><a onclick="account_showDeleteAccount()" style="cursor:pointer">Delete account</a></div>
|
||||
</div>
|
||||
</div>
|
||||
<br style=clear:both />
|
||||
<strong>Meshes</strong>
|
||||
( <a onclick=account_createMesh() style=cursor:pointer><img height=12 src="images/icon-addnew.png" width=12 border=0 /> New</a> )
|
||||
<br /><br />
|
||||
<div id=p3meshes></div>
|
||||
<div id=p3noMeshFound style=margin-left:9px;display:none>No meshes. <a onclick=account_createMesh() style=cursor:pointer><strong>Get started here!</strong></a></div>
|
||||
<br style=clear:both />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id=p10 style=display:none;position:absolute;bottom:0;top:0;width:100%;overflow:hidden>
|
||||
<table cellspacing=0 style="margin:0;padding:0;border-spacing:0;border:0;position:absolute;top:0">
|
||||
<tr style=padding:0>
|
||||
<td style="padding:0;color:#c8c8c8;text-align:center;cursor:pointer" width=60px valign=top onclick=goBack()>
|
||||
<div style="padding:0;background-color:#036;width:10px;height:10px;float:right;border:0">
|
||||
@ -96,9 +148,11 @@
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div id=p10html style="margin-left:8px;margin-right:8px"></div>
|
||||
<div id=p10html2></div>
|
||||
<div id=p10html3></div>
|
||||
<div style="overflow-y:scroll;position:absolute;top:55px;bottom:0px;width:100%">
|
||||
<div id=p10html style="margin-left:8px;margin-right:8px"></div>
|
||||
<div id=p10html2></div>
|
||||
<div id=p10html3></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id=p20 style=display:none;position:absolute;bottom:0;top:0;width:100%>
|
||||
<table cellspacing=0 style="margin:0;padding:0;border-spacing:0;border:0;">
|
||||
@ -151,6 +205,10 @@
|
||||
<input id="idx_dlgOkButton" type="button" value="OK" style="float:right;width:80px" onclick="dialogclose(1)">
|
||||
</div>
|
||||
</div>
|
||||
<div id=topMenu style="z-index:1000;background-color:#EEE;box-shadow:0px 0px 15px #666;font-family:Arial,Helvetica,sans-serif;border-radius:0px 0px 5px 5px;position:fixed;top:50px;right:5px;width:170px;display:none">
|
||||
<div style="padding:12px;border-top:1px solid gray;color:black;cursor:pointer" onclick=topMenu(1)>My Account</div>
|
||||
<a href=/logout><div style="padding:12px;border-top:1px solid gray;color:black;cursor:pointer">Logout</div></a>
|
||||
</div>
|
||||
<script>
|
||||
var debugLevel = {{{debuglevel}}};
|
||||
var features = {{{features}}};
|
||||
@ -222,6 +280,7 @@
|
||||
}
|
||||
case 'userinfo': {
|
||||
userinfo = message.userinfo;
|
||||
QH('p3userName', userinfo.name);
|
||||
//updateSiteAdmin();
|
||||
//QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
//QV('verifyEmailId2', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
@ -397,6 +456,7 @@
|
||||
|
||||
// Change the node
|
||||
node.name = message.event.node.name;
|
||||
node.rname = message.event.node.rname;
|
||||
node.host = message.event.node.host;
|
||||
node.desc = message.event.node.desc;
|
||||
node.publicip = message.event.node.publicip;
|
||||
@ -473,20 +533,194 @@
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Menu System
|
||||
//
|
||||
|
||||
function topMenu(select) {
|
||||
if ((xxdialogMode != null) && (xxdialogMode != 0) && (xxdialogMode != 999)) return;
|
||||
if (select === undefined) {
|
||||
var x = (QS('topMenu').display == 'none');
|
||||
if (x == true) { if ((xxdialogMode == 0) || (xxdialogMode == null)) { QV('topMenu', true); xxdialogMode = 999; } } else { QV('topMenu', false); xxdialogMode = 0; }
|
||||
} else {
|
||||
QV('topMenu', false);
|
||||
xxdialogMode = 0;
|
||||
if ((select == 1) && (xxcurrentView != 3)) { goForward('account'); } // My Account
|
||||
}
|
||||
}
|
||||
|
||||
var backStack = [];
|
||||
function goBack() { if (xxdialogMode) return; if (backStack.length > 0) { backStack.pop(); } goStack(); }
|
||||
function goForward(id) { if (xxdialogMode) return; backStack.push(id); goStack(); }
|
||||
function goStack() {
|
||||
if (backStack.length == 0) { go(2); return; }
|
||||
var id = backStack[backStack.length - 1], idtype = id.split('/')[0];
|
||||
if (idtype == 'node') { gotoDevice(id); }
|
||||
if (idtype == 'mesh') { gotoMesh(id); }
|
||||
if (idtype == 'account') { go(3); }
|
||||
if (idtype == 'devices') { go(2); }
|
||||
}
|
||||
|
||||
//
|
||||
// MY ACCOUNT
|
||||
//
|
||||
|
||||
function updateMeshes() { }
|
||||
function account_showVerifyEmail() {
|
||||
if (xxdialogMode || (userinfo.emailVerified == true) || (serverinfo.emailcheck != true)) return;
|
||||
var x = "Click ok to send a verification mail to:<br /><div style=padding:8px><b>" + EscapeHtml(userinfo.email) + "</b></div>Please wait a few minute to receive the verification.";
|
||||
setDialogMode(2, "Email Verification", 3, account_showVerifyEmailEx, x);
|
||||
}
|
||||
|
||||
function account_showVerifyEmailEx() {
|
||||
meshserver.send({ action: 'verifyemail', email: userinfo.email });
|
||||
}
|
||||
|
||||
function account_showChangeEmail() {
|
||||
if (xxdialogMode) return;
|
||||
var x = addHtmlValue('Email', '<input id=dp3email style=width:170px maxlength=256 onchange=account_validateEmail() onkeyup=account_validateEmail(event) />');
|
||||
setDialogMode(2, "Email Address Change", 3, account_changeEmail, x);
|
||||
if (userinfo.email != null) { Q('dp3email').value = userinfo.email; }
|
||||
account_validateEmail();
|
||||
Q('dp3email').focus();
|
||||
}
|
||||
|
||||
function account_validateEmail(e, email) {
|
||||
QE('idx_dlgOkButton', validateEmail(Q('dp3email').value) && (Q('dp3email').value != userinfo.email));
|
||||
if ((x == true) && (e != null) && (e.keyCode == 13)) { dialogclose(1); }
|
||||
}
|
||||
|
||||
function account_changeEmail() {
|
||||
meshserver.send({ action: 'changeemail', email: Q('dp3email').value });
|
||||
}
|
||||
|
||||
function account_showDeleteAccount() {
|
||||
if (xxdialogMode) return;
|
||||
var x = "<form action='{{{domainurl}}}deleteaccount' method=post><table style=margin-left:10px><tr>";
|
||||
x += "<td align=right>Password:</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>";
|
||||
x += "</tr><tr><td align=right>Password:</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateDeleteAccount() onkeyup=account_validateDeleteAccount() /></td>";
|
||||
x += '</tr></table><div style=padding:10px;margin-bottom:4px>';
|
||||
x += '<input id=account_dlgCancelButton type=button value=Cancel style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
|
||||
x += '<input id=account_dlgOkButton type=submit value=OK style="float:right;width:80px" onclick=dialogclose(1)>';
|
||||
x += '</div><br /></form>';
|
||||
setDialogMode(2, "Delete Account", 0, null, x);
|
||||
account_validateDeleteAccount();
|
||||
Q('apassword1').focus();
|
||||
}
|
||||
|
||||
function account_showChangePassword() {
|
||||
if (xxdialogMode) return;
|
||||
var x = "<form action='{{{domainurl}}}changepassword' method=post><table style=margin-left:10px><tr>";
|
||||
x += "<td align=right>Password:</td><td><input id=apassword1 type=password name=apassword1 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() /> <b><span id=dxPassWarn></span></b></td>";
|
||||
x += "</tr><tr><td align=right>Password:</td><td><input id=apassword2 type=password name=apassword2 autocomplete=off onchange=account_validateNewPassword() onkeyup=account_validateNewPassword() /></td>";
|
||||
x += "</tr><tr><td align=right>Hint:</td><td><input id=apasswordhint name=apasswordhint maxlength=250 type=text autocomplete=off /></td>";
|
||||
x += '</tr></table><div style=padding:10px;margin-bottom:4px>';
|
||||
x += '<input id=account_dlgCancelButton type=button value=Cancel style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
|
||||
x += '<input id=account_dlgOkButton type=submit value=OK style="float:right;width:80px" onclick=dialogclose(1)>';
|
||||
x += '</div><br /></form>';
|
||||
setDialogMode(2, "Change Password", 0, null, x);
|
||||
account_validateDeleteAccount();
|
||||
Q('apassword1').focus();
|
||||
}
|
||||
|
||||
function account_createMesh() {
|
||||
if (xxdialogMode) return;
|
||||
var x = addHtmlValue('Name', '<input id=dp3meshname style=width:170px maxlength=64 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate() />');
|
||||
x += addHtmlValue('Type', '<div style=width:170px;margin:0;padding:0><select id=dp3meshtype style=width:100% onchange=account_validateMeshCreate() ><option value=2>Mesh Agent Policy</option><option value=1>Intel® AMT Agent-less Policy</option></select></div>');
|
||||
x += addHtmlValue('Description', '<div style=width:170px;margin:0;padding:0><textarea id=dp3meshdesc maxlength=1024 style=width:100%;resize:none></textarea></div>');
|
||||
setDialogMode(2, "Create Mesh", 3, account_createMeshEx, x);
|
||||
account_validateMeshCreate();
|
||||
Q('dp3meshname').focus();
|
||||
}
|
||||
|
||||
function account_validateMeshCreate() {
|
||||
QE('idx_dlgOkButton', Q('dp3meshname').value.length > 0);
|
||||
}
|
||||
|
||||
function account_createMeshEx(button, tag) {
|
||||
meshserver.send({ action: 'createmesh', meshname: Q('dp3meshname').value, meshtype: Q('dp3meshtype').value, desc: Q('dp3meshdesc').value });
|
||||
}
|
||||
|
||||
function account_validateDeleteAccount() {
|
||||
QE('account_dlgOkButton', (Q('apassword1').value.length > 0) && (Q('apassword1').value == Q('apassword2').value));
|
||||
}
|
||||
|
||||
function account_validateNewPassword() {
|
||||
QE('account_dlgOkButton', (Q('apassword1').value.length > 0) && (Q('apassword1').value == Q('apassword2').value));
|
||||
var r = '';
|
||||
if (Q('apassword1').value != '') {
|
||||
var passStrength = checkPasswordStrength(Q('apassword1').value);
|
||||
if (passStrength >= 80) { r = '<span style=color:green>Strong<span>'; } else if (passStrength >= 60) { r = '<span style=color:blue>Good<span>'; } else { r = '<span style=color:red>Weak<span>'; }
|
||||
}
|
||||
QH('dxPassWarn', r);
|
||||
}
|
||||
|
||||
// Return a password strength score
|
||||
function checkPasswordStrength(password) {
|
||||
var r = 0, letters = {}, varCount = 0, variations = { digits: /\d/.test(password), lower: /[a-z]/.test(password), upper: /[A-Z]/.test(password), nonWords: /\W/.test(password) }
|
||||
if (!password) return 0;
|
||||
for (var i = 0; i< password.length; i++) { letters[password[i]] = (letters[password[i]] || 0) + 1; r += 5.0 / letters[password[i]]; }
|
||||
for (var c in variations) { varCount += (variations[c] == true) ? 1 : 0; }
|
||||
return parseInt(r + (varCount - 1) * 10);
|
||||
}
|
||||
|
||||
function updateMeshes() {
|
||||
var r = '', count = 0;
|
||||
for (i in meshes) {
|
||||
count++;
|
||||
|
||||
// Mesh rights
|
||||
var meshrights = meshes[i].links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
|
||||
var rights = 'Partial Rights';
|
||||
if (meshrights == 0xFFFFFFFF) rights = 'Full Administrator'; else if (meshrights == 0) rights = 'No Rights';
|
||||
|
||||
// Print the mesh information
|
||||
r += '<div style=cursor:pointer onclick=goForward(\'' + i + '\')>';
|
||||
r += '<div style="float:left;margin-left:4px"><img src="/images/meshicon50.png" width=50 height=50 /></div>';
|
||||
r += '<div style="width:auto;height:40px;background-color:lightgray;margin-top:5px;margin-bottom:5px;margin-left:60px;padding-top:5px;padding-bottom:5px;border-radius:8px 0px 0px 8px">';
|
||||
r += '<div><div style=padding-left:12px;padding-top:2px><b>' + EscapeHtml(meshes[i].name) + '</b></div><div style=padding-left:12px;padding-top:3px;color:gray>' + rights + '</div></div>';
|
||||
r += '</div></div>';
|
||||
}
|
||||
|
||||
meshcount = count;
|
||||
QH('p3meshes', r);
|
||||
QV('p3noMeshFound', count == 0);
|
||||
}
|
||||
|
||||
function gotoMesh(meshid) {
|
||||
currentMesh = meshes[meshid];
|
||||
p20updateMesh();
|
||||
go(20);
|
||||
}
|
||||
|
||||
function server_showRestoreDlg() {
|
||||
if (xxdialogMode) return;
|
||||
var x = 'Restore the server using a backup, <span style=color:red>this will delete the existing server data</span>. Only do this if you know what you are doing.<br /><br />';
|
||||
x += '<form action="/restoreserver.ashx" enctype="multipart/form-data" method="post"><div>';
|
||||
x += '<input id=account_dlgFileInput type=file name=datafile style=width:100% accept=".zip,application/octet-stream,application/zip,application/x-zip,application/x-zip-compressed" onchange=account_validateServerRestore()>';
|
||||
x += '<input id=account_dlgCancelButton type=button value=Cancel style=float:right;width:80px;margin-left:5px onclick=dialogclose(0)>';
|
||||
x += '<input id=account_dlgOkButton type=submit value=OK style=float:right;width:80px onclick=dialogclose(1)>';
|
||||
x += '</div><br /><br /></form>';
|
||||
setDialogMode(2, "Restore Server", 0, null, x);
|
||||
account_validateServerRestore();
|
||||
}
|
||||
|
||||
function account_validateServerRestore() {
|
||||
QE('account_dlgOkButton', Q('account_dlgFileInput').files.length == 1);
|
||||
}
|
||||
|
||||
function server_showVersionDlg() {
|
||||
if (xxdialogMode) return;
|
||||
setDialogMode(2, "MeshCentral Version", 1, null, "Loading...", 'MeshCentralServerUpdate');
|
||||
meshserver.send({ action: 'serverversion' });
|
||||
}
|
||||
|
||||
function server_showVersionDlgUpdate() { QE('idx_dlgOkButton', Q('d2updateCheck').checked); }
|
||||
function server_showVersionDlgEx() { meshserver.send({ action: 'serverupdate' }); }
|
||||
|
||||
//
|
||||
// MY DEVICES
|
||||
//
|
||||
|
||||
var backStack = [];
|
||||
function goBack() { if (backStack.length == 0) { goMyDevices(); } else { gotoDevice(backStack.pop()); } }
|
||||
function goMyDevices() { go(2); }
|
||||
|
||||
var sort = 0;
|
||||
var deviceHeaderId = 0;
|
||||
var deviceHeaderCount;
|
||||
@ -523,7 +757,7 @@
|
||||
if (current != null) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
|
||||
r += '<div class=DevSt style=padding-top:4px><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 + ' style=color:lightgray></span></div>';
|
||||
r += '</span><span id=MxMESH style=cursor:pointer onclick=goForward("' + nodes[i].meshid + '")>' + EscapeHtml(meshes[nodes[i].meshid].name) + '</span>' + extra + '<span id=DevxHeader' + deviceHeaderId + ' style=color:lightgray></span></div>';
|
||||
current = nodes[i].meshid;
|
||||
displayedMeshes[current] = 1;
|
||||
c = 0;
|
||||
@ -553,7 +787,7 @@
|
||||
// Node
|
||||
var icon = nodes[i].icon, nodestate = NodeStateStr(nodes[i]);
|
||||
if ((!nodes[i].conn) || (nodes[i].conn == 0)) { icon += ' gray'; }
|
||||
r += '<div style=cursor:pointer onclick=gotoDevice(\'' + nodes[i]._id + '\')>';
|
||||
r += '<div style=cursor:pointer onclick=goForward(\'' + nodes[i]._id + '\')>';
|
||||
r += '<div class="i' + icon + '" style="float:left;margin-left:4px"></div>';
|
||||
r += '<div style="width:auto;height:40px;background-color:lightgray;margin-top:5px;margin-bottom:5px;margin-left:60px;padding-top:5px;padding-bottom:5px;border-radius:8px 0px 0px 8px">';
|
||||
r += '<div><div style=padding-left:12px;padding-top:2px><b>' + name + '</b></div><div style=padding-left:12px;padding-top:3px;color:gray>' + nodestate + '</div></div>';
|
||||
@ -587,7 +821,7 @@
|
||||
if ((current != '') && (r != '')) { r += '</tr></table>'; }
|
||||
r += '<div><div 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></div>';
|
||||
r += '</span><span id=MxMESH style=cursor:pointer onclick=goForward("' + mesh._id + '")>' + EscapeHtml(mesh.name) + '</span></div>';
|
||||
if (mesh.mtype == 1) { r += '<div style=padding:10px><i>No Intel® AMT devices in this mesh'; }
|
||||
if (mesh.mtype == 2) { r += '<div style=padding:10px><i>No devices in this mesh'; }
|
||||
r += '.</i></div></div>';
|
||||
@ -604,11 +838,6 @@
|
||||
for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
|
||||
}
|
||||
|
||||
function gotoMeshStack(meshid) {
|
||||
backStack.push(currentNode._id);
|
||||
gotoMesh(meshid);
|
||||
}
|
||||
|
||||
var powerStatetable = ['', 'Powered', 'Sleep', 'Sleep', 'Sleep', 'Hibernating', 'Power off', 'Present'];
|
||||
var powerStateStrings = ['', '<span title="Device is powered on.">Powered</span>', '<span title="Device is in sleep state (S1).">Sleeping</span>', '<span title="Device is in sleep state (S2).">Sleeping</span>', '<span title="Device is in deep sleep state (S3).">Deep Sleep</span>', '<span title="Device is in hibernating state (S4).">Hibernating</span>', '<span title="Device is in powered off state (S5).">Soft-Off</span>', '<span title="Device is detected but power state could not be obtained.">Present</span>'];
|
||||
var powerStateStrings2 = ['', 'Device is powered', 'Device is in sleep state (S1)', 'Device is in sleep state (S2)', 'Device is in deep sleep state (S3)', 'Device is hibernating (S4)', 'Device is in soft-off state (S5)', 'Device is present, but power state cannot be determined'];
|
||||
@ -705,7 +934,7 @@
|
||||
var x = '<table style=width:100%>';
|
||||
|
||||
// Attribute: Mesh
|
||||
x += addDeviceAttribute('<span title="The name of the administrative group this computer belong to">Mesh</span>', '<a title="The name of the group this computer belong to" onclick=gotoMeshStack("' + node.meshid + '") style=cursor:pointer>' + EscapeHtml(meshes[node.meshid].name) + '</a>');
|
||||
x += addDeviceAttribute('<span title="The name of the administrative group this computer belong to">Mesh</span>', '<a title="The name of the group this computer belong to" onclick=goForward("' + node.meshid + '") style=cursor:pointer>' + EscapeHtml(meshes[node.meshid].name) + '</a>');
|
||||
|
||||
// Attribute: Name
|
||||
if (node.rname != null) { x += addDeviceAttribute('<span title="The name of this computer as set in the operating system">Name</span>', '<span title="The name of this computer as set in the operating system">' + EscapeHtml(node.rname) + '</span>'); }
|
||||
@ -743,23 +972,27 @@
|
||||
// Attribute: Intel AMT
|
||||
if (node.intelamt != null) {
|
||||
var str = '';
|
||||
var provisioningStates = { 0: 'Not Activated (Pre)', 1: 'Not Activated (In)', 2: 'Activated' };
|
||||
if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>Unknown State</i>, v' + node.intelamt.ver; } else
|
||||
if (node.intelamt.ver == null || node.intelamt.state == null) { str += '<i>Unknown Version & State</i>'; } else {
|
||||
var provisioningStates = { 0: 'Not Activated (Pre)', 1: 'Not Activated (In)', 2: 'Activated' };
|
||||
if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>Unknown State</i>, v' + node.intelamt.ver; } else
|
||||
|
||||
if ((node.intelamt.ver == null) && (node.intelamt.state == 2)) { str += '<i>Activated</i>'; }
|
||||
else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += '<i>Unknown Version & State</i>'; }
|
||||
else {
|
||||
str += provisioningStates[node.intelamt.state];
|
||||
if (node.intelamt.flags) { if (node.intelamt.flags & 2) { str += ' <span title="Intel AMT is activated in Client Control Mode">CCM</span>'; } else if (node.intelamt.flags & 4) { str += ' <span title="Intel AMT is activated in Admin Control Mode">ACM</span>'; } }
|
||||
str += (', v' + node.intelamt.ver);
|
||||
}
|
||||
|
||||
if (node.intelamt.tls == 1) { str += ', <span title="Intel AMT is setup with TLS network security">TLS</span>'; }
|
||||
if (node.intelamt.state == 2) {
|
||||
if (node.intelamt.user == null || node.intelamt.user == '') {
|
||||
if ((meshrights & 4) != 0) {
|
||||
str += ', <i style=color:#FF0000;cursor:pointer title="Edit Intel® AMT credentials" onclick=editDeviceAmtSettings("' + node._id + '")>No Credentials</i>';
|
||||
} else {
|
||||
str += ', <i style=color:#FF0000>No Credentials</i>';
|
||||
str += ', <i style=color:#FF0000>No Credentials</i>';
|
||||
}
|
||||
}
|
||||
str += ' ';
|
||||
str += ' ';
|
||||
if ((meshrights & 4) != 0) {
|
||||
str += '<img src=images/link4.png height=10 width=10 title="Edit Intel® AMT credentials" style=cursor:pointer onclick=editDeviceAmtSettings("' + node._id + '")>';
|
||||
}
|
||||
@ -795,7 +1028,7 @@
|
||||
|
||||
x += '</table><br />';
|
||||
// Show action button, only show if we have permissions 4, 8, 64
|
||||
//if ((meshrights & 76) != 0) { x += '<input type=button value=Actions title="Perform power actions on the device" onclick=deviceActionFunction() />'; }
|
||||
if ((meshrights & 76) != 0) { x += '<input type=button value=Actions title="Perform power actions on the device" onclick=deviceActionFunction() />'; }
|
||||
//x += '<input type=button value=Notes title="View notes about this device" onclick=showNotes(' + ((meshrights & 128) == 0) + ',"' + encodeURIComponent(node._id) + '") />';
|
||||
//if ((connectivity & 1) && (meshrights & 8) && (node.agent.id < 5)) { x += '<input type=button value=Toast title="Display a text message of the remote device" onclick=deviceToastFunction() />'; }
|
||||
QH('p10html', x);
|
||||
@ -804,8 +1037,8 @@
|
||||
//drawDeviceTimeline();
|
||||
|
||||
// Show bottom buttons
|
||||
x = '<div style=float:right;font-size:x-small>';
|
||||
//if ((meshrights & 4) != 0) x += '<a style=cursor:pointer onclick=p10showDeleteNodeDialog("' + node._id + '") title="Remove this device">Delete Device</a>';
|
||||
x = '<div style=float:right;font-size:x-small;margin-right:10px>';
|
||||
if ((meshrights & 4) != 0) x += '<a style=cursor:pointer onclick=p10showDeleteNodeDialog("' + node._id + '") title="Remove this device">Delete Device</a>';
|
||||
x += '</div><div style=font-size:x-small>';
|
||||
//if (mesh.mtype == 2) x += '<a style=cursor:pointer onclick=p10showNodeNetInfoDialog("' + node._id + '") title="Show device network interface information">Interfaces</a> ';
|
||||
//if (xxmap != null) x += '<a style=cursor:pointer onclick=p10showNodeLocationDialog("' + node._id + '") title="Show device locations information">Location</a> ';
|
||||
@ -823,15 +1056,156 @@
|
||||
|
||||
// Set the node icon
|
||||
QH('MainComputerImage', '<div class="i' + node.icon + '"></div>');
|
||||
|
||||
// Request the power timeline
|
||||
if ((powerTimelineNode != currentNode._id) && (powerTimelineReq != currentNode._id)) { QH('p10html2', ''); powerTimelineReq = currentNode._id; meshserver.send({ action: 'powertimeline', nodeid: currentNode._id }); }
|
||||
}
|
||||
if (!panel) panel = 10;
|
||||
go(panel);
|
||||
}
|
||||
|
||||
function deviceActionFunction() {
|
||||
if (xxdialogMode) return;
|
||||
var meshrights = meshes[currentNode.meshid].links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
|
||||
var x = "Select an operation to perform on this device.<br /><br />";
|
||||
var y = '<select id=d2deviceop style=float:right;width:170px>';
|
||||
if ((meshrights & 64) != 0) { y += '<option value=100>Wake-up</option>'; } // Wake-up permission
|
||||
if ((meshrights & 8) != 0) { y += '<option value=4>Sleep</option><option value=3>Reset</option><option value=2>Power off</option>'; } // Remote control permission
|
||||
y += '</select>';
|
||||
x += addHtmlValue('Operation', y);
|
||||
setDialogMode(2, "Device Action", 3, deviceActionFunctionEx, x);
|
||||
}
|
||||
|
||||
function deviceActionFunctionEx() {
|
||||
var op = Q('d2deviceop').value;
|
||||
if (op == 100) {
|
||||
// Device wake
|
||||
meshserver.send({ action: 'wakedevices', nodeids: [ currentNode._id ] });
|
||||
} else {
|
||||
// Power operation
|
||||
meshserver.send({ action: 'poweraction', nodeids: [ currentNode._id ], actiontype: op });
|
||||
}
|
||||
}
|
||||
|
||||
// Look to see if we need to update the device timeline
|
||||
function updateDeviceTimeline() {
|
||||
if ((meshserver.State != 2) || (powerTimelineNode == null) || (powerTimelineUpdate == null) || (currentNode == null)) return;
|
||||
if ((powerTimelineNode == powerTimelineReq) && (currentNode._id == powerTimelineNode) && (powerTimelineUpdate < Date.now())) { powerTimelineUpdate = null; meshserver.send({ action: 'powertimeline', nodeid: currentNode._id }); }
|
||||
}
|
||||
|
||||
// Draw device power bars. The bars are 766px wide.
|
||||
function drawDeviceTimeline() {
|
||||
var timeline = null, now = Date.now();
|
||||
if (currentNode._id == powerTimelineNode) { timeline = powerTimeline; }
|
||||
|
||||
// Calculate when the timeline starts
|
||||
var d = new Date();
|
||||
d.setHours(0, 0, 0, 0);
|
||||
d = new Date(d.getTime() - (1000 * 60 * 60 * 24 * 6));
|
||||
var timelineStart = d.getTime();
|
||||
|
||||
// De-compact the timeline
|
||||
var timeline2 = [];
|
||||
if (timeline != null && timeline.length > 1) {
|
||||
timeline2.push([ 0, timeline[1], timeline[0] ]); // Start, End, Power
|
||||
var ct = timeline[1];
|
||||
for (var i = 2; i < timeline.length; i += 2) {
|
||||
var power = timeline[i], dt = now;
|
||||
if (timeline.length > (i + 1)) { dt = timeline[i + 1]; }
|
||||
timeline2.push([ ct, ct + dt, power ]); // Start, End, Power
|
||||
ct = ct + dt;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the timeline
|
||||
var x = '', count = 1, date = new Date();
|
||||
var totalWidth = Q('masthead').offsetWidth - (90 + 9 + 9 + 14); // Compute the total width of the power bar
|
||||
date.setHours(0, 0, 0, 0);
|
||||
for (var i = 0; i < 7; i++) {
|
||||
var datavalue = '', start = date.getTime(), end = start + (1000 * 60 * 60 * 24);
|
||||
for (var j in timeline2) {
|
||||
var block = timeline2[j];
|
||||
if (isTimeBlockInside(start, end, block[0], block[1]) == true) {
|
||||
var ts = Math.max(start, block[0]);
|
||||
var te = Math.min(Math.min(end, block[1]), now);
|
||||
var width = Math.round(((te - ts) * totalWidth) / 86400000);
|
||||
if (width > 0) {
|
||||
var title = powerStateStrings2[block[2]] + ' from ' + new Date(ts).toLocaleTimeString() + ' to ' + new Date(te).toLocaleTimeString() + '.';
|
||||
datavalue += '<div title="' + title + '" style=display:table-cell;width:' + width + 'px;background-color:' + powerColor(block[2]) + ';height:16px></div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
x += '<tr style=' + (((count % 2) == 0)?'background-color:#DDD':'') + '><td><div> ' + date.toLocaleDateString() + '<div></div></div></td><td><div>' + datavalue + '</div></td></tr>';
|
||||
++count;
|
||||
date = new Date(date.getTime() - (1000 * 60 * 60 * 24)); // Substract one day
|
||||
}
|
||||
QH('p10html2', '<table style="color:black;background-color:#EEE;border-color:#AAA;border-width:1px;border-style:solid;border-collapse:collapse;width:calc(100% - 18px);margin:9px" border=0 cellpadding=2 cellspacing=0><tbody><tr style=background-color:#AAAAAA;font-weight:bold><th scope=col style=text-align:center;width:90px>Day</th><th scope=col style=text-align:center>Power State</th></tr>' + x + '</tbody></table>');
|
||||
}
|
||||
|
||||
// Return a color for the given power state
|
||||
function powerColor(x) { if (x < powerColorTable.length) { return powerColorTable[x]; } return 'yellow'; }
|
||||
|
||||
// Return true if the time block is visible within the start/end period
|
||||
function isTimeBlockInside(start, end, blockStart, blockEnd) {
|
||||
if ((blockStart < start) && (blockEnd > end)) return true; // Block is wider than timespan
|
||||
if ((blockStart > start) && (blockStart < end)) return true;
|
||||
if ((blockEnd > start) && (blockEnd < end)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function addDeviceAttribute(name, value) {
|
||||
return '<tr><td style=width:100px;color:gray>' + name + '</td><td style=overflow:hidden>' + value + '</td></tr>';
|
||||
}
|
||||
|
||||
function editDeviceAmtSettings(nodeid, func) {
|
||||
if (xxdialogMode) return;
|
||||
var x = '', node = getNodeFromId(nodeid), buttons = 3, meshrights = getNodeRights(nodeid);
|
||||
if ((meshrights & 4) == 0) return;
|
||||
x += addHtmlValue('Username', '<input id=dp10username style=width:170px maxlength=32 autocomplete=nope placeholder="admin" onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
||||
x += addHtmlValue('Password', '<input id=dp10password type=password style=width:170px autocomplete=nope maxlength=32 onchange=validateDeviceAmtSettings() onkeyup=validateDeviceAmtSettings() />');
|
||||
x += addHtmlValue('Security', '<select id=dp10tls style=width:176px><option value=0>No TLS security</option><option value=1>TLS security required</option></select>');
|
||||
if ((node.intelamt.user != null) && (node.intelamt.user != '')) { buttons = 7; }
|
||||
setDialogMode(2, "Edit Intel® AMT credentials", buttons, editDeviceAmtSettingsEx, x, { node: node, func: func });
|
||||
if ((node.intelamt.user != null) && (node.intelamt.user != '')) { Q('dp10username').value = node.intelamt.user; } else { Q('dp10username').value = 'admin'; }
|
||||
Q('dp10tls').value = node.intelamt.tls;
|
||||
validateDeviceAmtSettings();
|
||||
}
|
||||
|
||||
function validateDeviceAmtSettings() {
|
||||
QE('idx_dlgOkButton', passwordcheck(Q('dp10password').value));
|
||||
}
|
||||
|
||||
function editDeviceAmtSettingsEx(button, tag) {
|
||||
if (button == 2) {
|
||||
// Delete button pressed, remove credentials
|
||||
meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: '', pass: '' } });
|
||||
} else {
|
||||
// Change Intel AMT credentials
|
||||
var amtuser = Q('dp10username').value;
|
||||
if (amtuser == '') amtuser = 'admin';
|
||||
var amtpass = Q('dp10password').value;
|
||||
if (amtpass == '') amtuser = '';
|
||||
meshserver.send({ action: 'changedevice', nodeid: tag.node._id, intelamt: { user: amtuser, pass: amtpass, tls: Q('dp10tls').value } });
|
||||
tag.node.intelamt.user = amtuser;
|
||||
tag.node.intelamt.tls = Q('dp10tls').value;
|
||||
if (tag.func) { setTimeout(tag.func, 300); }
|
||||
}
|
||||
}
|
||||
|
||||
function p10showDeleteNodeDialog(nodeid) {
|
||||
if (xxdialogMode) return;
|
||||
setDialogMode(2, "Delete Node", 3, p10showDeleteNodeDialogEx, "Delete \"" + EscapeHtml(currentNode.name) + "\"?<br /><br /><input id=p10check type=checkbox onchange=p10validateDeleteNodeDialog() />Confirm", nodeid);
|
||||
p10validateDeleteNodeDialog();
|
||||
}
|
||||
|
||||
function p10validateDeleteNodeDialog() {
|
||||
QE('idx_dlgOkButton', Q('p10check').checked);
|
||||
}
|
||||
|
||||
function p10showDeleteNodeDialogEx(buttons, nodeid) {
|
||||
meshserver.send({ action: 'removedevices', nodeids: [ nodeid ] });
|
||||
}
|
||||
|
||||
function p10showiconselector() {
|
||||
if (xxdialogMode) return;
|
||||
var mesh = meshes[currentNode.meshid];
|
||||
@ -880,17 +1254,6 @@
|
||||
QE('idx_dlgOkButton', x);
|
||||
if ((e != null) && (x == true) && (e.keyCode == 13)) { dialogclose(1); }
|
||||
}
|
||||
|
||||
//
|
||||
// MY ACCOUNT
|
||||
//
|
||||
|
||||
function gotoMesh(meshid) {
|
||||
currentMesh = meshes[meshid];
|
||||
p20updateMesh();
|
||||
go(20);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// MY MESHS
|
||||
@ -898,6 +1261,7 @@
|
||||
|
||||
var currentMesh;
|
||||
function p20updateMesh() {
|
||||
if (currentMesh == null) return;
|
||||
QH('p20meshName', EscapeHtml(currentMesh.name));
|
||||
var meshtype = 'Unknown #' + currentMesh.mtype;
|
||||
var meshrights = currentMesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
|
||||
@ -914,7 +1278,7 @@
|
||||
|
||||
x += '<br style=clear:both><br>';
|
||||
var currentMeshLinks = currentMesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()];
|
||||
if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<a onclick=p20showAddMeshUserDialog() style=cursor:pointer;margin-right:10px><img src=images/icon-addnew.png border=0 height=12 width=12> Add User</a>'; }
|
||||
if (currentMeshLinks && ((currentMeshLinks.rights & 2) != 0)) { x += '<div style=margin-bottom:6px><a onclick=p20showAddMeshUserDialog() style=cursor:pointer><img src=images/icon-addnew.png border=0 height=12 width=12> Add User</a></div>'; }
|
||||
|
||||
/*
|
||||
if ((meshrights & 4) != 0) {
|
||||
@ -964,7 +1328,7 @@
|
||||
x += '</tbody></table>';
|
||||
|
||||
// If we are full administrator on this mesh, allow deletion of the mesh
|
||||
if (meshrights == 0xFFFFFFFF) { x += '<div style=font-size:x-small;text-align:right><span><a onclick=p20showDeleteMeshDialog() style=cursor:pointer>Delete Mesh</a></span></div>'; }
|
||||
if (meshrights == 0xFFFFFFFF) { x += '<div style=font-size:small;text-align:right;margin-top:6px><span><a onclick=p20showDeleteMeshDialog() style=cursor:pointer>Delete Mesh</a></span></div>'; }
|
||||
|
||||
QH('p20info', x);
|
||||
}
|
||||
@ -1141,6 +1505,7 @@
|
||||
function addHtmlValue2(t, v) { return '<div><div style=display:inline-block;float:right>' + v + '</div><div style=display:inline-block>' + t + '</div></div>'; }
|
||||
function addLink(x, f) { return "<a style=cursor:pointer;color:darkblue;text-decoration:none onclick='" + f + "'>♦ " + x + "</a>"; }
|
||||
function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
|
||||
function passwordcheck(p) { var re = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()]).{8,}/; return re.test(p); }
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
@ -886,13 +886,10 @@
|
||||
//QS('column_l').padding = '0';
|
||||
QS('column_l').width = 'calc(100% - 30px)';
|
||||
}
|
||||
drawDeviceTimeline();
|
||||
}
|
||||
|
||||
function getNodeFromId(id) {
|
||||
for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; }
|
||||
return null;
|
||||
}
|
||||
|
||||
function getNodeFromId(id) { for (var i in nodes) { if (nodes[i]._id == id) return nodes[i]; } return null; }
|
||||
function reload() { window.location.href = window.location.href; }
|
||||
|
||||
function onStateChanged(server, state) {
|
||||
@ -1279,6 +1276,7 @@
|
||||
|
||||
// Change the node
|
||||
node.name = message.event.node.name;
|
||||
node.rname = message.event.node.rname;
|
||||
node.host = message.event.node.host;
|
||||
node.desc = message.event.node.desc;
|
||||
node.publicip = message.event.node.publicip;
|
||||
@ -1600,8 +1598,8 @@
|
||||
}
|
||||
|
||||
// If there is nothing to display, explain the problem
|
||||
if ((r == '') && (meshcount > 0)) {
|
||||
if ((Q('SearchInput').value == '') && (sort == 3)) {
|
||||
if ((r == '') && (meshcount > 0) && (Q('SearchInput').value != '')) {
|
||||
if (sort == 3) {
|
||||
r = '<div style="margin:30px">No devices are included in any groups, click on a device\'s \"Groups\" to add to a group.</div>';
|
||||
} else {
|
||||
r = '<div style="margin:30px">No devices matching this search.</div>';
|
||||
@ -2874,11 +2872,15 @@
|
||||
var str = '';
|
||||
var provisioningStates = { 0: 'Not Activated (Pre)', 1: 'Not Activated (In)', 2: 'Activated' };
|
||||
if (node.intelamt.ver != null && node.intelamt.state == null) { str += '<i>Unknown State</i>, v' + node.intelamt.ver; } else
|
||||
if (node.intelamt.ver == null || node.intelamt.state == null) { str += '<i>Unknown Version & State</i>'; } else {
|
||||
|
||||
if ((node.intelamt.ver == null) && (node.intelamt.state == 2)) { str += '<i>Activated</i>'; }
|
||||
else if ((node.intelamt.ver == null) || (node.intelamt.state == null)) { str += '<i>Unknown Version & State</i>'; }
|
||||
else {
|
||||
str += provisioningStates[node.intelamt.state];
|
||||
if (node.intelamt.flags) { if (node.intelamt.flags & 2) { str += ' <span title="Intel AMT is activated in Client Control Mode">CCM</span>'; } else if (node.intelamt.flags & 4) { str += ' <span title="Intel AMT is activated in Admin Control Mode">ACM</span>'; } }
|
||||
str += (', v' + node.intelamt.ver);
|
||||
}
|
||||
|
||||
if (node.intelamt.tls == 1) { str += ', <span title="Intel AMT is setup with TLS network security">TLS</span>'; }
|
||||
if (node.intelamt.state == 2) {
|
||||
if (node.intelamt.user == null || node.intelamt.user == '') {
|
||||
@ -2977,7 +2979,7 @@
|
||||
QV('MainDevDesktop', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 1) != 0)) && (meshrights & 8));
|
||||
QV('MainDevTerminal', ((mesh.mtype == 1) || (node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 2) != 0)) && (meshrights & 8));
|
||||
QV('MainDevFiles', ((mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 4) != 0))) && (meshrights & 8));
|
||||
QV('MainDevAmt', (node.intelamt != null) && (node.intelamt.state == 2) && (meshrights & 8));
|
||||
QV('MainDevAmt', (node.intelamt != null) && ((node.intelamt.state == 2) || (node.conn & 2)) && (meshrights & 8));
|
||||
QV('MainDevConsole', (consoleRights && (mesh.mtype == 2) && ((node.agent == null) || (node.agent.caps == null) || ((node.agent.caps & 8) != 0))) && (meshrights & 8));
|
||||
QV('p15uploadCore', (node.agent != null) && (node.agent.caps != null) && ((node.agent.caps & 16) != 0) && (userinfo.siteadmin == 0xFFFFFFFF));
|
||||
QH('p15coreName', ((node.agent != null) && (node.agent.core != null))?node.agent.core:'');
|
||||
@ -2996,7 +2998,7 @@
|
||||
QV('filesActionsBtn', (meshrights & 72) != 0);
|
||||
|
||||
// Request the power timeline
|
||||
if ((powerTimelineNode != currentNode._id) && (powerTimelineReq != currentNode._id)) { powerTimelineReq = currentNode._id; meshserver.send({ action: 'powertimeline', nodeid: currentNode._id }); }
|
||||
if ((powerTimelineNode != currentNode._id) && (powerTimelineReq != currentNode._id)) { QH('p10html2', ''); powerTimelineReq = currentNode._id; meshserver.send({ action: 'powertimeline', nodeid: currentNode._id }); }
|
||||
|
||||
// Reset the desktop tools
|
||||
QV('DeskTools', false);
|
||||
@ -3072,6 +3074,7 @@
|
||||
|
||||
// Draw device power bars. The bars are 766px wide.
|
||||
function drawDeviceTimeline() {
|
||||
if ((currentNode == null) || (xxcurrentView < 10) || (xxcurrentView > 19)) return;
|
||||
var timeline = null, now = Date.now();
|
||||
if (currentNode._id == powerTimelineNode) { timeline = powerTimeline; }
|
||||
|
||||
@ -3096,6 +3099,7 @@
|
||||
|
||||
// Draw the timeline
|
||||
var x = '', count = 1, date = new Date();
|
||||
var totalWidth = Q('masthead').offsetWidth - (160 + 9 + 9 + 14); // Compute the total width of the power bar
|
||||
date.setHours(0, 0, 0, 0);
|
||||
for (var i = 0; i < 7; i++) {
|
||||
var datavalue = '', start = date.getTime(), end = start + (1000 * 60 * 60 * 24);
|
||||
@ -3104,7 +3108,7 @@
|
||||
if (isTimeBlockInside(start, end, block[0], block[1]) == true) {
|
||||
var ts = Math.max(start, block[0]);
|
||||
var te = Math.min(Math.min(end, block[1]), now);
|
||||
var width = Math.round((te - ts) / 112794);
|
||||
var width = Math.round(((te - ts) * totalWidth) / 86400000);
|
||||
if (width > 0) {
|
||||
var title = powerStateStrings2[block[2]] + ' from ' + new Date(ts).toLocaleTimeString() + ' to ' + new Date(te).toLocaleTimeString() + '.';
|
||||
datavalue += '<div title="' + title + '" style=display:table-cell;width:' + width + 'px;background-color:' + powerColor(block[2]) + ';height:16px></div>';
|
||||
@ -4657,6 +4661,7 @@
|
||||
|
||||
var currentMesh;
|
||||
function p20updateMesh() {
|
||||
if (currentMesh == null) return;
|
||||
QH('p20meshName', EscapeHtml(currentMesh.name));
|
||||
var meshtype = 'Unknown #' + currentMesh.mtype;
|
||||
var meshrights = currentMesh.links['user/{{{domain}}}/' + userinfo.name.toLowerCase()].rights;
|
||||
@ -5710,7 +5715,10 @@
|
||||
if (((b & 8) || x) && f) f(x, t);
|
||||
}
|
||||
|
||||
function center() { QS('dialog').left = ((((getDocWidth() - 400) / 2)) + "px"); deskAdjust(); }
|
||||
function center() {
|
||||
QS('dialog').left = ((((getDocWidth() - 400) / 2)) + "px"); deskAdjust();
|
||||
drawDeviceTimeline();
|
||||
}
|
||||
function messagebox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
|
||||
function statusbox(t, m) { QH('id_dialogMessage', m); setDialogMode(1, t); }
|
||||
function getDocWidth() { if (window.innerWidth) return window.innerWidth; if (document.documentElement && document.documentElement.clientWidth && document.documentElement.clientWidth != 0) return document.documentElement.clientWidth; return document.getElementsByTagName('body')[0].clientWidth; }
|
||||
|
Loading…
Reference in New Issue
Block a user