Web app improvements and support for high SPI screens.

Ylian Saint-Hilaire committed Dec 7, 2020 at 19:13 UTC c99048be135a16c85998d6a1af8c198d0540262a
16 files changed +184 -208
meshuser.js
+1 -1
@@ -3526,7 +3526,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
3526 // Event the node change
3527 var newMesh = parent.meshes[command.meshid];
3528 var event = { etype: 'node', userid: user._id, username: user.name, action: 'nodemeshchange', nodeid: node._id, node: node, oldMeshId: oldMeshId, newMeshId: command.meshid, msgid: 85, msgArgs: [node.name, newMesh.name], msg: 'Moved device ' + node.name + ' to group ' + newMesh.name, domain: domain.id };
3529 - if (db.changeStream) { event.noact = 1; } // If DB change stream is active, don't use this event to change the mesh. Another event will come.
3529 + // Even if change stream is enabled on this server, we still make the nodemeshchange actionable. This is because the DB can't send out a change event that will match this.
3530 parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(command.meshid, [oldMeshId, node._id]), obj, event);
3531
3532 // Send response if required
public/images/icons100.png
Binary files /dev/null and b/public/images/icons100.png differ
public/images/icons32.png
Binary files /dev/null and b/public/images/icons32.png differ
public/images/leftbar-128.png
Binary files /dev/null and b/public/images/leftbar-128.png differ
public/images/webp/icons100.webp
Binary files /dev/null and b/public/images/webp/icons100.webp differ
public/images/webp/icons16.webp
Binary files /dev/null and b/public/images/webp/icons16.webp differ
public/images/webp/icons32.webp
Binary files /dev/null and b/public/images/webp/icons32.webp differ
public/images/webp/icons50.webp
Binary files /dev/null and b/public/images/webp/icons50.webp differ
public/images/webp/leftbar-128.webp
Binary files /dev/null and b/public/images/webp/leftbar-128.webp differ
public/images/webp/leftbar-64.webp
Binary files /dev/null and b/public/images/webp/leftbar-64.webp differ
public/images/webp/notify24.webp
Binary files /dev/null and b/public/images/webp/notify24.webp differ
public/images/webp/notify48.webp
Binary files /dev/null and b/public/images/webp/notify48.webp differ
public/styles/style.css
+42 -11
@@ -858,17 +858,17 @@ NoMeshesPanel img {
858 box-shadow:none;
859 }
860
861 -.deviceBatterySmall1 { background: url(../images/batteries24.png) 0px 0px; }
862 -.deviceBatterySmall2 { background: url(../images/batteries24.png) -14px 0px; }
863 -.deviceBatterySmall3 { background: url(../images/batteries24.png) -28px 0px; }
864 -.deviceBatterySmall4 { background: url(../images/batteries24.png) -42px 0px; }
865 -.deviceBatterySmall5 { background: url(../images/batteries24.png) -56px 0px; }
866 -.deviceBatterySmall6 { background: url(../images/batteries24.png) -70px 0px; }
867 -.deviceBatterySmall7 { background: url(../images/batteries24.png) -84px 0px; }
868 -.deviceBatterySmall8 { background: url(../images/batteries24.png) -98px 0px; }
869 -.deviceBatterySmall9 { background: url(../images/batteries24.png) -112px 0px; }
870 -.deviceBatterySmall10 { background: url(../images/batteries24.png) -126px 0px; }
871 -.deviceBatterySmall11 { background: url(../images/batteries24.png) -140px 0px; }
861 +.deviceBatterySmall1 { background: url(../images/batteries24.png) 0px 0px; background-image: -webkit-image-set(url(../images/batteries24.png) 1x, url(../images/batteries48.png) 2x); }
862 +.deviceBatterySmall2 { background: url(../images/batteries24.png) -14px 0px; background-image: -webkit-image-set(url(../images/batteries24.png) 1x, url(../images/batteries48.png) 2x); }
863 +.deviceBatterySmall3 { background: url(../images/batteries24.png) -28px 0px; background-image: -webkit-image-set(url(../images/batteries24.png) 1x, url(../images/batteries48.png) 2x); }
864 +.deviceBatterySmall4 { background: url(../images/batteries24.png) -42px 0px; background-image: -webkit-image-set(url(../images/batteries24.png) 1x, url(../images/batteries48.png) 2x); }
865 +.deviceBatterySmall5 { background: url(../images/batteries24.png) -56px 0px; background-image: -webkit-image-set(url(../images/batteries24.png) 1x, url(../images/batteries48.png) 2x); }
866 +.deviceBatterySmall6 { background: url(../images/batteries24.png) -70px 0px; background-image: -webkit-image-set(url(../images/batteries24.png) 1x, url(../images/batteries48.png) 2x); }
867 +.deviceBatterySmall7 { background: url(../images/batteries24.png) -84px 0px; background-image: -webkit-image-set(url(../images/batteries24.png) 1x, url(../images/batteries48.png) 2x); }
868 +.deviceBatterySmall8 { background: url(../images/batteries24.png) -98px 0px; background-image: -webkit-image-set(url(../images/batteries24.png) 1x, url(../images/batteries48.png) 2x); }
869 +.deviceBatterySmall9 { background: url(../images/batteries24.png) -112px 0px; background-image: -webkit-image-set(url(../images/batteries24.png) 1x, url(../images/batteries48.png) 2x); }
870 +.deviceBatterySmall10 { background: url(../images/batteries24.png) -126px 0px; background-image: -webkit-image-set(url(../images/batteries24.png) 1x, url(../images/batteries48.png) 2x); }
871 +.deviceBatterySmall11 { background: url(../images/batteries24.png) -140px 0px; background-image: -webkit-image-set(url(../images/batteries24.png) 1x, url(../images/batteries48.png) 2x); }
872
873 .deviceNotifyLargeDot {
874 position:absolute;
@@ -1303,6 +1303,7 @@ a {
1303
1304 .i1 {
1305 background: url(../images/icons50.png) 0px 0px;
1306 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
1307 height: 50px;
1308 width: 50px;
1309 cursor: pointer;
@@ -1311,6 +1312,7 @@ a {
1312
1313 .i2 {
1314 background: url(../images/icons50.png) -50px 0px;
1315 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
1316 height: 50px;
1317 width: 50px;
1318 cursor: pointer;
@@ -1319,6 +1321,7 @@ a {
1321
1322 .i3 {
1323 background: url(../images/icons50.png) -100px 0px;
1324 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
1325 height: 50px;
1326 width: 50px;
1327 cursor: pointer;
@@ -1327,6 +1330,7 @@ a {
1330
1331 .i4 {
1332 background: url(../images/icons50.png) -150px 0px;
1333 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
1334 height: 50px;
1335 width: 50px;
1336 cursor: pointer;
@@ -1335,6 +1339,7 @@ a {
1339
1340 .i5 {
1341 background: url(../images/icons50.png) -200px 0px;
1342 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
1343 height: 50px;
1344 width: 50px;
1345 cursor: pointer;
@@ -1343,6 +1348,7 @@ a {
1348
1349 .i6 {
1350 background: url(../images/icons50.png) -250px 0px;
1351 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
1352 height: 50px;
1353 width: 50px;
1354 cursor: pointer;
@@ -1351,6 +1357,7 @@ a {
1357
1358 .i7 {
1359 background: url(../images/icons50.png) -300px 0px;
1360 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
1361 height: 50px;
1362 width: 50px;
1363 cursor: pointer;
@@ -1359,6 +1366,7 @@ a {
1366
1367 .i8 {
1368 background: url(../images/icons50.png) -350px 0px;
1369 + background-image: -webkit-image-set(url(../images/icons50.png) 1x, url(../images/webp/icons100.webp) 2x);
1370 height: 50px;
1371 width: 50px;
1372 cursor: pointer;
@@ -1367,6 +1375,7 @@ a {
1375
1376 .j1 {
1377 background: url(../images/icons16.png) 0px 0px;
1378 + background-image: -webkit-image-set(url(../images/webp/icons16.webp) 1x, url(../images/webp/icons32.webp) 2x);
1379 height: 16px;
1380 width: 16px;
1381 cursor: pointer;
@@ -1375,6 +1384,7 @@ a {
1384
1385 .j2 {
1386 background: url(../images/icons16.png) -16px 0px;
1387 + background-image: -webkit-image-set(url(../images/webp/icons16.webp) 1x, url(../images/webp/icons32.webp) 2x);
1388 height: 16px;
1389 width: 16px;
1390 cursor: pointer;
@@ -1383,6 +1393,7 @@ a {
1393
1394 .j3 {
1395 background: url(../images/icons16.png) -32px 0px;
1396 + background-image: -webkit-image-set(url(../images/webp/icons16.webp) 1x, url(../images/webp/icons32.webp) 2x);
1397 height: 16px;
1398 width: 16px;
1399 cursor: pointer;
@@ -1391,6 +1402,7 @@ a {
1402
1403 .j4 {
1404 background: url(../images/icons16.png) -48px 0px;
1405 + background-image: -webkit-image-set(url(../images/webp/icons16.webp) 1x, url(../images/webp/icons32.webp) 2x);
1406 height: 16px;
1407 width: 16px;
1408 cursor: pointer;
@@ -1399,6 +1411,7 @@ a {
1411
1412 .j5 {
1413 background: url(../images/icons16.png) -64px 0px;
1414 + background-image: -webkit-image-set(url(../images/webp/icons16.webp) 1x, url(../images/webp/icons32.webp) 2x);
1415 height: 16px;
1416 width: 16px;
1417 cursor: pointer;
@@ -1407,6 +1420,7 @@ a {
1420
1421 .j6 {
1422 background: url(../images/icons16.png) -80px 0px;
1423 + background-image: -webkit-image-set(url(../images/webp/icons16.webp) 1x, url(../images/webp/icons32.webp) 2x);
1424 height: 16px;
1425 width: 16px;
1426 cursor: pointer;
@@ -1415,6 +1429,7 @@ a {
1429
1430 .j7 {
1431 background: url(../images/icons16.png) -96px 0px;
1432 + background-image: -webkit-image-set(url(../images/webp/icons16.webp) 1x, url(../images/webp/icons32.webp) 2x);
1433 height: 16px;
1434 width: 16px;
1435 cursor: pointer;
@@ -1423,6 +1438,7 @@ a {
1438
1439 .j8 {
1440 background: url(../images/icons16.png) -112px 0px;
1441 + background-image: -webkit-image-set(url(../images/webp/icons16.webp) 1x, url(../images/webp/icons32.webp) 2x);
1442 height: 16px;
1443 width: 16px;
1444 cursor: pointer;
@@ -1469,6 +1485,7 @@ a {
1485
1486 .lb1 {
1487 background: url(../images/leftbar-64.png) -1px -2px;
1488 + background-image: -webkit-image-set(url(../images/webp/leftbar-64.webp) 1x, url(../images/webp/leftbar-128.webp) 2x);
1489 height: 62px;
1490 width: 62px;
1491 cursor: pointer;
@@ -1480,6 +1497,7 @@ a {
1497
1498 .lb2 {
1499 background: url(../images/leftbar-64.png) -66px -2px;
1500 + background-image: -webkit-image-set(url(../images/webp/leftbar-64.webp) 1x, url(../images/webp/leftbar-128.webp) 2x);
1501 height: 62px;
1502 width: 62px;
1503 cursor: pointer;
@@ -1491,6 +1509,7 @@ a {
1509
1510 .lb3 {
1511 background: url(../images/leftbar-64.png) -130px -2px;
1512 + background-image: -webkit-image-set(url(../images/webp/leftbar-64.webp) 1x, url(../images/webp/leftbar-128.webp) 2x);
1513 height: 62px;
1514 width: 62px;
1515 cursor: pointer;
@@ -1502,6 +1521,7 @@ a {
1521
1522 .lb4 {
1523 background: url(../images/leftbar-64.png) -194px -2px;
1524 + background-image: -webkit-image-set(url(../images/webp/leftbar-64.webp) 1x, url(../images/webp/leftbar-128.webp) 2x);
1525 height: 62px;
1526 width: 62px;
1527 cursor: pointer;
@@ -1513,6 +1533,7 @@ a {
1533
1534 .lb5 {
1535 background: url(../images/leftbar-64.png) -257px -2px;
1536 + background-image: -webkit-image-set(url(../images/webp/leftbar-64.webp) 1x, url(../images/webp/leftbar-128.webp) 2x);
1537 height: 62px;
1538 width: 62px;
1539 cursor: pointer;
@@ -1524,6 +1545,7 @@ a {
1545
1546 .lb6 {
1547 background: url(../images/leftbar-64.png) -318px -2px;
1548 + background-image: -webkit-image-set(url(../images/webp/leftbar-64.webp) 1x, url(../images/webp/leftbar-128.webp) 2x);
1549 height: 62px;
1550 width: 62px;
1551 cursor: pointer;
@@ -1583,6 +1605,7 @@ a {
1605
1606 .si1 {
1607 background: url(../images/icons16.png) 0px 0px;
1608 + background-image: -webkit-image-set(url(../images/icons16.png) 1x, url(../images/icons32.png) 2x);
1609 height: 16px;
1610 width: 16px;
1611 border: none;
@@ -1591,6 +1614,7 @@ a {
1614
1615 .si2 {
1616 background: url(../images/icons16.png) -16px 0px;
1617 + background-image: -webkit-image-set(url(../images/icons16.png) 1x, url(../images/icons32.png) 2x);
1618 height: 16px;
1619 width: 16px;
1620 border: none;
@@ -1599,6 +1623,7 @@ a {
1623
1624 .si3 {
1625 background: url(../images/icons16.png) -32px 0px;
1626 + background-image: -webkit-image-set(url(../images/icons16.png) 1x, url(../images/icons32.png) 2x);
1627 height: 16px;
1628 width: 16px;
1629 border: none;
@@ -1607,6 +1632,7 @@ a {
1632
1633 .si4 {
1634 background: url(../images/icons16.png) -48px 0px;
1635 + background-image: -webkit-image-set(url(../images/icons16.png) 1x, url(../images/icons32.png) 2x);
1636 height: 16px;
1637 width: 16px;
1638 border: none;
@@ -1615,6 +1641,7 @@ a {
1641
1642 .si5 {
1643 background: url(../images/icons16.png) -64px 0px;
1644 + background-image: -webkit-image-set(url(../images/icons16.png) 1x, url(../images/icons32.png) 2x);
1645 height: 16px;
1646 width: 16px;
1647 border: none;
@@ -1623,6 +1650,7 @@ a {
1650
1651 .si6 {
1652 background: url(../images/icons16.png) -80px 0px;
1653 + background-image: -webkit-image-set(url(../images/icons16.png) 1x, url(../images/icons32.png) 2x);
1654 height: 16px;
1655 width: 16px;
1656 border: none;
@@ -1631,6 +1659,7 @@ a {
1659
1660 .si7 {
1661 background: url(../images/icons16.png) -96px 0px;
1662 + background-image: -webkit-image-set(url(../images/icons16.png) 1x, url(../images/icons32.png) 2x);
1663 height: 16px;
1664 width: 16px;
1665 border: none;
@@ -1639,6 +1668,7 @@ a {
1668
1669 .si8 {
1670 background: url(../images/icons16.png) -112px 0px;
1671 + background-image: -webkit-image-set(url(../images/icons16.png) 1x, url(../images/icons32.png) 2x);
1672 height: 16px;
1673 width: 16px;
1674 border: none;
@@ -1647,6 +1677,7 @@ a {
1677
1678 .mi {
1679 background: url(../images/meshicon50.png) 0px 0px;
1680 + background-image: -webkit-image-set(url(../images/meshicon50.png) 1x, url(../images/meshicon100.png) 2x);
1681 height: 50px;
1682 width: 50px;
1683 cursor: pointer;
translate/translate.json
+40 -40
@@ -2392,7 +2392,7 @@
2392 "zh-chs": "AMT",
2393 "zh-cht": "AMT",
2394 "xloc": [
2395 - "default.handlebars->29->219",
2395 + "default.handlebars->29->244",
2396 "default.handlebars->29->430"
2397 ]
2398 },
@@ -3214,7 +3214,7 @@
3214 "default.handlebars->29->1482",
3215 "default.handlebars->29->1886",
3216 "default.handlebars->29->2004",
3217 - "default.handlebars->29->239"
3217 + "default.handlebars->29->224"
3218 ]
3219 },
3220 {
@@ -3855,7 +3855,7 @@
3855 "zh-chs": "地址",
3856 "zh-cht": "地址",
3857 "xloc": [
3858 - "default.handlebars->29->235"
3858 + "default.handlebars->29->220"
3859 ]
3860 },
3861 {
@@ -4064,7 +4064,7 @@
4064 "default-mobile.handlebars->9->250",
4065 "default.handlebars->29->1545",
4066 "default.handlebars->29->1553",
4067 - "default.handlebars->29->215",
4067 + "default.handlebars->29->240",
4068 "default.handlebars->29->426",
4069 "default.handlebars->container->column_l->p15->consoleTable->1->6->1->1->1->0->p15outputselecttd->p15outputselect->1"
4070 ]
@@ -6314,7 +6314,7 @@
6314 "zh-cht": "CIRA",
6315 "xloc": [
6316 "default-mobile.handlebars->9->204",
6317 - "default.handlebars->29->217",
6317 + "default.handlebars->29->242",
6318 "default.handlebars->29->428"
6319 ]
6320 },
@@ -7530,7 +7530,7 @@
7530 "nl": "Wis zoekfilter",
7531 "xloc": [
7532 "default-mobile.handlebars->9->154",
7533 - "default.handlebars->29->229"
7533 + "default.handlebars->29->214"
7534 ]
7535 },
7536 {
@@ -8919,8 +8919,8 @@
8919 "default-mobile.handlebars->9->2",
8920 "default-mobile.handlebars->9->337",
8921 "default-mobile.handlebars->9->37",
8922 - "default.handlebars->29->245",
8923 - "default.handlebars->29->248",
8922 + "default.handlebars->29->230",
8923 + "default.handlebars->29->233",
8924 "default.handlebars->29->277",
8925 "default.handlebars->29->9",
8926 "default.handlebars->29->945",
@@ -9028,7 +9028,7 @@
9028 "xloc": [
9029 "default-mobile.handlebars->9->255",
9030 "default.handlebars->29->1556",
9031 - "default.handlebars->29->236",
9031 + "default.handlebars->29->221",
9032 "default.handlebars->29->616",
9033 "default.handlebars->container->column_l->p21->3->1->meshConnChartDiv->1"
9034 ]
@@ -9666,7 +9666,7 @@
9666 "zh-chs": "创建一个新的设备组。",
9667 "zh-cht": "創建一個新的裝置群。",
9668 "xloc": [
9669 - "default.handlebars->29->238"
9669 + "default.handlebars->29->223"
9670 ]
9671 },
9672 {
@@ -11614,7 +11614,7 @@
11614 "xloc": [
11615 "default-mobile.handlebars->9->160",
11616 "default-mobile.handlebars->9->216",
11617 - "default.handlebars->29->213",
11617 + "default.handlebars->29->238",
11618 "default.handlebars->29->545"
11619 ]
11620 },
@@ -11862,7 +11862,7 @@
11862 "xloc": [
11863 "default-mobile.handlebars->9->159",
11864 "default-mobile.handlebars->9->215",
11865 - "default.handlebars->29->212",
11865 + "default.handlebars->29->237",
11866 "default.handlebars->29->544"
11867 ]
11868 },
@@ -12134,9 +12134,9 @@
12134 "default-mobile.handlebars->9->1",
12135 "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea1->1->3->deskstatus",
12136 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->0->1->3->p13Status",
12137 - "default.handlebars->29->224",
12138 - "default.handlebars->29->244",
12139 - "default.handlebars->29->247",
12137 + "default.handlebars->29->229",
12138 + "default.handlebars->29->232",
12139 + "default.handlebars->29->249",
12140 "default.handlebars->29->276",
12141 "default.handlebars->29->8",
12142 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->deskstatus",
@@ -12543,7 +12543,7 @@
12543 "zh-chs": "下载MeshCentral Router,一个TCP端口映射工具。",
12544 "zh-cht": "下載MeshCentral Router,一個TCP端口映射工具。",
12545 "xloc": [
12546 - "default.handlebars->29->242"
12546 + "default.handlebars->29->227"
12547 ]
12548 },
12549 {
@@ -12583,7 +12583,7 @@
12583 "zh-chs": "下载MeshCmd,这是一个多功能的指令执行工具。",
12584 "zh-cht": "下載MeshCmd,這是一個多功能的指令執行工具。",
12585 "xloc": [
12586 - "default.handlebars->29->240"
12586 + "default.handlebars->29->225"
12587 ]
12588 },
12589 {
@@ -18029,8 +18029,8 @@
18029 "xloc": [
18030 "default-mobile.handlebars->9->148",
18031 "default.handlebars->29->209",
18032 - "default.handlebars->29->225",
18033 - "default.handlebars->29->226"
18032 + "default.handlebars->29->210",
18033 + "default.handlebars->29->211"
18034 ]
18035 },
18036 {
@@ -18410,7 +18410,7 @@
18410 "zh-chs": "英特尔®AMT CIRA已连接并可以使用。",
18411 "zh-cht": "Intel® AMT CIRA已連接並可以使用。",
18412 "xloc": [
18413 - "default.handlebars->29->216",
18413 + "default.handlebars->29->241",
18414 "default.handlebars->29->427",
18415 "default.handlebars->29->608"
18416 ]
@@ -18701,7 +18701,7 @@
18701 "zh-chs": "英特尔®AMT是可路由的。",
18702 "zh-cht": "Intel® AMT是可路由的。",
18703 "xloc": [
18704 - "default.handlebars->29->218",
18704 + "default.handlebars->29->243",
18705 "default.handlebars->29->429"
18706 ]
18707 },
@@ -22004,7 +22004,7 @@
22004 "default-mobile.handlebars->9->254",
22005 "default.handlebars->29->1028",
22006 "default.handlebars->29->1029",
22007 - "default.handlebars->29->223",
22007 + "default.handlebars->29->248",
22008 "default.handlebars->29->434",
22009 "default.handlebars->29->615",
22010 "default.handlebars->container->column_l->p15->consoleTable->1->6->1->1->1->0->p15outputselecttd->p15outputselect->3"
@@ -22109,7 +22109,7 @@
22109 "zh-chs": "与设备的MQTT连接已激活。",
22110 "zh-cht": "與裝置的MQTT連接已啟動。",
22111 "xloc": [
22112 - "default.handlebars->29->222",
22112 + "default.handlebars->29->247",
22113 "default.handlebars->29->433",
22114 "default.handlebars->29->614"
22115 ]
@@ -22902,7 +22902,7 @@
22902 "zh-chs": "已连接网状代理并准备使用。",
22903 "zh-cht": "已連接Mesh Agent並準備使用。",
22904 "xloc": [
22905 - "default.handlebars->29->214",
22905 + "default.handlebars->29->239",
22906 "default.handlebars->29->425",
22907 "default.handlebars->29->606"
22908 ]
@@ -22924,7 +22924,7 @@
22924 "zh-chs": "网格代理可以经过其他代理作为中继访问得到。",
22925 "zh-cht": "Mesh Agent可以經過其他代理作為中繼訪問得到。",
22926 "xloc": [
22927 - "default.handlebars->29->220",
22927 + "default.handlebars->29->245",
22928 "default.handlebars->29->431",
22929 "default.handlebars->29->612"
22930 ]
@@ -23170,7 +23170,7 @@
23170 "zh-chs": "MeshCmd",
23171 "zh-cht": "MeshCmd",
23172 "xloc": [
23173 - "default.handlebars->29->241",
23173 + "default.handlebars->29->226",
23174 "default.handlebars->29->639",
23175 "default.handlebars->29->819"
23176 ]
@@ -24745,7 +24745,7 @@
24745 "zh-chs": "此网格中没有英特尔®AMT设备",
24746 "zh-cht": "此網格中沒有Intel® AMT裝置",
24747 "xloc": [
24748 - "default.handlebars->29->230"
24748 + "default.handlebars->29->215"
24749 ]
24750 },
24751 {
@@ -25031,7 +25031,7 @@
25031 "zh-chs": "没有一个设备被加入任何一组,请单击一个设备的“组”以添加到一个组中。",
25032 "zh-cht": "沒有一個裝置被加入任何一群,請單擊一個裝置的“群”以新增到一個群中。",
25033 "xloc": [
25034 - "default.handlebars->29->227"
25034 + "default.handlebars->29->212"
25035 ]
25036 },
25037 {
@@ -25130,7 +25130,7 @@
25130 "zh-cht": "該群中沒有裝置",
25131 "xloc": [
25132 "default-mobile.handlebars->9->151",
25133 - "default.handlebars->29->232"
25133 + "default.handlebars->29->217"
25134 ]
25135 },
25136 {
@@ -25152,7 +25152,7 @@
25152 "xloc": [
25153 "default-mobile.handlebars->9->149",
25154 "default-mobile.handlebars->9->153",
25155 - "default.handlebars->29->228"
25155 + "default.handlebars->29->213"
25156 ]
25157 },
25158 {
@@ -25172,7 +25172,7 @@
25172 "zh-chs": "找不到带有标签的设备。",
25173 "zh-cht": "找不到帶有標籤的裝置。",
25174 "xloc": [
25175 - "default.handlebars->29->237"
25175 + "default.handlebars->29->222"
25176 ]
25177 },
25178 {
@@ -25490,8 +25490,8 @@
25490 "default.handlebars->29->1945",
25491 "default.handlebars->29->1949",
25492 "default.handlebars->29->1961",
25493 - "default.handlebars->29->210",
25494 - "default.handlebars->29->211",
25493 + "default.handlebars->29->235",
25494 + "default.handlebars->29->236",
25495 "default.handlebars->29->546",
25496 "default.handlebars->29->557",
25497 "default.handlebars->29->558",
@@ -28875,7 +28875,7 @@
28875 "zh-cht": "中繼",
28876 "xloc": [
28877 "default-mobile.handlebars->9->206",
28878 - "default.handlebars->29->221",
28878 + "default.handlebars->29->246",
28879 "default.handlebars->29->432"
28880 ]
28881 },
@@ -30662,7 +30662,7 @@
30662 "zh-chs": "路由器",
30663 "zh-cht": "路由器",
30664 "xloc": [
30665 - "default.handlebars->29->243"
30665 + "default.handlebars->29->228"
30666 ]
30667 },
30668 {
@@ -32875,8 +32875,8 @@
32875 "xloc": [
32876 "default-mobile.handlebars->9->3",
32877 "default.handlebars->29->10",
32878 - "default.handlebars->29->246",
32879 - "default.handlebars->29->249",
32878 + "default.handlebars->29->231",
32879 + "default.handlebars->29->234",
32880 "default.handlebars->29->278",
32881 "desktop.handlebars->3->3",
32882 "terminal.handlebars->3->3",
@@ -38257,7 +38257,7 @@
38257 "default.handlebars->29->1745",
38258 "default.handlebars->29->1884",
38259 "default.handlebars->29->2067",
38260 - "default.handlebars->29->234",
38260 + "default.handlebars->29->219",
38261 "default.handlebars->29->671"
38262 ]
38263 },
@@ -41188,8 +41188,8 @@
41188 "zh-chs": "加一",
41189 "zh-cht": "加一",
41190 "xloc": [
41191 - "default.handlebars->29->231",
41192 - "default.handlebars->29->233"
41191 + "default.handlebars->29->216",
41192 + "default.handlebars->29->218"
41193 ]
41194 },
41195 {
views/default-mobile.handlebars
+28 -22
@@ -52,6 +52,7 @@
52
53 .i1 {
54 background: url(../images/icons50.png) 0px 0px;
55 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
56 height: 50px;
57 width: 50px;
58 border: none;
@@ -59,6 +60,7 @@
60
61 .i2 {
62 background: url(../images/icons50.png) -50px 0px;
63 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
64 height: 50px;
65 width: 50px;
66 border: none;
@@ -66,6 +68,7 @@
68
69 .i3 {
70 background: url(../images/icons50.png) -100px 0px;
71 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
72 height: 50px;
73 width: 50px;
74 border: none;
@@ -73,6 +76,7 @@
76
77 .i4 {
78 background: url(../images/icons50.png) -150px 0px;
79 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
80 height: 50px;
81 width: 50px;
82 border: none;
@@ -80,6 +84,7 @@
84
85 .i5 {
86 background: url(../images/icons50.png) -200px 0px;
87 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
88 height: 50px;
89 width: 50px;
90 border: none;
@@ -87,6 +92,7 @@
92
93 .i6 {
94 background: url(../images/icons50.png) -250px 0px;
95 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
96 height: 50px;
97 width: 50px;
98 border: none;
@@ -94,6 +100,7 @@
100
101 .i7 {
102 background: url(../images/icons50.png) -300px 0px;
103 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
104 height: 50px;
105 width: 50px;
106 border: none;
@@ -101,6 +108,7 @@
108
109 .i8 {
110 background: url(../images/icons50.png) -350px 0px;
111 + background-image: -webkit-image-set(url(../images/webp/icons50.webp) 1x, url(../images/webp/icons100.webp) 2x);
112 height: 50px;
113 width: 50px;
114 border: none;
@@ -146,15 +154,15 @@
154 float: left;
155 }
156
149 - .NotifyIconSmall1 { width:24px; height:24px; background: url(../images/notify24.png) 0px 0px; }
150 - .NotifyIconSmall2 { width:24px; height:24px; background: url(../images/notify24.png) -24px 0px; }
151 - .NotifyIconSmall3 { width:24px; height:24px; background: url(../images/notify24.png) -48px 0px; }
152 - .NotifyIconSmall4 { width:24px; height:24px; background: url(../images/notify24.png) -72px 0px; }
153 - .NotifyIconSmall5 { width:24px; height:24px; background: url(../images/notify24.png) -96px 0px; }
154 - .NotifyIconSmall6 { width:24px; height:24px; background: url(../images/notify24.png) -120px 0px; }
155 - .NotifyIconSmall7 { width:24px; height:24px; background: url(../images/notify24.png) -144px 0px; }
156 - .NotifyIconSmall8 { width:24px; height:24px; background: url(../images/notify24.png) -168px 0px; }
157 - .NotifyIconSmall9 { width:24px; height:24px; background: url(../images/notify24.png) -192px 0px; }
157 + .NotifyIconSmall1 { width:24px; height:24px; background: url(../images/notify24.png) 0px 0px; background-image: -webkit-image-set(url(../images/webp/notify24.webp) 1x, url(../images/webp/notify48.webp) 2x); }
158 + .NotifyIconSmall2 { width:24px; height:24px; background: url(../images/notify24.png) -24px 0px; background-image: -webkit-image-set(url(../images/webp/notify24.webp) 1x, url(../images/webp/notify48.webp) 2x); }
159 + .NotifyIconSmall3 { width:24px; height:24px; background: url(../images/notify24.png) -48px 0px; background-image: -webkit-image-set(url(../images/webp/notify24.webp) 1x, url(../images/webp/notify48.webp) 2x); }
160 + .NotifyIconSmall4 { width:24px; height:24px; background: url(../images/notify24.png) -72px 0px; background-image: -webkit-image-set(url(../images/webp/notify24.webp) 1x, url(../images/webp/notify48.webp) 2x); }
161 + .NotifyIconSmall5 { width:24px; height:24px; background: url(../images/notify24.png) -96px 0px; background-image: -webkit-image-set(url(../images/webp/notify24.webp) 1x, url(../images/webp/notify48.webp) 2x); }
162 + .NotifyIconSmall6 { width:24px; height:24px; background: url(../images/notify24.png) -120px 0px; background-image: -webkit-image-set(url(../images/webp/notify24.webp) 1x, url(../images/webp/notify48.webp) 2x); }
163 + .NotifyIconSmall7 { width:24px; height:24px; background: url(../images/notify24.png) -144px 0px; background-image: -webkit-image-set(url(../images/webp/notify24.webp) 1x, url(../images/webp/notify48.webp) 2x); }
164 + .NotifyIconSmall8 { width:24px; height:24px; background: url(../images/notify24.png) -168px 0px; background-image: -webkit-image-set(url(../images/webp/notify24.webp) 1x, url(../images/webp/notify48.webp) 2x); }
165 + .NotifyIconSmall9 { width:24px; height:24px; background: url(../images/notify24.png) -192px 0px; background-image: -webkit-image-set(url(../images/webp/notify24.webp) 1x, url(../images/webp/notify48.webp) 2x); }
166
167 .gray {
168 /*filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale");*/ /* Firefox 10+, Firefox on Android */
@@ -442,7 +450,7 @@
450 <div id=xdevicesBar style="position:absolute;overflow-y:auto;height:34px;left:0;right:0;bottom:0px;background-color:#aaa">
451 <div style="margin:4px">
452 <span style="width:20px;display:inline-block;text-align:center;cursor:pointer;font-size:16px" onclick=clearSearchInput()><b>X</b></span>
445 - <input id=SearchInput type=text placeholder=Filter onchange=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) autocomplete=off style="padding:2px;margin:0;height:20px" />&nbsp;
453 + <input id=SearchInput autocomplete=off type=search placeholder=Filter onchange=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) style="padding:2px;margin:0;height:20px" />&nbsp;
454 <label class=noselect><input type=checkbox id=RealNameCheckBox onclick=onRealNameCheckBox() />OS Name</label>
455 <label class=noselect><input type=checkbox id=OnlineCheckBox onclick=onOnlineCheckBox(event) />Online</label>
456 </div>
@@ -2359,9 +2367,7 @@
2367 var onDevicesTouchActive = false;
2368 var onDevicesScrollnagleTimer = null;
2369 function onDevicesScroll() {
2362 - if (onDevicesScrollnagleTimer != null) { clearTimeout(onDevicesScrollnagleTimer); onDevicesScrollnagleTimer = null; }
2363 - if (onDevicesTouchActive) return;
2364 - onDevicesScrollnagleTimer = setTimeout(onDevicesScrollEx, 50);
2370 + if (onDevicesScrollnagleTimer == null) { onDevicesScrollnagleTimer = setTimeout(onDevicesScrollEx, 250); }
2371 }
2372
2373 function onDeviceTouch(x) {
@@ -4021,7 +4027,7 @@
4027 var m = hardware.windows.osinfo;
4028 if (m.OSArchitecture) { x += addDetailItem("Architecture", EscapeHtml(m.OSArchitecture), s); }
4029 }
4024 - if (x != '') { sections.push({ name: "Operating System", html: x, img: 'software32.png' }); }
4030 + if (x != '') { sections.push({ name: "Operating System", html: x, img: 'software' }); }
4031 }
4032
4033 // MeshAgent
@@ -4052,7 +4058,7 @@
4058 }
4059 }
4060 }
4055 - if (x != '') { sections.push({ name: "Mesh Agent", html: x, img: 'meshagent32.png' }); }
4061 + if (x != '') { sections.push({ name: "Mesh Agent", html: x, img: 'meshagent' }); }
4062 }
4063
4064 // Networking
@@ -4094,7 +4100,7 @@
4100 x += '</div>';
4101 }
4102 x += '</table>';
4097 - if (x != '') { sections.push({ name: "Networking", html: x, img: 'networking64.png' }); }
4103 + if (x != '') { sections.push({ name: "Networking", html: x, img: 'networking' }); }
4104 }
4105
4106 // Attribute: Intel AMT
@@ -4107,7 +4113,7 @@
4113 x += addDetailItem("Provisioning State", ((node.intelamt.state) ? (provisioningStates[node.intelamt.state]) : ('<i>' + "Unknown" + '</i>')) + provisioningMode, s);
4114 x += addDetailItem("Security", (node.intelamt.tls == 1) ? "Secured using TLS" : "TLS is not setup", s);
4115 x += addDetailItem("Admin Credentials", (node.intelamt.user == null || node.intelamt.user == '') ? "Not Known" : "Known", s);
4110 - if (x != '') { sections.push({ name: "Intel&reg; Active Management Technology (Intel&reg; AMT)", html: x, img: 'amt32.png' }); }
4116 + if (x != '') { sections.push({ name: "Intel&reg; Active Management Technology (Intel&reg; AMT)", html: x, img: 'amt' }); }
4117 }
4118
4119 if (hardware.identifiers) {
@@ -4115,7 +4121,7 @@
4121 // BIOS
4122 if (ident.bios_vendor) { x += addDetailItem("Vendor", EscapeHtml(ident.bios_vendor), s); }
4123 if (ident.bios_version) { x += addDetailItem("Version", EscapeHtml(ident.bios_version), s); }
4118 - if (x != '') { sections.push({ name: "BIOS", html: x, img: 'chip32.png' }); }
4124 + if (x != '') { sections.push({ name: "BIOS", html: x, img: 'chip' }); }
4125
4126 // Motherboard
4127 x = '';
@@ -4126,7 +4132,7 @@
4132 if (ident.product_uuid) { x += addDetailItem("Identifier", EscapeHtml(ident.product_uuid), s); }
4133 if (ident.cpu_name) { x += addDetailItem("CPU", EscapeHtml(ident.cpu_name).split('(TM)').join('&trade;').split('(R)').join('&reg;'), s); }
4134 if (ident.gpu_name) { for (var i in ident.gpu_name) { x += addDetailItem("GPU", EscapeHtml(ident.gpu_name[i]).split('(TM)').join('&trade;').split('(R)').join('&reg;'), s); } }
4129 - if (x != '') { sections.push({ name: "Motherboard", html: x, img: 'motherboard32.png' }); }
4135 + if (x != '') { sections.push({ name: "Motherboard", html: x, img: 'motherboard' }); }
4136 }
4137
4138 if (hardware.windows) {
@@ -4147,7 +4153,7 @@
4153 }
4154 x += '</table>';
4155
4150 - if (x != '') { sections.push({ name: "Memory", html: x, img: 'ram32.png' }); }
4156 + if (x != '') { sections.push({ name: "Memory", html: x, img: 'ram' }); }
4157 }
4158 }
4159
@@ -4174,7 +4180,7 @@
4180 }
4181 x += '</table>';
4182
4177 - if (x != '') { sections.push({ name: "Storage", html: x, img: 'storage32.png' }); }
4183 + if (x != '') { sections.push({ name: "Storage", html: x, img: 'storage' }); }
4184 }
4185
4186 // Render the sections
@@ -4184,7 +4190,7 @@
4190 x += '<div class=DevSt style=margin-bottom:3px;margin-left:4px><b>' + sections[i].name + '</b></div><div style=margin-bottom:10px;margin-left:4px>' + sections[i].html + '</div>';
4191 } else {
4192 x += '<table style=width:100%><tr>';
4187 - x += '<td style=width:32px;vertical-align:top><img src=images/details/' + sections[i].img + ' border=0 width=32 /></td>'; // height=12
4193 + x += '<td style=width:32px;vertical-align:top><img src=images/details/' + sections[i].img + '32.png srcset="images/details/' + sections[i].img + '64.png 2x" border=0 width=32 /></td>'; // height=12
4194 x += '<td><div class=DevSt style=margin-bottom:3px;margin-left:4px><b>' + sections[i].name + '</b></div><div style=margin-bottom:10px;margin-left:4px>' + sections[i].html + '</div></td>';
4195 x += '</tr></table>';
4196 }
views/default.handlebars
+73 -134
@@ -246,7 +246,7 @@
246 <td id=devListToolbar class=style14 style="display:none">
247 &nbsp;&nbsp;<input type="button" id="SelectAllButton" onclick="selectallButtonFunction();" value="Select All" />&nbsp;
248 <input type=button id=GroupActionButton disabled="disabled" value="Group Action" onclick=groupActionFunction() />&nbsp;
249 - <input id=SearchInput type=text placeholder=Filter onchange=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) autocomplete=off onfocus=onSearchFocus(1) onblur=onSearchFocus(0) />&nbsp;
249 + <input id=SearchInput type=search autocomplete=off placeholder=Filter onchange=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) onfocus=onSearchFocus(1) onblur=onSearchFocus(0) />&nbsp;
250 <select id=DevFilterSelect onchange=onOnlineCheckBox(event) title="Device Filter">
251 <option value=0>All</option>
252 <option value=1>Online</option>
@@ -267,10 +267,10 @@
267 <input type="button" onclick="disconnectAllKvmFunction()" value="Disconnect All" />&nbsp;
268 <label><input type="checkbox" id="autoConnectDesktopCheckbox" onclick="autoConnectDesktops(event)" title="Automatic connect" />Auto&nbsp;</label>
269 <input type="button" onclick="showMultiDesktopSettings()" value="Settings" />&nbsp;
270 - <input id=KvmSearchInput type=text placeholder=Filter onchange=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) autocomplete=off onfocus=onSearchFocus(1) onblur=onSearchFocus(0) />&nbsp;
270 + <input id=KvmSearchInput type=search placeholder=Filter onchange=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) autocomplete=off onfocus=onSearchFocus(1) onblur=onSearchFocus(0) />&nbsp;
271 </td>
272 <td id=devMapToolbar class=style14 style="display:none">
273 - &nbsp;&nbsp;<input type=text id=mapSearchLocation placeholder="Search Location" onfocus=onMapSearchFocus(1) onblur=onMapSearchFocus(0) />
273 + &nbsp;&nbsp;<input type=search id=mapSearchLocation placeholder="Search Location" onfocus=onMapSearchFocus(1) onblur=onMapSearchFocus(0) />
274 <input type=button value=Search title="Search for location" onclick=getSearchLocation() />
275 <input type=button id=refreshmap title="Reset map view" value=Reset onclick=refreshMap(false,true) />
276 </td>
@@ -411,7 +411,7 @@
411 <input type=button id=UsersSelectAllButton onclick="p3usersSelectallButtonFunction()" value="Select All" />
412 <input type=button id=UsersGroupActionButton disabled="disabled" value="Group Action" onclick=p3usersGroupActionFunction() />
413 <input id=UserNewAccountButton type=button onclick=showCreateNewAccountDialog() value="New Account..." />
414 - <input id=UserSearchInput type=text style=width:120px;margin-left:6px placeholder=Filter onchange=onUserSearchInputChanged() onkeyup=onUserSearchInputChanged() autocomplete=off onfocus=onUserSearchFocus(1) onblur=onUserSearchFocus(0) />
414 + <input id=UserSearchInput type=search style=width:120px;margin-left:6px placeholder=Filter onchange=onUserSearchInputChanged() onkeyup=onUserSearchInputChanged() autocomplete=off onfocus=onUserSearchFocus(1) onblur=onUserSearchFocus(0) />
415 </div>
416 </td>
417 <td class="h2"></td>
@@ -1299,7 +1299,6 @@
1299 var logoutControls = JSON.parse(decodeURIComponent('{{{logoutControls}}}'));
1300 var authCookieRenewTimer = null;
1301 var multiDesktop = {};
1302 - var multiDesktopFilter = null;
1302 var serverPublicNamePort = '{{{serverDnsName}}}:{{{serverPublicPort}}}';
1303 var amtScanResults = null;
1304 var debugmode = 0;
@@ -1329,6 +1328,7 @@
1328 var xtermfit = null;
1329 var xtermResizeTimer = null;
1330 var miscState = {};
1331 + var checkedNodeids = {};
1332
1333 // Console Message Display Timers
1334 var p11DeskConsoleMsgTimer = null;
@@ -2853,6 +2853,27 @@
2853 if (node.rname) { node.rnamel = node.rname.toLowerCase(); } else { node.rnamel = node.namel; }
2854 if (message.event.node.icon) { node.icon = message.event.node.icon; }
2855
2856 + // Check if this device has changed device group
2857 + if (message.event.node.meshid != node.meshid) {
2858 + if ((meshes[message.event.node.meshid] == null) && ((userinfo.links == null) || (userinfo.links[node._id] == null))) {
2859 + // We don't see the new mesh, remove this device
2860 + // TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
2861 + if ((currentNode != null) && (currentNode._id == node._id)) {
2862 + if ((xxcurrentView >= 10) && (xxcurrentView < 20) && !IsNodeViewable(currentNode)) { currentNode = null; setDialogMode(0); go(1); }
2863 + }
2864 + var index = -1;
2865 + for (var i in nodes) { if (nodes[i]._id == message.event.nodeid) { index = i; break; } }
2866 + nodes.splice(index, 1);
2867 +
2868 + mainUpdate(4 | 16);
2869 + } else {
2870 + // We see the new mesh, move this device
2871 + node.meshid = message.event.node.meshid;
2872 + node.meshnamel = meshes[message.event.node.meshid]?meshes[message.event.node.meshid].name.toLowerCase():'*';
2873 + mainUpdate(1 | 2 | 4);
2874 + }
2875 + }
2876 +
2877 // Web page update
2878 updateDeviceViewDevice(node);
2879 mainUpdate(2 | 8 | 16);
@@ -2871,7 +2892,9 @@
2892 // We don't see the new mesh, remove this device
2893
2894 // TODO: Correctly disconnect from this node (Desktop/Terminal/Files...)
2874 - if ((xxcurrentView >= 10) && (xxcurrentView < 20) && !IsNodeViewable(currentNode)) { currentNode = null; setDialogMode(0); go(1); }
2895 + if ((currentNode != null) && (currentNode._id == node._id)) {
2896 + if ((xxcurrentView >= 10) && (xxcurrentView < 20) && !IsNodeViewable(currentNode)) { currentNode = null; setDialogMode(0); go(1); }
2897 + }
2898 nodes.splice(index, 1);
2899 mainUpdate(4 | 16);
2900 } else {
@@ -3441,12 +3464,6 @@
3464 else if (sort == 1) { nodes.sort(powerSort); }
3465 else if (sort == 2) { if (showRealNames == true) { nodes.sort(deviceHostSort); } else { nodes.sort(deviceSort); } }
3466
3444 - // Save the list of currently checked nodeid's
3445 - var checkedNodeids = [], elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
3446 - for (var i=0;i<elements.length;i++) { if (elements[i].checked) { checkedNodeids.push(elements[i].value); } }
3447 - if ((oldviewmode < 3) && (view == 3)) { multiDesktopFilter = checkedNodeids; }
3448 - else if ((oldviewmode == 3) && (view < 3)) { checkedNodeids = multiDesktopFilter; }
3449 -
3467 // Compute the width of the device view.
3468 var totalDeviceViewWidth = Q('column_l').clientWidth - 60;
3469 var deviceBoxWidth = Math.floor(totalDeviceViewWidth / 301);
@@ -3525,95 +3542,9 @@
3542 var collapsed = (sort != 3) & (sort != 4) & CollapsedGroups[collapseName];
3543 r += '<tr name=xxdevice2 colname=DevxCol' + collapseName + ' style=height:20px' + (collapsed?';display:none':'') + ' id=xv2' + node._id + '></tr>';
3544 } 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 - }
3547 -
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 -
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 -
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 -
3592 - if (levelnum > 0) {
3593 - devNotify += '<div class="deviceBatterySmall deviceBatterySmall' + levelnum + '" title="' + ((statestr != null)?(statestr + ', ' + levelstr):levelstr) + '"></div>';
3594 - }
3595 - }
3596 - }
3597 -
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 -
3607 - // Node
3608 - var icon = node.icon;
3609 - if ((!node.conn) || (node.conn == 0)) { icon += ' gray'; }
3610 -
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>';
3615 - r += '<span onclick=gotoDevice(\'' + node._id + '\',null,null,event)></span><div id=xkvmid_' + node._id.split('/')[2] + '><div id=skvmid_' + node._id.split('/')[2] + ' tabindex=0 style="position:absolute;color:white;left:5px;top:27px;text-shadow:0px 0px 5px #000;z-index:1000;cursor:default" onclick=toggleKvmDevice(\'' + node._id + '\') onkeypress="if (event.key==\'Enter\') toggleKvmDevice(\'' + node._id + '\')">' + "Disconnected" + '</div></div>';
3616 - r += '</div>';
3545 + // Draw the device (TODO: See if we can replace this with a standin in the future)
3546 + if ((Object.keys(checkedNodeids).length == 0) || checkedNodeids[node._id]) {
3547 + r += updateDeviceViewHtml(3, null, node);
3548 kvmDivs.push(node._id);
3549 }
3550 }
@@ -3741,10 +3672,6 @@
3672 QH('xdevices', r);
3673 deviceHeaderSet();
3674
3744 - // Re-check nodeid's
3745 - var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
3746 - if (checkedNodeids) { for (var i=0;i<elements.length;i++) { elements[i].checked = (checkedNodeids.indexOf(elements[i].value) >= 0); } }
3747 -
3675 for (var i in deviceHeaders) { QH(i, deviceHeaders[i]); }
3676 for (var i in deviceHeadersTitles) { Q(i).title = deviceHeadersTitles[i]; }
3677 p1updateInfo();
@@ -3835,7 +3762,7 @@
3762 }
3763
3764 function onDevicesScrollEx() {
3838 - onDevicesScrollnagleTimer = null;
3765 + if (onDevicesScrollnagleTimer != null) { clearTimeout(onDevicesScrollnagleTimer); onDevicesScrollnagleTimer = null; }
3766 var visibleTop = Q('xdevices').scrollTop - 200, visibleBottom = Q('xdevices').scrollTop + Q('xdevices').clientHeight + 200;
3767 var view = Q('viewselect').value, devdivs = document.getElementsByName('xxdevice' + view);
3768 for (var i = 0; i < devdivs.length; i++) {
@@ -3855,18 +3782,17 @@
3782 if (typeof node == 'string') { node = getNodeFromId(node); }
3783 if (node == null) return;
3784 var devdiv = Q('xv' + view + node._id);
3858 - if (devdiv.innerHTML != '') { updateDeviceViewHtml(view, devdiv, node); } // Only update if the device is visible
3785 + if ((devdiv != null) && (devdiv.innerHTML != '')) { updateDeviceViewHtml(view, devdiv, node); } // Only update if the device is visible
3786 }
3787
3788 function updateDeviceViewHtml(view, div, node) {
3862 - var deviceBoxWidth = div.clientWidth;
3863 -
3789 var title = EscapeHtml(node.name);
3790 if (title.length == 0) { title = '<i>' + "None" + '</i>'; }
3791 if ((node.rname != null) && (node.rname.length > 0)) { title += ' / ' + EscapeHtml(node.rname); }
3792 var name = EscapeHtml(node.name);
3793 if (showRealNames == true && node.rname != null) name = EscapeHtml(node.rname);
3794 if (name.length == 0) { name = '<i>' + "None" + '</i>'; }
3795 + if (((view == 1) && (div.parentNode.style['display'] == 'none')) || ((view == 2) && (div.style['display'] == 'none'))) { div.innerHTML = ''; return; } // If this section is collapsed, don't render
3796
3797 // Add device notification icons
3798 var devNotify = '', devNotifySub = '';
@@ -3944,8 +3870,8 @@
3870 if ((!node.conn) || (node.conn == 0)) { icon += ' gray'; }
3871
3872 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 {
3873 + 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" onchange=p1devcheck(event) value=devid_' + node._id + ' type=checkbox ' + (checkedNodeids[node._id]?' checked':'') + '></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 style=width:' + ((div.clientWidth) - 100) + 'px><div class=e1 title="' + title + '">' + name + '</div><div>' + NodeStateStr(node) + '</div></div><div class=g2></div></div></div>' + devNotify + '</div>';
3874 + } else if (view == 2) {
3875 var states = [];
3876 if (node.conn) {
3877 if ((node.conn & 1) != 0) { states.push('<span title="' + "Mesh agent is connected and ready for use." + '">' + "Agent" + '</span>'); }
@@ -3959,18 +3885,21 @@
3885 if (sort == 1) { collapseName = ('pwr:' + (node.pwr?node.pwr:0)); }
3886 else if ((sort == 3) || (sort == 4)) { collapseName = 'tag:**xx**xx*TaG*xx**xx**'; }
3887 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)">';
3888 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>';
3889 + r += '<div class=deviceBarCheckbox><input class="' + node.meshid + ' DeviceCheckbox" value=devid_' + node._id + ' type=checkbox onchange=p1devcheck(event) ' + (checkedNodeids[node._id]?' checked':'') + '></div>';
3890 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>';
3891 r += '<div class=g1 style=height:18px;float:left></div><div class=g2 style=height:18px;float:right></div>';
3892 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>';
3893 + r += '<td style=text-align:center>' + getUserShortStr(node) + '<td style=text-align:center>' + (node.ip != null ? node.ip : '') + '<td style=text-align:center>' + states.join('&nbsp;+&nbsp;');
3894 div.innerHTML = r;
3895 + } else if (view == 3) {
3896 + // Draw the device and canvas
3897 + var 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;
3898 + //r += '<input class="' + node.meshid + ' DeviceCheckbox" onclick=p1updateInfo() value=devid_' + node._id + ' type=checkbox style=float:left>';
3899 + r += '<div class="j' + icon + '" style=width:16px;float:left></div>&nbsp;' + name + '</div>';
3900 + r += '<span onclick=gotoDevice(\'' + node._id + '\',null,null,event)></span><div id=xkvmid_' + node._id.split('/')[2] + '><div id=skvmid_' + node._id.split('/')[2] + ' tabindex=0 style="position:absolute;color:white;left:5px;top:27px;text-shadow:0px 0px 5px #000;z-index:1000;cursor:default" onclick=toggleKvmDevice(\'' + node._id + '\') onkeypress="if (event.key==\'Enter\') toggleKvmDevice(\'' + node._id + '\')">' + "Disconnected" + '</div></div>';
3901 + r += '</div>';
3902 + return r;
3903 }
3904 }
3905
@@ -4062,6 +3991,7 @@
3991 }
3992 Q('DevxColImg' + id).src = x?'images/c2.png':'images/c1.png';
3993 putstore('_collapse', JSON.stringify(CollapsedGroups));
3994 + onDevicesScrollEx();
3995 }
3996
3997 function toggleKvmDevice(node) {
@@ -4091,7 +4021,7 @@
4021 var count = 0;
4022 for (var i in nodes) {
4023 var node = nodes[i], nodeid = nodes[i]._id;
4094 - if ((multiDesktop[nodeid] == null) && ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + nodeid) >= 0))) {
4024 + if ((multiDesktop[nodeid] == null) && ((Object.keys(checkedNodeids).length == 0) || checkedNodeids[nodeid])) {
4025 var rights = GetNodeRights(node);
4026 if ((rights & 8) || (rights & 256)) { // Requires remote control rights or desktop view only rights
4027 //var conn = 0;
@@ -4105,7 +4035,7 @@
4035
4036 // Perform connect all
4037 for (var i in nodes) {
4108 - if ((nodes[i].v == true) && (multiDesktop[nodes[i]._id] == null) && ((multiDesktopFilter.length == 0) || (multiDesktopFilter.indexOf('devid_' + nodes[i]._id) >= 0))) {
4038 + if ((nodes[i].v == true) && (multiDesktop[nodes[i]._id] == null) && ((Object.keys(checkedNodeids).length == 0) || checkedNodeids[nodes[i]._id])) {
4039 toggleKvmDevice(nodes[i]._id);
4040 }
4041 }
@@ -4579,16 +4509,23 @@
4509 }
4510
4511 function selectallButtonFunction() {
4582 - var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
4583 - for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) checkcount++; }
4584 - for (var i=0;i<elements.length;i++) { elements[i].checked = (checkcount == 0); }
4512 + var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = Object.keys(checkedNodeids).length;
4513 + for (var i = 0; i < elements.length; i++) { elements[i].checked = (checkcount == 0); }
4514 + checkedNodeids = {};
4515 + if (checkcount == 0) {
4516 + var devdivs = document.getElementsByName('xxdevice' + Q('viewselect').value);
4517 + for (var i = 0; i < devdivs.length; i++) { checkedNodeids[devdivs[i].id.substring(3)] = 1; }
4518 + }
4519 + p1updateInfo();
4520 + }
4521 +
4522 + function p1devcheck(e) {
4523 + if (e.srcElement.checked) { checkedNodeids[e.srcElement.value.substring(6)] = 1; } else { delete checkedNodeids[e.srcElement.value.substring(6)]; }
4524 p1updateInfo();
4525 }
4526
4527 function p1updateInfo() {
4589 - var elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
4590 - for (var i=0;i<elements.length;i++) { if (elements[i].checked === true) { checkcount++; } }
4591 - if (checkcount > 0) {
4528 + if (Object.keys(checkedNodeids).length > 0) {
4529 QE('GroupActionButton', true);
4530 Q('SelectAllButton').value = "Select None";
4531 QV('cxmdesktop', true);
@@ -4636,16 +4573,13 @@
4573 setDialogMode(2, "Group Action", 3, groupActionFunctionEx, x);
4574 }
4575
4639 - // Get the list of checked devices, removes any duplicates.
4640 - function getCheckedDevices() {
4641 - var nodeids = [], elements = document.getElementsByClassName('DeviceCheckbox'), checkcount = 0;
4642 - for (var i=0;i<elements.length;i++) { if (elements[i].checked) { if (elements[i].value) { var nid = elements[i].value.substring(6); if (nodeids.indexOf(nid) == -1) { nodeids.push(nid); } } } }
4643 - return nodeids;
4644 - }
4576 + // Get the list of checked devices
4577 + function getCheckedDevices() { return Object.keys(checkedNodeids); }
4578
4579 function uncheckAllDevices() {
4580 var elements = document.getElementsByClassName('DeviceCheckbox');
4581 for (var i=0;i<elements.length;i++) { elements[i].checked = false; }
4582 + checkedNodeids = {};
4583 }
4584
4585 function groupActionFunctionEx() {
@@ -4778,7 +4712,6 @@
4712 csv += '"' + n._id.split(',').join('') + '","' + n.name.split(',').join('') + '","' + (n.rname?(n.rname.split(',').join('')):'') + '","' + (n.host?(n.host.split(',').join('')):'') + '","' + n.icon + '","' + (n.ip?n.ip:'') + '","' + (n.osdesc?(n.osdesc.split(',').join('')):'') + '","' + n.state + '","' + meshes[n.meshid].name.split(',').join('') + '","' + (n.conn?n.conn:'') + '","' + (n.pwr?n.pwr:'') + '"\r\n';
4713 }
4714 saveAs(new Blob([csv], { type: 'application/octet-stream' }), "devicelist.csv");
4781 - uncheckAllDevices();
4715 return false;
4716 }
4717
@@ -4786,7 +4719,6 @@
4719 var chkNodeIds = getCheckedDevices(), r = [];
4720 for (var i in chkNodeIds) { r.push(getNodeFromId(chkNodeIds[i])); }
4721 saveAs(new Blob([JSON.stringify(r, null, 2)], { type: 'application/octet-stream' }), "devicelist.json");
4789 - uncheckAllDevices();
4722 return false;
4723 }
4724
@@ -5001,9 +4933,16 @@
4933 var meshid = contextelement.attributes.onclick.value.substring(10, contextelement.attributes.onclick.value.length - 2);
4934 var elements = document.getElementsByClassName('DeviceCheckbox');
4935 if ((action == 1) || (action == 2)) {
4936 + // Change the visible check boxes
4937 for (var i = 0; i < elements.length; i++) {
4938 if ((elements[i].attributes) && (elements[i].attributes['class']['value'].split(' ')[0] == meshid)) { elements[i].checked = (action == 1); }
4939 }
4940 + // Update the list of checked nodes
4941 + if (action == 1) {
4942 + for (var i in nodes) { if (nodes[i].meshid == meshid) { checkedNodeids[nodes[i]._id] = 1; } }
4943 + } else if (action == 2) {
4944 + for (var i in checkedNodeids) { if (getNodeFromId(i).meshid == meshid) { delete checkedNodeids[i]; } }
4945 + }
4946 }
4947 //if (action == 3) { window.location = "multidesktop.aspx?mesh=" + meshid + "&auto=1"; }
4948 p1updateInfo();