Improved web app when dealing with lots of devices.

Ylian Saint-Hilaire committed Dec 7, 2020 at 01:32 UTC a7c7ee7e66f986b87328f6167b32a133bc5f2785
1 file changed +255 -109
views/default.handlebars
+255 -109
@@ -321,7 +321,7 @@
321 </tr>
322 </table>
323 </div>
324 - <div id="xdevices" class="noselect" style="display:none"></div>
324 + <div id="xdevices" class="noselect" style="display:none" onscroll="onDevicesScroll()"></div>
325 <div id="xdevicesmap" style="display:none">
326 <div id=xmapSearchResultsDlg style="display:none">
327 <div id=xmapSearchResultsBck>
@@ -2854,7 +2854,8 @@
2854 if (message.event.node.icon) { node.icon = message.event.node.icon; }
2855
2856 // Web page update
2857 - mainUpdate(2 | 4 | 8 | 16);
2857 + updateDeviceViewDevice(node);
2858 + mainUpdate(2 | 8 | 16);
2859 refreshDevice(node._id);
2860
2861 if ((currentNode == node) && (xxdialogMode != null) && (xxdialogTag == '@xxmap')) { p10showNodeLocationDialog(); }
@@ -2940,7 +2941,8 @@
2941 if ((node.conn & 1) == 0) { delete node.sessions; }
2942
2943 // Web page update
2943 - mainUpdate(1 | 4 | 16);
2944 + updateDeviceViewDevice(node);
2945 + mainUpdate(1 | 16);
2946 refreshDevice(node._id);
2947 }
2948 break;
@@ -3033,7 +3035,7 @@
3035 for (var i in node.sessions) { if (Object.keys(node.sessions[i]).length == 0) { delete node.sessions[i]; } }
3036 if (Object.keys(node.sessions).length == 0) { delete node.sessions; }
3037 }
3036 - mainUpdate(4);
3038 + updateDeviceViewDevice(node);
3039 if ((currentNode != null) && (currentNode._id == message.event.nodeid)) { gotoDevice(currentNode._id, xxcurrentView, true); }
3040
3041 // If we are looking at the sessions dialog box for this device now, update it
@@ -3494,7 +3496,7 @@
3496 deviceHeaderSet();
3497 if ((view == 1) && (current !== null)) { if (c == 2) { r += '<td><div style=width:301px></div></td>'; } if (r != '') { r += '</tr></table>'; } }
3498
3497 - if (view == 2) { r += '<tr><td>'; }
3499 + if (view == 2) { r += '<tr><td colspan=5>'; }
3500 r += '<div class=DevSt style=width:100%;padding-top:4px><span id=DevxHeader' + deviceHeaderId + ' class=devHeaderx style=float:right></span>';
3501 if ((view == 1) || (view == 2) || (view == 3)) {
3502 var collapsed = CollapsedGroups['pwr:' + pwr];
@@ -3512,115 +3514,101 @@
3514 }
3515
3516 count++;
3515 - var title = EscapeHtml(node.name);
3516 - if (title.length == 0) { title = '<i>' + "None" + '</i>'; }
3517 - if ((node.rname != null) && (node.rname.length > 0)) { title += ' / ' + EscapeHtml(node.rname); }
3518 - var name = EscapeHtml(node.name);
3519 - if (showRealNames == true && node.rname != null) name = EscapeHtml(node.rname);
3520 - if (name.length == 0) { name = '<i>' + "None" + '</i>'; }
3521 -
3522 - // Add device notification icons
3523 - var devNotify = '', devNotifySub = '';
3524 -
3525 - // This device is "starred"
3526 - if (stars[node._id] == 1) {
3527 - if (view == 2) {
3528 - devNotifySub += '<img class=deviceNotifySmallDotSub src=images/icon-star-notify-10.png width=10 height=10>';
3529 - } else {
3530 - devNotifySub += '<img class=deviceNotifyDotSub src=images/icon-star-notify-16.png width=16 height=16>';
3531 - }
3532 - }
3533 -
3534 - // This device has session information
3535 - if (node.sessions != null) {
3536 - // Display any agent messages
3537 - if (node.sessions.msg != null) {
3538 - if (view == 2) {
3539 - devNotifySub += '<div onclick=showDeviceMessages(\'' + node._id + '\',null,event) style="width:10;height:10" class=deviceNotifySmallDotSub></div>';
3540 - } else {
3541 - devNotifySub += '<div onclick=showDeviceMessages(\'' + node._id + '\',null,event) style="width:16;height:16" class=deviceNotifyDotSub>' + Object.keys(node.sessions.msg).length + '</div>';
3517 + if (view == 1) {
3518 + // Draw the device standin
3519 + r += '<div name=xxdevice1 id=xv1' + node._id + ' style=display:inline-block;position:relative;width:' + deviceBoxWidth + 'px;height:50px;padding-top:1px;padding-bottom:1px></div>';
3520 + } else if (view == 2) {
3521 + // Draw the device standin
3522 + var collapseName = node.meshid;
3523 + if (sort == 1) { collapseName = ('pwr:' + (node.pwr?node.pwr:0)); }
3524 + else if ((sort == 3) || (sort == 4)) { collapseName = 'tag:**xx**xx*TaG*xx**xx**'; }
3525 + var collapsed = (sort != 3) & (sort != 4) & CollapsedGroups[collapseName];
3526 + r += '<tr name=xxdevice2 colname=DevxCol' + collapseName + ' style=height:20px' + (collapsed?';display:none':'') + ' id=xv2' + node._id + '></tr>';
3527 + } else if ((view == 3) && (node.conn & 1) && (((meshrights & 8) || (meshrights & 256)) != 0) && ((node.agent.caps & 1) != 0)) { // Check if we have rights and agent is capable of KVM.
3528 + if ((multiDesktopFilter) && ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + node._id) >= 0))) {
3529 + var title = EscapeHtml(node.name);
3530 + if (title.length == 0) { title = '<i>' + "None" + '</i>'; }
3531 + if ((node.rname != null) && (node.rname.length > 0)) { title += ' / ' + EscapeHtml(node.rname); }
3532 + var name = EscapeHtml(node.name);
3533 + if (showRealNames == true && node.rname != null) name = EscapeHtml(node.rname);
3534 + if (name.length == 0) { name = '<i>' + "None" + '</i>'; }
3535 +
3536 + // Add device notification icons
3537 + var devNotify = '', devNotifySub = '';
3538 +
3539 + // This device is "starred"
3540 + if (stars[node._id] == 1) {
3541 + if (view == 2) {
3542 + devNotifySub += '<img class=deviceNotifySmallDotSub src=images/icon-star-notify-10.png width=10 height=10>';
3543 + } else {
3544 + devNotifySub += '<img class=deviceNotifyDotSub src=images/icon-star-notify-16.png width=16 height=16>';
3545 + }
3546 }
3543 - }
3547
3545 - // Sessions are active
3546 - if ((node.sessions.kvm != null) || (node.sessions.terminal != null) || (node.sessions.files != null) || (node.sessions.tcp != null) || (node.sessions.udp != null)) {
3547 - if (view == 2) {
3548 - devNotifySub += '<img onclick=showDeviceSessions(\'' + node._id + '\',null,event) class=deviceNotifySmallDotSub src=images/icon-relay-notify10.png width=10 height=10>';
3549 - } else {
3550 - devNotifySub += '<img onclick=showDeviceSessions(\'' + node._id + '\',null,event) class=deviceNotifyDotSub src=images/icon-relay-notify.png width=16 height=16>';
3551 - }
3552 - }
3548 + // This device has session information
3549 + if (node.sessions != null) {
3550 + // Display any agent messages
3551 + if (node.sessions.msg != null) {
3552 + if (view == 2) {
3553 + devNotifySub += '<div onclick=showDeviceMessages(\'' + node._id + '\',null,event) style="width:10;height:10" class=deviceNotifySmallDotSub></div>';
3554 + } else {
3555 + devNotifySub += '<div onclick=showDeviceMessages(\'' + node._id + '\',null,event) style="width:16;height:16" class=deviceNotifyDotSub>' + Object.keys(node.sessions.msg).length + '</div>';
3556 + }
3557 + }
3558
3554 - // Help is required
3555 - if (node.sessions.help != null) {
3556 - if (view == 2) {
3557 - devNotifySub += '<img onclick=showDeviceHelpRequests(\'' + node._id + '\',null,event) class=deviceNotifySmallDotSub src=images/icon-help-notify-10.png width=10 height=10>';
3558 - } else {
3559 - devNotifySub += '<img onclick=showDeviceHelpRequests(\'' + node._id + '\',null,event) class=deviceNotifyDotSub src=images/icon-help-notify-16.png width=16 height=16>';
3560 - }
3561 - }
3559 + // Sessions are active
3560 + if ((node.sessions.kvm != null) || (node.sessions.terminal != null) || (node.sessions.files != null) || (node.sessions.tcp != null) || (node.sessions.udp != null)) {
3561 + if (view == 2) {
3562 + devNotifySub += '<img onclick=showDeviceSessions(\'' + node._id + '\',null,event) class=deviceNotifySmallDotSub src=images/icon-relay-notify10.png width=10 height=10>';
3563 + } else {
3564 + devNotifySub += '<img onclick=showDeviceSessions(\'' + node._id + '\',null,event) class=deviceNotifyDotSub src=images/icon-relay-notify.png width=16 height=16>';
3565 + }
3566 + }
3567
3563 - // Battery state
3564 - if ((node.sessions.battery != null) && (view == 1)) {
3565 - var bat = node.sessions.battery;
3566 - var statestr = '';
3567 - if (bat.state == 'ac') { statestr = "Device is plugged-in"; }
3568 - if (bat.state == 'dc') { statestr = "Device is battery powered"; }
3569 -
3570 - var levelstr = '', levelnum = -1;
3571 - if ((typeof bat.level == 'number') && (bat.level >= 0) && (bat.level <= 100)) {
3572 - levelstr = bat.level + '%';
3573 - levelnum = (Math.floor((bat.level + 10) / 25) + 1);
3574 - if (levelnum > 5) { lvl = 5; }
3575 - if (bat.state == 'ac') { if (bat.level == 100) { levelnum = 11; } else { levelnum += 5; } }
3576 - }
3568 + // Help is required
3569 + if (node.sessions.help != null) {
3570 + if (view == 2) {
3571 + devNotifySub += '<img onclick=showDeviceHelpRequests(\'' + node._id + '\',null,event) class=deviceNotifySmallDotSub src=images/icon-help-notify-10.png width=10 height=10>';
3572 + } else {
3573 + devNotifySub += '<img onclick=showDeviceHelpRequests(\'' + node._id + '\',null,event) class=deviceNotifyDotSub src=images/icon-help-notify-16.png width=16 height=16>';
3574 + }
3575 + }
3576 +
3577 + // Battery state
3578 + if ((node.sessions.battery != null) && (view == 1)) {
3579 + var bat = node.sessions.battery;
3580 + var statestr = '';
3581 + if (bat.state == 'ac') { statestr = "Device is plugged-in"; }
3582 + if (bat.state == 'dc') { statestr = "Device is battery powered"; }
3583 +
3584 + var levelstr = '', levelnum = -1;
3585 + if ((typeof bat.level == 'number') && (bat.level >= 0) && (bat.level <= 100)) {
3586 + levelstr = bat.level + '%';
3587 + levelnum = (Math.floor((bat.level + 10) / 25) + 1);
3588 + if (levelnum > 5) { lvl = 5; }
3589 + if (bat.state == 'ac') { if (bat.level == 100) { levelnum = 11; } else { levelnum += 5; } }
3590 + }
3591
3578 - if (levelnum > 0) {
3579 - devNotify += '<div class="deviceBatterySmall deviceBatterySmall' + levelnum + '" title="' + ((statestr != null)?(statestr + ', ' + levelstr):levelstr) + '"></div>';
3592 + if (levelnum > 0) {
3593 + devNotify += '<div class="deviceBatterySmall deviceBatterySmall' + levelnum + '" title="' + ((statestr != null)?(statestr + ', ' + levelstr):levelstr) + '"></div>';
3594 + }
3595 + }
3596 }
3581 - }
3582 - }
3597
3584 - // Add any device icons
3585 - if (devNotifySub != '') {
3586 - if (view == 2) {
3587 - devNotify += '<div class=deviceNotifySmallDot>' + devNotifySub + '</div>';
3588 - } else {
3589 - devNotify += '<div class=deviceNotifyDot>' + devNotifySub + '</div>';
3590 - }
3591 - }
3598 + // Add any device icons
3599 + if (devNotifySub != '') {
3600 + if (view == 2) {
3601 + devNotify += '<div class=deviceNotifySmallDot>' + devNotifySub + '</div>';
3602 + } else {
3603 + devNotify += '<div class=deviceNotifyDot>' + devNotifySub + '</div>';
3604 + }
3605 + }
3606
3593 - // Node
3594 - var icon = node.icon;
3595 - if ((!node.conn) || (node.conn == 0)) { icon += ' gray'; }
3596 - if (view == 1) {
3597 - r += '<div id=devs cmenu=devsContentMenu onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=display:inline-block;position:relative;width:' + deviceBoxWidth + 'px;height:50px;padding-top:1px;padding-bottom:1px><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div><div style=height:100%;cursor:pointer tabindex=0 onclick=gotoDevice(\'' + node._id + '\',null,null,event) onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',null,null,event)"><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 style=width:' + (deviceBoxWidth - 100) + 'px title="' + title + '">' + name + '</div><div>' + NodeStateStr(node) + '</div></div><div class=g2></div></div></div>' + devNotify + '</div>';
3598 - } else if (view == 2) {
3599 - var states = [];
3600 - if (node.conn) {
3601 - if ((node.conn & 1) != 0) { states.push('<span title="' + "Mesh agent is connected and ready for use." + '">' + "Agent" + '</span>'); }
3602 - if ((node.conn & 2) != 0) { states.push('<span title="' + "Intel&reg; AMT CIRA is connected and ready for use." + '">' + "CIRA" + '</span>'); }
3603 - else if ((node.conn & 4) != 0) { states.push('<span title="' + "Intel&reg; AMT is routable." + '">' + "AMT" + '</span>'); }
3604 - if ((node.conn & 8) != 0) { states.push('<span title="' + "Mesh agent is reachable using another agent as relay." + '">' + "Relay" + '</span>'); }
3605 - if ((node.conn & 16) != 0) { states.push('<span title="' + "MQTT connection to the device is active." + '">' + "MQTT" + '</span>'); }
3606 - }
3607 + // Node
3608 + var icon = node.icon;
3609 + if ((!node.conn) || (node.conn == 0)) { icon += ' gray'; }
3610
3608 - var collapseName = node.meshid;
3609 - if (sort == 1) { collapseName = ('pwr:' + (node.pwr?node.pwr:0)); }
3610 - else if ((sort == 3) || (sort == 4)) { collapseName = 'tag:**xx**xx*TaG*xx**xx**'; }
3611 - var collapsed = (sort != 3) & (sort != 4) & CollapsedGroups[collapseName];
3612 - r += '<tr name=DevxCol' + collapseName + (collapsed?' style=display:none':'') + '><td style=position:relative><div id=devs cmenu=devsContentMenu class=bar18 tabindex=0 onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=height:18px;width:100%;font-size:medium onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',null,null,event)">';
3613 - r += '<div class=deviceBarCheckbox><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div>';
3614 - r += '<div class=deviceBarIcon onclick=gotoDevice(\'' + node._id + '\',null,null,event)><div class="j' + icon + '" style=width:16px;margin-top:1px;margin-left:2px;height:16px></div></div>';
3615 - r += '<div class=g1 style=height:18px;float:left></div><div class=g2 style=height:18px;float:right></div>';
3616 - r += '<div class=style10 style=cursor:pointer;font-size:14px title="' + title + '" onclick=gotoDevice(\'' + node._id + '\',null,null,event)><span style=width:300px>' + name + '</span></div></div>' + devNotify + '</td>';
3617 - r += '<td style=text-align:center>' + getUserShortStr(node);
3618 - r += '<td style=text-align:center>' + (node.ip != null ? node.ip : '');
3619 - r += '<td style=text-align:center>' + states.join('&nbsp;+&nbsp;');
3620 - //r += '<td style=text-align:center>' + (node.pwr != null ? powerStateStrings[node.pwr] : '');
3621 - r += '</tr>';
3622 - } else if ((view == 3) && (node.conn & 1) && (((meshrights & 8) || (meshrights & 256)) != 0) && ((node.agent.caps & 1) != 0)) { // Check if we have rights and agent is capable of KVM.
3623 - if ((multiDesktopFilter) && ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + node._id) >= 0))) {
3611 + // Draw the device and canvas
3612 r += '<div id=devs cmenu=devsContentMenu style=display:inline-block;position:relative;margin:1px;background-color:lightgray;border-radius:5px;position:relative><div tabindex=0 style=padding:3px;cursor:pointer onclick=gotoDevice(\'' + node._id + '\',11,null,event) onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',11,null,event)">' + devNotify;
3613 //r += '<input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox style=float:left>';
3614 r += '<div class="j' + icon + '" style=width:16px;float:left></div>&nbsp;' + name + '</div>';
@@ -3829,6 +3817,161 @@
3817 }
3818 }
3819 oldviewmode = view;
3820 + onDevicesScrollEx();
3821 + }
3822 +
3823 +
3824 + var onDevicesTouchActive = false;
3825 + var onDevicesScrollnagleTimer = null;
3826 + function onDevicesScroll() {
3827 + if ((onDevicesScrollnagleTimer != null) || (onDevicesTouchActive)) return;
3828 + onDevicesScrollnagleTimer = setTimeout(onDevicesScrollEx, 250);
3829 + }
3830 +
3831 + function onDeviceTouch(x) {
3832 + if (onDevicesTouchActive == x) return;
3833 + onDevicesTouchActive = x;
3834 + if (x == false) onDevicesScrollEx();
3835 + }
3836 +
3837 + function onDevicesScrollEx() {
3838 + onDevicesScrollnagleTimer = null;
3839 + var visibleTop = Q('xdevices').scrollTop - 200, visibleBottom = Q('xdevices').scrollTop + Q('xdevices').clientHeight + 200;
3840 + var view = Q('viewselect').value, devdivs = document.getElementsByName('xxdevice' + view);
3841 + for (var i = 0; i < devdivs.length; i++) {
3842 + if ((devdivs[i].offsetTop >= visibleTop) && (devdivs[i].offsetTop < visibleBottom)) {
3843 + var node = getNodeFromId(devdivs[i].id.substring(3));
3844 + if (node != null) { updateDeviceViewHtml(view, devdivs[i], node); } else { devdivs[i].innerHTML = ''; }
3845 + } else {
3846 + devdivs[i].innerHTML = '';
3847 + }
3848 + }
3849 + }
3850 +
3851 + // Update a single device in the current view
3852 + function updateDeviceViewDevice(node) {
3853 + var view = Q('viewselect').value;
3854 + if ((view != 1) && (view != 2)) { mainUpdate(4); return; }
3855 + if (typeof node == 'string') { node = getNodeFromId(node); }
3856 + if (node == null) return;
3857 + var devdiv = Q('xv' + view + node._id);
3858 + if (devdiv.innerHTML != '') { updateDeviceViewHtml(view, devdiv, node); } // Only update if the device is visible
3859 + }
3860 +
3861 + function updateDeviceViewHtml(view, div, node) {
3862 + var deviceBoxWidth = div.clientWidth;
3863 +
3864 + var title = EscapeHtml(node.name);
3865 + if (title.length == 0) { title = '<i>' + "None" + '</i>'; }
3866 + if ((node.rname != null) && (node.rname.length > 0)) { title += ' / ' + EscapeHtml(node.rname); }
3867 + var name = EscapeHtml(node.name);
3868 + if (showRealNames == true && node.rname != null) name = EscapeHtml(node.rname);
3869 + if (name.length == 0) { name = '<i>' + "None" + '</i>'; }
3870 +
3871 + // Add device notification icons
3872 + var devNotify = '', devNotifySub = '';
3873 +
3874 + // This device is "starred"
3875 + if (stars[node._id] == 1) {
3876 + if (view == 2) {
3877 + devNotifySub += '<img class=deviceNotifySmallDotSub src=images/icon-star-notify-10.png width=10 height=10>';
3878 + } else {
3879 + devNotifySub += '<img class=deviceNotifyDotSub src=images/icon-star-notify-16.png width=16 height=16>';
3880 + }
3881 + }
3882 +
3883 + // This device has session information
3884 + if (node.sessions != null) {
3885 + // Display any agent messages
3886 + if (node.sessions.msg != null) {
3887 + if (view == 2) {
3888 + devNotifySub += '<div onclick=showDeviceMessages(\'' + node._id + '\',null,event) style="width:10;height:10" class=deviceNotifySmallDotSub></div>';
3889 + } else {
3890 + devNotifySub += '<div onclick=showDeviceMessages(\'' + node._id + '\',null,event) style="width:16;height:16" class=deviceNotifyDotSub>' + Object.keys(node.sessions.msg).length + '</div>';
3891 + }
3892 + }
3893 +
3894 + // Sessions are active
3895 + if ((node.sessions.kvm != null) || (node.sessions.terminal != null) || (node.sessions.files != null) || (node.sessions.tcp != null) || (node.sessions.udp != null)) {
3896 + if (view == 2) {
3897 + devNotifySub += '<img onclick=showDeviceSessions(\'' + node._id + '\',null,event) class=deviceNotifySmallDotSub src=images/icon-relay-notify10.png width=10 height=10>';
3898 + } else {
3899 + devNotifySub += '<img onclick=showDeviceSessions(\'' + node._id + '\',null,event) class=deviceNotifyDotSub src=images/icon-relay-notify.png width=16 height=16>';
3900 + }
3901 + }
3902 +
3903 + // Help is required
3904 + if (node.sessions.help != null) {
3905 + if (view == 2) {
3906 + devNotifySub += '<img onclick=showDeviceHelpRequests(\'' + node._id + '\',null,event) class=deviceNotifySmallDotSub src=images/icon-help-notify-10.png width=10 height=10>';
3907 + } else {
3908 + devNotifySub += '<img onclick=showDeviceHelpRequests(\'' + node._id + '\',null,event) class=deviceNotifyDotSub src=images/icon-help-notify-16.png width=16 height=16>';
3909 + }
3910 + }
3911 +
3912 + // Battery state
3913 + if ((node.sessions.battery != null) && (view == 1)) {
3914 + var bat = node.sessions.battery;
3915 + var statestr = '';
3916 + if (bat.state == 'ac') { statestr = "Device is plugged-in"; }
3917 + if (bat.state == 'dc') { statestr = "Device is battery powered"; }
3918 +
3919 + var levelstr = '', levelnum = -1;
3920 + if ((typeof bat.level == 'number') && (bat.level >= 0) && (bat.level <= 100)) {
3921 + levelstr = bat.level + '%';
3922 + levelnum = (Math.floor((bat.level + 10) / 25) + 1);
3923 + if (levelnum > 5) { lvl = 5; }
3924 + if (bat.state == 'ac') { if (bat.level == 100) { levelnum = 11; } else { levelnum += 5; } }
3925 + }
3926 +
3927 + if (levelnum > 0) {
3928 + devNotify += '<div class="deviceBatterySmall deviceBatterySmall' + levelnum + '" title="' + ((statestr != null)?(statestr + ', ' + levelstr):levelstr) + '"></div>';
3929 + }
3930 + }
3931 + }
3932 +
3933 + // Add any device icons
3934 + if (devNotifySub != '') {
3935 + if (view == 2) {
3936 + devNotify += '<div class=deviceNotifySmallDot>' + devNotifySub + '</div>';
3937 + } else {
3938 + devNotify += '<div class=deviceNotifyDot>' + devNotifySub + '</div>';
3939 + }
3940 + }
3941 +
3942 + // Node
3943 + var icon = node.icon;
3944 + if ((!node.conn) || (node.conn == 0)) { icon += ' gray'; }
3945 +
3946 + if (view == 1) {
3947 + div.innerHTML = '<div id=devs cmenu=devsContentMenu onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=width:100%;height:100%><div style=width:22px;height:50%;float:left;padding-top:12px><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div><div style=height:100%;cursor:pointer tabindex=0 onclick=gotoDevice(\'' + node._id + '\',null,null,event) onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',null,null,event)"><div class="i' + icon + '" style=width:50px;float:left></div><div style=height:100%><div class=g1></div><div class=e2><div class=e1 style=width:' + (deviceBoxWidth - 100) + 'px title="' + title + '">' + name + '</div><div>' + NodeStateStr(node) + '</div></div><div class=g2></div></div></div>' + devNotify + '</div>';
3948 + } else {
3949 + var states = [];
3950 + if (node.conn) {
3951 + if ((node.conn & 1) != 0) { states.push('<span title="' + "Mesh agent is connected and ready for use." + '">' + "Agent" + '</span>'); }
3952 + if ((node.conn & 2) != 0) { states.push('<span title="' + "Intel&reg; AMT CIRA is connected and ready for use." + '">' + "CIRA" + '</span>'); }
3953 + else if ((node.conn & 4) != 0) { states.push('<span title="' + "Intel&reg; AMT is routable." + '">' + "AMT" + '</span>'); }
3954 + if ((node.conn & 8) != 0) { states.push('<span title="' + "Mesh agent is reachable using another agent as relay." + '">' + "Relay" + '</span>'); }
3955 + if ((node.conn & 16) != 0) { states.push('<span title="' + "MQTT connection to the device is active." + '">' + "MQTT" + '</span>'); }
3956 + }
3957 +
3958 + var collapseName = node.meshid;
3959 + if (sort == 1) { collapseName = ('pwr:' + (node.pwr?node.pwr:0)); }
3960 + else if ((sort == 3) || (sort == 4)) { collapseName = 'tag:**xx**xx*TaG*xx**xx**'; }
3961 + var collapsed = (sort != 3) & (sort != 4) & CollapsedGroups[collapseName];
3962 + //r += '<tr name=DevxCol' + collapseName + (collapsed?' style=display:none':'') + '><td style=position:relative><div id=devs cmenu=devsContentMenu class=bar18 tabindex=0 onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=height:18px;width:100%;font-size:medium onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',null,null,event)">';
3963 + var r = '<td style=position:relative><div id=devs cmenu=devsContentMenu class=bar18 tabindex=0 onmouseover=devMouseHover(this,1) onmouseout=devMouseHover(this,0) style=height:18px;width:100%;font-size:medium onkeypress="if (event.key==\'Enter\') gotoDevice(\'' + node._id + '\',null,null,event)">';
3964 + r += '<div class=deviceBarCheckbox><input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox></div>';
3965 + r += '<div class=deviceBarIcon onclick=gotoDevice(\'' + node._id + '\',null,null,event)><div class="j' + icon + '" style=width:16px;margin-top:1px;margin-left:2px;height:16px></div></div>';
3966 + r += '<div class=g1 style=height:18px;float:left></div><div class=g2 style=height:18px;float:right></div>';
3967 + r += '<div class=style10 style=cursor:pointer;font-size:14px title="' + title + '" onclick=gotoDevice(\'' + node._id + '\',null,null,event)><span style=width:300px>' + name + '</span></div></div>' + devNotify + '</td>';
3968 + r += '<td style=text-align:center>' + getUserShortStr(node);
3969 + r += '<td style=text-align:center>' + (node.ip != null ? node.ip : '');
3970 + r += '<td style=text-align:center>' + states.join('&nbsp;+&nbsp;');
3971 + //r += '<td style=text-align:center>' + (node.pwr != null ? powerStateStrings[node.pwr] : '');
3972 + //r += '</tr>';
3973 + div.innerHTML = r;
3974 + }
3975 }
3976
3977 // Show device help requests
@@ -3904,9 +4047,11 @@
4047 var x;
4048 if (type == 2) {
4049 // Table rows collapse
3907 - var rows = document.getElementsByName('DevxCol' + id2);
3908 - if (rows.length == 0) return;
3909 - x = (rows[0].style['display'] == 'none');
4050 + var xrows = document.getElementsByName('xxdevice2');
4051 + if (xrows.length == 0) return;
4052 + var rows = [];
4053 + for (var i = 0; i < xrows.length; i++) { if (xrows[i].attributes.colname.value.substring(7) == id2) { rows.push(xrows[i]); } }
4054 + var x = (rows[0].style['display'] == 'none');
4055 if (x) { delete CollapsedGroups[id2]; } else { CollapsedGroups[id2] = true; }
4056 for (var i = 0; i < rows.length; i++) { rows[i].style['display'] = (x ? '' : 'none'); }
4057 } else {
@@ -4847,7 +4992,8 @@
4992 var starcount = Object.keys(stars).length;
4993 for (var i in selectedDevices) { if ((starcount < 20) && (stars[selectedDevices[i]] == null)) { stars[selectedDevices[i]] = 1; starcount++; } }
4994 putstore('stars', JSON.stringify(stars));
4850 - if (Q('DevFilterSelect').value == 3) { mainUpdate(5); } else { mainUpdate(4); }
4995 + updateDeviceViewDevice(nodeid);
4996 + if (Q('DevFilterSelect').value == 3) { mainUpdate(1); }
4997 }
4998 }
4999