@cryptotaxi247 / netdata-1 / commits / a29b43352

Issue 4582 (Show alternate urls in my-netdata menu) (#4590)

* Wip #4582 * CSS fix * Work on new my-menu layout, wip * Render alternate urls * Toggle alternates * Aesthetics * Integrated in the menu * Fixes #4582 * Handle some exceptional cases * Visible expand icon #4582 * Minor * Support for 'mirrored hosts' * Better separator * Cleanup * Minor * Cleanup * Refactored netdataRegistryCallback to keep Codacy happy Even though I do not agree with the `===` warning. We need to disable this. * Fixed issue with hosts * Minor improvement for multiline * Clip alternate urls to avoid wrapping * Show section descriptions #4582 * More aesthetic improvements * Show demo-servers if list empty, aesthetic improvements * Cleanup * Fix for codacy warning * Improved UI, shows ulrs for all agents * Cleanup * Customize colors for white theme * Add cache-buster to url to js/css urls * Minor * Improvements to avoid hitting the scrollbar * Finetuning

George Moschovitis committed Nov 12, 2018 at 21:26 UTC a29b433526f56fe983d88dc4e86585bad65916c4
3 files changed +299 -136
web/gui/index.html
+4 -16
@@ -13,7 +13,7 @@
13 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
14 <meta name="author" content="costa@tsaousis.gr">
15
16 - <link rel="stylesheet" type="text/css" href="main.css">
16 + <link rel="stylesheet" type="text/css" href="main.css?v=2">
17
18 <!-- <link rel="shortcut icon" href="images/seo-performance-multi-size.ico"> -->
19
@@ -50,7 +50,7 @@
50 <meta name="twitter:description" content="Unparalleled insights, in real-time, of everything happening on your Linux systems and applications, with stunning, interactive web dashboards and powerful performance and health alarms." />
51 <meta name="twitter:image" content="https://cloud.githubusercontent.com/assets/2662304/14092712/93b039ea-f551-11e5-822c-beadbf2b2a2e.gif" />
52
53 - <script src="main.js"></script>
53 + <script src="main.js?v=2"></script>
54 </head>
55
56 <body data-spy="scroll" data-target="#sidebar" data-offset="100">
@@ -76,20 +76,8 @@
76 <ul class="nav navbar-nav">
77 <li class="dropdown" id="myNetdataDropdownParent" title="your other netdata servers" data-toggle="tooltip" data-placement="right">
78 <a href="#" class="dropdown-toggle" data-toggle="dropdown">my-netdata <strong class="caret"></strong></a>
79 - <ul class="dropdown-menu scrollable-menu inpagemenu multi-column columns-2" role="menu" id="myNetdataDropdownUL">
80 - <div class="row">
81 - <div class="col-sm-6" style="width: 85%; padding-right: 0;">
82 - <ul id="mynetdata_servers" class="multi-column-dropdown">
83 - <li><a href="#" onclick="return false;" style="color: #999;">loading...</a></li>
84 - </ul>
85 - </div>
86 - <div class="col-sm-3 hidden-xs" style="width: 15%; padding-left: 0;">
87 - <ul id="mynetdata_actions1" class="multi-column-dropdown">
88 - <li style="color: #999;">&nbsp;</li>
89 - </ul>
90 - </div>
91 - </div>
92 - </ul>
79 + <div id="my-netdata-dropdown-content" class="dropdown-menu scrollable-menu inpagemenu">
80 + </div>
81 </li>
82 </ul>
83 </nav>
web/gui/main.css
+81 -1
@@ -264,7 +264,7 @@ body.modal-open {
264 }
265
266 .multi-column-dropdown li a {
267 - display: block;
267 + display: inline-block;
268 clear: both;
269 line-height: 1.428571429;
270 white-space: normal;
@@ -531,3 +531,83 @@ body.modal-open {
531 opacity: .2;
532 transition: 0s
533 }
534 +
535 +/* --- */
536 +
537 +#my-netdata-dropdown-content a:hover {
538 + color: #fff;
539 +}
540 +
541 +#my-netdata-dropdown-content .info-item {
542 + height: 32px;
543 + line-height: 32px;
544 + padding-left: 14px;
545 +}
546 +
547 +#my-netdata-dropdown-content .agent-item {
548 + display: flex;
549 + align-items: center;
550 + min-height: 32px;
551 + font-weight: 300;
552 +}
553 +
554 +#my-netdata-dropdown-content .agent-item:hover {
555 + background-color: #262626;
556 +}
557 +
558 +#my-netdata-dropdown-content .agent-item a:hover {
559 + text-decoration: none;
560 +}
561 +
562 +#my-netdata-dropdown-content .agent-item > :first-child {
563 + width: 40px;
564 + text-align: center;
565 +}
566 +
567 +#my-netdata-dropdown-content .agent-item > :last-child {
568 + width: 40px;
569 + text-align: center;
570 +}
571 +
572 +#my-netdata-dropdown-content .agent-item :nth-child(2) {
573 + min-width: 420px;
574 + line-height: 14px;
575 +}
576 +
577 +.agent-item--separated {
578 + border-top: 1px solid #333;
579 +}
580 +
581 +.agent-item--alternate a {
582 + color: #999;
583 +}
584 +
585 +#my-netdata-dropdown-content .agent-alternate-urls.collapsed {
586 + display: none;
587 +}
588 +
589 +#my-netdata-dropdown-content hr {
590 + display: block;
591 + margin-top: 5px;
592 + margin-bottom: 0;
593 + border-top: 1px solid #333;
594 + height: 4px;
595 +}
596 +
597 +/* white theme overrides */
598 +
599 +#my-netdata-dropdown-content.theme-white hr {
600 + border-top: 1px solid #ddd;
601 +}
602 +
603 +#my-netdata-dropdown-content.theme-white .agent-item:hover {
604 + background-color: #e6e6e6;
605 +}
606 +
607 +#my-netdata-dropdown-content.theme-white a {
608 + color: #555;
609 +}
610 +
611 +#my-netdata-dropdown-content.theme-white a:hover {
612 + color: #000;
613 +}
web/gui/main.js
+214 -119
@@ -259,7 +259,7 @@ var urlOptions = {
259
260 $('.highlight-tooltip').tooltip({
261 html: true,
262 - delay: {show: 500, hide: 0},
262 + delay: { show: 500, hide: 0 },
263 container: 'body'
264 });
265 }
@@ -464,121 +464,216 @@ function saveObjectToClient(data, filename) {
464 // --------------------------------------------------------------------
465 // registry call back to render my-netdata menu
466
467 -var netdataRegistryCallback = function (machines_array) {
468 - var el = '';
469 - var a1 = '';
470 - var found = 0, hosted = 0;
471 - var len, i, url, hostname, icon;
467 +function toggleExpandIcon(svgEl) {
468 + if (svgEl.getAttribute('data-icon') === 'caret-down') {
469 + svgEl.setAttribute('data-icon', 'caret-up');
470 + } else {
471 + svgEl.setAttribute('data-icon', 'caret-down');
472 + }
473 +}
474
473 - if (options.hosts.length > 1) {
474 - // there are mirrored hosts here
475 +function toggleAgentItem(e, guid) {
476 + e.stopPropagation();
477 + e.preventDefault();
478
476 - el += '<li><a href="#" onClick="return false;" style="color: #666;" target="_blank">databases available on this host</a></li>';
477 - a1 += '<li><a href="#" onClick="return false;"><i class="fas fa-info-circle" style="color: #666;"></i></a></li>';
479 + toggleExpandIcon(e.currentTarget.children[0]);
480
479 - var base = document.location.origin.toString() + document.location.pathname.toString();
480 - if (base.endsWith("/host/" + options.hostname + "/")) {
481 - base = base.substring(0, base.length - ("/host/" + options.hostname + "/").toString().length);
482 - }
481 + const el = document.querySelector(`.agent-alternate-urls.agent-${guid}`);
482 + if (el) {
483 + el.classList.toggle('collapsed');
484 + }
485 +}
486
484 - if (base.endsWith("/")) {
485 - base = base.substring(0, base.length - 1);
486 - }
487 +// TODO: consider renaming to `truncateString`
488
488 - var master = options.hosts[0].hostname;
489 - var sorted = options.hosts.sort(function (a, b) {
490 - if (a.hostname === master) {
491 - return -1;
492 - }
493 - return naturalSortCompare(a.hostname, b.hostname);
494 - });
489 +/// Enforces a maximum string length while retaining the prefix and the postfix of
490 +/// the string.
491 +function clipString(str, maxLength) {
492 + if (str.length <= maxLength) {
493 + return str;
494 + }
495
496 - i = 0;
497 - len = sorted.length;
498 - while (len--) {
499 - hostname = sorted[i].hostname;
500 - if (hostname === master) {
501 - url = base + "/";
502 - icon = "home";
503 - }
504 - else {
505 - url = base + "/host/" + hostname + "/";
506 - icon = "window-restore";
507 - }
496 + const spanLength = Math.floor((maxLength - 3) / 2);
497 + return `${str.substring(0, spanLength)}...${str.substring(str.length - spanLength)}`;
498 +}
499 +
500 +// When you stream metrics from netdata to netdata, the recieving netdata now
501 +// has multiple host databases. It's own, and multiple mirrored. Mirrored databases
502 +// can be accessed with <http://localhost:19999/host/NAME/>
503 +function renderStreamedHosts(options) {
504 + let html = `<div class="info-item">Databases streamed to this agent</div>`;
505
509 - el += '<li id="registry_server_hosted_' + len.toString() + '"><a class="registry_link" href="' + url + '#" onClick="return gotoHostedModalHandler(\'' + url + '\');">' + hostname + '</a></li>';
510 - a1 += '<li id="registry_action_hosted_' + len.toString() + '"><a class="registry_link" href="' + url + '#" onClick="return gotoHostedModalHandler(\'' + url + '\');"><i class="fas fa-' + icon + '" style="color: #999;"></i></a></li>';
511 - hosted++;
512 - i++;
506 + var base = document.location.origin.toString() + document.location.pathname.toString();
507 + if (base.endsWith("/host/" + options.hostname + "/")) {
508 + base = base.substring(0, base.length - ("/host/" + options.hostname + "/").toString().length);
509 + }
510 +
511 + if (base.endsWith("/")) {
512 + base = base.substring(0, base.length - 1);
513 + }
514 +
515 + var master = options.hosts[0].hostname;
516 + var sorted = options.hosts.sort(function (a, b) {
517 + if (a.hostname === master) {
518 + return -1;
519 }
520 + return naturalSortCompare(a.hostname, b.hostname);
521 + });
522 +
523 + for (const s of sorted) {
524 + let url, icon;
525 + const hostname = s.hostname;
526
515 - el += '<li role="separator" class="divider"></li>';
516 - a1 += '<li role="separator" class="divider"></li>';
527 + if (hostname === master) {
528 + url = `base${'/'}`;
529 + icon = 'home';
530 + } else {
531 + url = `${base}/host/${hostname}/`;
532 + icon = 'window-restore';
533 + }
534 +
535 + html += (
536 + `<div class="agent-item">
537 + <a class="registry_link" href="${url}#" onClick="return gotoHostedModalHandler('${url}');">
538 + <i class="fas fa-${icon}" style="color: #999;"></i>
539 + </a>
540 + <a class="registry_link" href="${url}#" onClick="return gotoHostedModalHandler('${url}');">${hostname}</a>
541 + <div></div>
542 + </div>`
543 + )
544 }
545
519 - if (machines_array === null) {
520 - var ret = loadLocalStorage("registryCallback");
521 - if (typeof ret !== 'undefined' && ret !== null) {
522 - machines_array = JSON.parse(ret);
546 + return html;
547 +}
548 +
549 +function renderMachines(machinesArray) {
550 + let html = `<div class="info-item">My netdata agents</div>`;
551 +
552 + if (machinesArray === null) {
553 + let ret = loadLocalStorage("registryCallback");
554 + if (ret) {
555 + machinesArray = JSON.parse(ret);
556 console.log("failed to contact the registry - loaded registry data from browser local storage");
557 }
558 }
559
527 - if (machines_array) {
528 - saveLocalStorage("registryCallback", JSON.stringify(machines_array));
560 + let found = false;
561 +
562 + if (machinesArray) {
563 + saveLocalStorage("registryCallback", JSON.stringify(machinesArray));
564
530 - var machines = machines_array.sort(function (a, b) {
565 + var machines = machinesArray.sort(function (a, b) {
566 return naturalSortCompare(a.name, b.name);
567 });
568
534 - i = 0;
535 - len = machines.length;
536 - while (len--) {
537 - var u = machines[i++];
538 - found++;
539 - el += '<li id="registry_server_' + u.guid + '"><a class="registry_link" href="' + u.url + '#" onClick="return gotoServerModalHandler(\'' + u.guid + '\');">' + u.name + '</a></li>';
540 - a1 += '<li id="registry_action_' + u.guid + '"><a href="#" onclick="deleteRegistryModalHandler(\'' + u.guid + '\',\'' + u.name + '\',\'' + u.url + '\'); return false;"><i class="fas fa-trash" style="color: #999;"></i></a></li>';
569 + for (const machine of machines) {
570 + found = true;
571 +
572 + const alternateUrlItems = (
573 + `<div class="agent-alternate-urls agent-${machine.guid} collapsed">
574 + ${machine.alternate_urls.reduce(
575 + (str, url) => str + (
576 + `<div class="agent-item agent-item--alternate">
577 + <div></div>
578 + <a href="${url}" title="${url}">${clipString(url, 64)}</a>
579 + <a href="#" onclick="deleteRegistryModalHandler('${machine.guid}', '${machine.name}', '${url}'); return false;">
580 + <i class="fas fa-trash" style="color: #777;"></i>
581 + </a>
582 + </div>`
583 + ),
584 + ''
585 + )}
586 + </div>`
587 + )
588 +
589 + html += (
590 + `<div class="agent-item agent-${machine.guid}">
591 + <i class="fas fa-chart-bar" color: #fff"></i>
592 + <span>
593 + <a class="registry_link" href="${machine.url}#" onClick="return gotoServerModalHandler('${machine.guid}');">${machine.name}</a>
594 + </span>
595 + <a href="#" onClick="toggleAgentItem(event, '${machine.guid}');">
596 + <i class="fas fa-caret-down" style="color: #999"></i>
597 + </a>
598 + </div>
599 + ${alternateUrlItems}`
600 + )
601 }
602 }
603
604 if (!found) {
605 if (machines) {
546 - el += '<li><a href="https://github.com/netdata/netdata/tree/master/registry#netdata-registry" style="color: #666;" target="_blank">your netdata server list is empty...</a></li>';
606 + html += (
607 + `<div class="info-item">
608 + <a href="https://github.com/netdata/netdata/tree/master/registry#netdata-registry" target="_blank">Your netdata server list is empty</a>
609 + </div>`
610 + )
611 } else {
548 - el += '<li><a href="https://github.com/netdata/netdata/tree/master/registry#netdata-registry" style="color: #666;" target="_blank">failed to contact the registry...</a></li>';
549 - }
550 -
551 - a1 += '<li><a href="#" onClick="return false;">&nbsp;</a></li>';
552 -
553 - el += '<li role="separator" class="divider"></li>' +
554 - '<li><a href="//london.netdata.rocks/default.html">UK - London (DigitalOcean.com)</a></li>' +
555 - '<li><a href="//newyork.netdata.rocks/default.html">US - New York (DigitalOcean.com)</a></li>' +
556 - '<li><a href="//sanfrancisco.netdata.rocks/default.html">US - San Francisco (DigitalOcean.com)</a></li>' +
557 - '<li><a href="//atlanta.netdata.rocks/default.html">US - Atlanta (CDN77.com)</a></li>' +
558 - '<li><a href="//frankfurt.netdata.rocks/default.html">Germany - Frankfurt (DigitalOcean.com)</a></li>' +
559 - '<li><a href="//toronto.netdata.rocks/default.html">Canada - Toronto (DigitalOcean.com)</a></li>' +
560 - '<li><a href="//singapore.netdata.rocks/default.html">Japan - Singapore (DigitalOcean.com)</a></li>' +
561 - '<li><a href="//bangalore.netdata.rocks/default.html">India - Bangalore (DigitalOcean.com)</a></li>';
562 - a1 += '<li role="separator" class="divider"></li>' +
563 - '<li><a href="#">&nbsp;</a></li>' +
564 - '<li><a href="#">&nbsp;</a></li>' +
565 - '<li><a href="#">&nbsp;</a></li>' +
566 - '<li><a href="#">&nbsp;</a></li>' +
567 - '<li><a href="#">&nbsp;</a></li>' +
568 - '<li><a href="#">&nbsp;</a></li>' +
569 - '<li><a href="#">&nbsp;</a></li>' +
570 - '<li><a href="#">&nbsp;</a></li>';
612 + el += '<li></li>';
613 + html += (
614 + `<div class="info-item">
615 + <a href="https://github.com/netdata/netdata/tree/master/registry#netdata-registry" target="_blank">Failed to contact the registry</a>
616 + </div>`
617 + )
618 + }
619 +
620 + html += `<hr />`;
621 + html += `<div class="info-item">Demo netdata agents</div>`;
622 +
623 + const demoServers = [
624 + {url: "//london.netdata.rocks/default.html", title: "UK - London (DigitalOcean.com)"},
625 + {url: "//newyork.netdata.rocks/default.html", title: "US - New York (DigitalOcean.com)"},
626 + {url: "//sanfrancisco.netdata.rocks/default.html", title: "US - San Francisco (DigitalOcean.com)"},
627 + {url: "//atlanta.netdata.rocks/default.html", title: "US - Atlanta (CDN77.com)"},
628 + {url: "//frankfurt.netdata.rocks/default.html", title: "Germany - Frankfurt (DigitalOcean.com)"},
629 + {url: "//toronto.netdata.rocks/default.html", title: "Canada - Toronto (DigitalOcean.com)"},
630 + {url: "//singapore.netdata.rocks/default.html", title: "Japan - Singapore (DigitalOcean.com)"},
631 + {url: "//bangalore.netdata.rocks/default.html", title: "India - Bangalore (DigitalOcean.com)"},
632 +
633 + ]
634 +
635 + for (const server of demoServers) {
636 + html += (
637 + `<div class="agent-item">
638 + <i class="fas fa-chart-bar" color: #fff"></i>
639 + <a href="${server.url}">${server.title}</a>
640 + <div></div>
641 + </div>
642 + `
643 + );
644 + }
645 }
646
573 - el += '<li role="separator" class="divider"></li>';
574 - a1 += '<li role="separator" class="divider"></li>';
647 + return html;
648 +}
649 +
650 +// Populates the my-netdata menu.
651 +function netdataRegistryCallback(machinesArray) {
652 + let html = '';
653
576 - el += '<li><a href="https://github.com/netdata/netdata/tree/master/registry#netdata-registry" style="color: #999;" target="_blank">What is this?</a></li>';
577 - a1 += '<li><a href="#" style="color: #999;" onclick="switchRegistryModalHandler(); return false;"><i class="fas fa-cog" style="color: #999;"></i></a></li>';
654 + if (options.hosts.length > 1) {
655 + html += renderStreamedHosts(options) + `<hr />`;
656 + }
657
579 - document.getElementById('mynetdata_servers').innerHTML = el;
580 - document.getElementById('mynetdata_servers2').innerHTML = el;
581 - document.getElementById('mynetdata_actions1').innerHTML = a1;
658 + html += renderMachines(machinesArray);
659 +
660 + html += (
661 + `<hr />
662 + <div class="agent-item">
663 + <i class="fas fa-cog""></i>
664 + <a href="#" onclick="switchRegistryModalHandler(); return false;">Switch Identity</a>
665 + <div></div>
666 + </div>
667 + <div class="agent-item">
668 + <i class="fas fa-question-circle""></i>
669 + <a href="https://github.com/netdata/netdata/tree/master/registry#netdata-registry" target="_blank">What is this?</a>
670 + <div></div>
671 + </div>`
672 + )
673 +
674 + const el = document.getElementById('my-netdata-dropdown-content')
675 + el.classList.add(`theme-${netdataTheme}`);
676 + el.innerHTML = html;
677
678 gotoServerInit();
679 };
@@ -881,7 +976,7 @@ function scrollToId(hash) {
976 var offset = $('#' + hash).offset();
977 if (typeof offset !== 'undefined') {
978 //console.log('scrolling to ' + hash + ' at ' + offset.top.toString());
884 - $('html, body').animate({scrollTop: offset.top - 30}, 0);
979 + $('html, body').animate({ scrollTop: offset.top - 30 }, 0);
980 }
981 }
982
@@ -933,7 +1028,7 @@ var netdataDashboard = {
1028 }
1029
1030 if (typeof this.sparklines_registry[key] === 'undefined') {
936 - this.sparklines_registry[key] = {count: 1};
1031 + this.sparklines_registry[key] = { count: 1 };
1032 } else {
1033 this.sparklines_registry[key].count++;
1034 }
@@ -1533,7 +1628,7 @@ function renderPage(menus, data) {
1628
1629 sidebar += '<li class="" style="padding-top:15px;"><a href="https://github.com/netdata/netdata/wiki/Add-more-charts-to-netdata" target="_blank"><i class="fas fa-plus"></i> add more charts</a></li>';
1630 sidebar += '<li class=""><a href="https://github.com/netdata/netdata/wiki/Add-more-alarms-to-netdata" target="_blank"><i class="fas fa-plus"></i> add more alarms</a></li>';
1536 - sidebar += '<li class="" style="margin:20px;color:#666;"><small>netdata on <b>' + data.hostname.toString() + '</b>, collects every ' + ((data.update_every === 1) ? 'second' : data.update_every.toString() + ' seconds') + ' <b>' + data.dimensions_count.toLocaleString() + '</b> metrics, presented as <b>' + data.charts_count.toLocaleString() + '</b> charts and monitored by <b>' + data.alarms_count.toLocaleString() + '</b> alarms, using ' + Math.round(data.rrd_memory_bytes / 1024 / 1024).toLocaleString() + ' MB of memory for ' + NETDATA.seconds4human(data.update_every * data.history, {space: '&nbsp;'}) + ' of real-time history.<br/>&nbsp;<br/><b>netdata</b><br/>v' + data.version.toString() + '</small></li>';
1631 + sidebar += '<li class="" style="margin:20px;color:#666;"><small>netdata on <b>' + data.hostname.toString() + '</b>, collects every ' + ((data.update_every === 1) ? 'second' : data.update_every.toString() + ' seconds') + ' <b>' + data.dimensions_count.toLocaleString() + '</b> metrics, presented as <b>' + data.charts_count.toLocaleString() + '</b> charts and monitored by <b>' + data.alarms_count.toLocaleString() + '</b> alarms, using ' + Math.round(data.rrd_memory_bytes / 1024 / 1024).toLocaleString() + ' MB of memory for ' + NETDATA.seconds4human(data.update_every * data.history, { space: '&nbsp;' }) + ' of real-time history.<br/>&nbsp;<br/><b>netdata</b><br/>v' + data.version.toString() + '</small></li>';
1632 sidebar += '</ul>';
1633 div.innerHTML = html;
1634 document.getElementById('sidebar').innerHTML = sidebar;
@@ -1650,7 +1745,7 @@ function loadJs(url, callback) {
1745 url: url,
1746 cache: true,
1747 dataType: "script",
1653 - xhrFields: {withCredentials: true} // required for the cookie
1748 + xhrFields: { withCredentials: true } // required for the cookie
1749 })
1750 .fail(function () {
1751 alert('Cannot load required JS library: ' + url);
@@ -1757,8 +1852,8 @@ function alarmsUpdateModal() {
1852 if (data === null) {
1853 document.getElementById('alarms_active').innerHTML =
1854 document.getElementById('alarms_all').innerHTML =
1760 - document.getElementById('alarms_log').innerHTML =
1761 - 'failed to load alarm data!';
1855 + document.getElementById('alarms_log').innerHTML =
1856 + 'failed to load alarm data!';
1857 return;
1858 }
1859
@@ -1808,7 +1903,7 @@ function alarmsUpdateModal() {
1903
1904 return '<code>' + alarm.lookup_method + '</code> '
1905 + dimensions + ', of chart <code>' + alarm.chart + '</code>'
1811 - + ', starting <code>' + NETDATA.seconds4human(alarm.lookup_after + alarm.lookup_before, {space: '&nbsp;'}) + '</code> and up to <code>' + NETDATA.seconds4human(alarm.lookup_before, {space: '&nbsp;'}) + '</code>'
1906 + + ', starting <code>' + NETDATA.seconds4human(alarm.lookup_after + alarm.lookup_before, { space: '&nbsp;' }) + '</code> and up to <code>' + NETDATA.seconds4human(alarm.lookup_before, { space: '&nbsp;' }) + '</code>'
1907 + ((alarm.lookup_options) ? (', with options <code>' + alarm.lookup_options.replace(/ /g, ',&nbsp;') + '</code>') : '')
1908 + '.';
1909 }
@@ -1885,9 +1980,9 @@ function alarmsUpdateModal() {
1980 }
1981
1982 html += '<tr><td width="10%" style="text-align:right">check&nbsp;every</td><td>' + NETDATA.seconds4human(alarm.update_every, {
1888 - space: '&nbsp;',
1889 - negative_suffix: ''
1890 - }) + '</td></tr>'
1983 + space: '&nbsp;',
1984 + negative_suffix: ''
1985 + }) + '</td></tr>'
1986 + ((has_alarm === true) ? ('<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span>' + delay + '</td></tr>') : '')
1987 + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>'
1988 + '</table></td></tr>';
@@ -1932,7 +2027,7 @@ function alarmsUpdateModal() {
2027 // not found - this should never happen!
2028 if (typeof chart === 'undefined') {
2029 console.log('WARNING: alarm ' + x + ' is linked to chart ' + alarm.chart + ', which is not found in the list of chart got from the server.');
1935 - chart = {priority: 9999999};
2030 + chart = { priority: 9999999 };
2031 }
2032 else if (typeof chart.menu !== 'undefined' && typeof chart.submenu !== 'undefined')
2033 // the family based on the chart
@@ -2069,16 +2164,16 @@ function alarmsUpdateModal() {
2164
2165 switch (row.status) {
2166 case 'CRITICAL':
2072 - return {classes: 'danger'};
2167 + return { classes: 'danger' };
2168 break;
2169 case 'WARNING':
2075 - return {classes: 'warning'};
2170 + return { classes: 'warning' };
2171 break;
2172 case 'UNDEFINED':
2078 - return {classes: 'info'};
2173 + return { classes: 'info' };
2174 break;
2175 case 'CLEAR':
2081 - return {classes: 'success'};
2176 + return { classes: 'success' };
2177 break;
2178 }
2179 return {};
@@ -2266,7 +2361,7 @@ function alarmsUpdateModal() {
2361 formatter: function (value, row, index) {
2362 void (row);
2363 void (index);
2269 - return NETDATA.seconds4human(value, {negative_suffix: '', space: ' ', now: 'no time'});
2364 + return NETDATA.seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
2365 },
2366 align: 'center',
2367 valign: 'middle',
@@ -2280,7 +2375,7 @@ function alarmsUpdateModal() {
2375 formatter: function (value, row, index) {
2376 void (row);
2377 void (index);
2283 - return NETDATA.seconds4human(value, {negative_suffix: '', space: ' ', now: 'no time'});
2378 + return NETDATA.seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
2379 },
2380 align: 'center',
2381 valign: 'middle',
@@ -2412,7 +2507,7 @@ function alarmsUpdateModal() {
2507 void (row);
2508 void (index);
2509
2415 - return NETDATA.seconds4human(value, {negative_suffix: '', space: ' ', now: 'no time'});
2510 + return NETDATA.seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' });
2511 },
2512 align: 'center',
2513 valign: 'middle',
@@ -2632,7 +2727,7 @@ function getNetdataCommitId(force, callback) {
2727 url: 'version.txt',
2728 async: true,
2729 cache: false,
2635 - xhrFields: {withCredentials: true} // required for the cookie
2730 + xhrFields: { withCredentials: true } // required for the cookie
2731 })
2732 .done(function (data) {
2733 data = data.replace(/(\r\n|\n|\r| |\t)/gm, "");
@@ -2883,7 +2978,7 @@ var snapshotOptions = {
2978 bytes_per_point_disk: 1.9,
2979
2980 compress: function (s) {
2886 - return btoa(pako.deflate(s, {to: 'string'}));
2981 + return btoa(pako.deflate(s, { to: 'string' }));
2982 },
2983
2984 compressed_length: function (s) {
@@ -2891,7 +2986,7 @@ var snapshotOptions = {
2986 },
2987
2988 uncompress: function (s) {
2894 - return pako.inflate(atob(s), {to: 'string'});
2989 + return pako.inflate(atob(s), { to: 'string' });
2990 }
2991 },
2992
@@ -2900,7 +2995,7 @@ var snapshotOptions = {
2995 bytes_per_point_disk: 3.2,
2996
2997 compress: function (s) {
2903 - return pako.deflate(s, {to: 'string'});
2998 + return pako.deflate(s, { to: 'string' });
2999 },
3000
3001 compressed_length: function (s) {
@@ -2908,7 +3003,7 @@ var snapshotOptions = {
3003 },
3004
3005 uncompress: function (s) {
2911 - return pako.inflate(s, {to: 'string'});
3006 + return pako.inflate(s, { to: 'string' });
3007 }
3008 },
3009
@@ -3709,7 +3804,7 @@ function enableTooltipsAndPopovers() {
3804 animated: 'fade',
3805 trigger: 'hover',
3806 html: true,
3712 - delay: {show: 500, hide: 0},
3807 + delay: { show: 500, hide: 0 },
3808 container: 'body'
3809 });
3810 $('[data-toggle="popover"]').popover();
@@ -3788,7 +3883,7 @@ function runOnceOnDashboardWithjQuery() {
3883
3884 // scroll to the position we had open before the modal
3885 $('html, body')
3791 - .animate({scrollTop: scrollPos}, 0);
3886 + .animate({ scrollTop: scrollPos }, 0);
3887
3888 // unpause netdata, if we paused it
3889 if (netdata_paused_on_modal === true) {
@@ -3888,7 +3983,7 @@ function runOnceOnDashboardWithjQuery() {
3983 // ------------------------------------------------------------------------
3984 // my-netdata menu
3985
3891 - Ps.initialize(document.getElementById('myNetdataDropdownUL'), {
3986 + Ps.initialize(document.getElementById('my-netdata-dropdown-content'), {
3987 wheelSpeed: 1,
3988 wheelPropagation: false,
3989 swipePropagation: false,
@@ -3913,7 +4008,7 @@ function runOnceOnDashboardWithjQuery() {
4008 });
4009 })
4010 .on('shown.bs.dropdown', function () {
3916 - Ps.update(document.getElementById('myNetdataDropdownUL'));
4011 + Ps.update(document.getElementById('my-netdata-dropdown-content'));
4012 })
4013 .on('hidden.bs.dropdown', function () {
4014 NETDATA.unpause();
@@ -3945,8 +4040,8 @@ function runOnceOnDashboardWithjQuery() {
4040 .on('hidden.bs.modal', function () {
4041 document.getElementById('alarms_active').innerHTML =
4042 document.getElementById('alarms_all').innerHTML =
3948 - document.getElementById('alarms_log').innerHTML =
3949 - 'loading...';
4043 + document.getElementById('alarms_log').innerHTML =
4044 + 'loading...';
4045 });
4046
4047 // ------------------------------------------------------------------------
@@ -3996,7 +4091,7 @@ function runOnceOnDashboardWithjQuery() {
4091 if ($this.hasClass('less')) {
4092 $this.removeClass('less');
4093 $this.html(config.moreText);
3999 - $this.parent().prev().animate({'height': '0' + '%'}, 0, function () {
4094 + $this.parent().prev().animate({ 'height': '0' + '%' }, 0, function () {
4095 $this.parent().prev().prev().show();
4096 }).hide(0, function () {
4097 config.onLess();
@@ -4005,7 +4100,7 @@ function runOnceOnDashboardWithjQuery() {
4100 } else {
4101 $this.addClass('less');
4102 $this.html(config.lessText);
4008 - $this.parent().prev().animate({'height': '100' + '%'}, 0, function () {
4103 + $this.parent().prev().animate({ 'height': '100' + '%' }, 0, function () {
4104 $this.parent().prev().prev().hide();
4105 }).show(0, function () {
4106 config.onMore();
@@ -4169,7 +4264,7 @@ function finalizePage() {
4264
4265 NETDATA.onresizeCallback = function () {
4266 Ps.update(document.getElementById('sidebar'));
4172 - Ps.update(document.getElementById('myNetdataDropdownUL'));
4267 + Ps.update(document.getElementById('my-netdata-dropdown-content'));
4268 };
4269 NETDATA.onresizeCallback();
4270