@cryptotaxi247 / netdata-1 / commits / a7f03d3e5

fixed minor HTML errors

Costa Tsaousis (ktsaou) committed Dec 26, 2016 at 22:36 UTC a7f03d3e521a8b0794d260ce3a857d4cebd177ef
1 file changed +1896 -1898
web/index.html
+1896 -1898
@@ -390,2197 +390,2196 @@
390 }
391
392 </style>
393 -</head>
393
395 -<!-- check which theme to use -->
396 -<script type="text/javascript">
397 - // enable alarms checking and notifications
398 - var netdataShowAlarms = true;
399 -
400 - // enable registry updates
401 - var netdataRegistry = true;
402 -
403 - // --------------------------------------------------------------------
404 - // urlOptions
405 -
406 - var urlOptions = {
407 - hash: '#',
408 - theme: null,
409 - help: null,
410 - update_always: false,
411 - pan_and_zoom: false,
412 - after: 0,
413 - before: 0,
414 - nowelcome: false,
415 - show_alarms: false,
416 - chart: null,
417 - family: null,
418 - alarm: null,
419 - alarm_unique_id: 0,
420 - alarm_id: 0,
421 - alarm_event_id: 0,
422 -
423 - hasProperty: function(property) {
424 - // console.log('checking property ' + property + ' of type ' + typeof(this[property]));
425 - return typeof this[property] !== 'undefined';
426 - },
427 -
428 - genHash: function() {
429 - var hash = urlOptions.hash;
430 -
431 - if(urlOptions.pan_and_zoom === true) {
432 - hash += ';after=' + urlOptions.after.toString() +
433 - ';before=' + urlOptions.before.toString();
434 - }
394 + <!-- check which theme to use -->
395 + <script type="text/javascript">
396 + // enable alarms checking and notifications
397 + var netdataShowAlarms = true;
398 +
399 + // enable registry updates
400 + var netdataRegistry = true;
401 +
402 + // --------------------------------------------------------------------
403 + // urlOptions
404 +
405 + var urlOptions = {
406 + hash: '#',
407 + theme: null,
408 + help: null,
409 + update_always: false,
410 + pan_and_zoom: false,
411 + after: 0,
412 + before: 0,
413 + nowelcome: false,
414 + show_alarms: false,
415 + chart: null,
416 + family: null,
417 + alarm: null,
418 + alarm_unique_id: 0,
419 + alarm_id: 0,
420 + alarm_event_id: 0,
421 +
422 + hasProperty: function(property) {
423 + // console.log('checking property ' + property + ' of type ' + typeof(this[property]));
424 + return typeof this[property] !== 'undefined';
425 + },
426 +
427 + genHash: function() {
428 + var hash = urlOptions.hash;
429 +
430 + if(urlOptions.pan_and_zoom === true) {
431 + hash += ';after=' + urlOptions.after.toString() +
432 + ';before=' + urlOptions.before.toString();
433 + }
434
436 - if(urlOptions.theme !== null)
437 - hash += ';theme=' + urlOptions.theme.toString();
435 + if(urlOptions.theme !== null)
436 + hash += ';theme=' + urlOptions.theme.toString();
437
439 - if(urlOptions.help !== null)
440 - hash += ';help=' + urlOptions.help.toString();
438 + if(urlOptions.help !== null)
439 + hash += ';help=' + urlOptions.help.toString();
440
442 - if(urlOptions.update_always === true)
443 - hash += ';update_always=true';
441 + if(urlOptions.update_always === true)
442 + hash += ';update_always=true';
443
445 - return hash;
446 - },
444 + return hash;
445 + },
446
448 - parseHash: function() {
449 - var variables = document.location.hash.split(';');
450 - var len = variables.length;
451 - while(len--) {
452 - if(len !== 0) {
453 - var p = variables[len].split('=');
454 - if(urlOptions.hasProperty(p[0]) && typeof p[1] !== 'undefined')
455 - urlOptions[p[0]] = decodeURIComponent(p[1]);
447 + parseHash: function() {
448 + var variables = document.location.hash.split(';');
449 + var len = variables.length;
450 + while(len--) {
451 + if(len !== 0) {
452 + var p = variables[len].split('=');
453 + if(urlOptions.hasProperty(p[0]) && typeof p[1] !== 'undefined')
454 + urlOptions[p[0]] = decodeURIComponent(p[1]);
455 + }
456 + else {
457 + if(variables[len].length > 0)
458 + urlOptions.hash = variables[len];
459 + }
460 }
457 - else {
458 - if(variables[len].length > 0)
459 - urlOptions.hash = variables[len];
461 +
462 + var booleans = [ 'nowelcome', 'show_alarms', 'pan_and_zoom', 'update_always' ];
463 + len = booleans.length;
464 + while(len--) {
465 + if(urlOptions[booleans[len]] === 'true' || urlOptions[booleans[len]] === true || urlOptions[booleans[len]] === '1' || urlOptions[booleans[len]] === 1)
466 + urlOptions[booleans[len]] = true;
467 + else
468 + urlOptions[booleans[len]] = false;
469 }
461 - }
470
463 - var booleans = [ 'nowelcome', 'show_alarms', 'pan_and_zoom', 'update_always' ];
464 - len = booleans.length;
465 - while(len--) {
466 - if(urlOptions[booleans[len]] === 'true' || urlOptions[booleans[len]] === true || urlOptions[booleans[len]] === '1' || urlOptions[booleans[len]] === 1)
467 - urlOptions[booleans[len]] = true;
471 + if(urlOptions.before > 0 && urlOptions.after > 0) {
472 + urlOptions.pan_and_zoom = true;
473 + urlOptions.nowelcome = true;
474 + }
475 else
469 - urlOptions[booleans[len]] = false;
470 - }
476 + urlOptions.pan_and_zoom = false;
477 +
478 + // console.log(urlOptions);
479 + },
480
472 - if(urlOptions.before > 0 && urlOptions.after > 0) {
473 - urlOptions.pan_and_zoom = true;
474 - urlOptions.nowelcome = true;
481 + hashUpdate: function() {
482 + history.replaceState(null, '', urlOptions.genHash());
483 + },
484 +
485 + netdataPanAndZoomCallback: function(status, after, before) {
486 + urlOptions.pan_and_zoom = status;
487 + urlOptions.after = after;
488 + urlOptions.before = before;
489 + urlOptions.hashUpdate();
490 }
476 - else
477 - urlOptions.pan_and_zoom = false;
491
479 - // console.log(urlOptions);
480 - },
492 + };
493
482 - hashUpdate: function() {
483 - history.replaceState(null, '', urlOptions.genHash());
484 - },
494 + urlOptions.parseHash();
495
486 - netdataPanAndZoomCallback: function(status, after, before) {
487 - urlOptions.pan_and_zoom = status;
488 - urlOptions.after = after;
489 - urlOptions.before = before;
490 - urlOptions.hashUpdate();
491 - }
496 + // --------------------------------------------------------------------
497 + // check options that should be processed before loading netdata.js
498
493 - };
499 + function loadLocalStorage(name) {
500 + var ret = null;
501
495 - urlOptions.parseHash();
502 + try {
503 + if(typeof Storage !== "undefined" && typeof localStorage === 'object')
504 + ret = localStorage.getItem(name);
505 + }
506 + catch(error) {
507 + ;
508 + }
509
497 - // --------------------------------------------------------------------
498 - // check options that should be processed before loading netdata.js
510 + if(typeof ret === 'undefined' || ret === null)
511 + return null;
512
500 - function loadLocalStorage(name) {
501 - var ret = null;
513 + // console.log('loaded: ' + name.toString() + ' = ' + ret.toString());
514
503 - try {
504 - if(typeof Storage !== "undefined" && typeof localStorage === 'object')
505 - ret = localStorage.getItem(name);
506 - }
507 - catch(error) {
508 - ;
515 + return ret;
516 }
517
511 - if(typeof ret === 'undefined' || ret === null)
512 - return null;
513 -
514 - // console.log('loaded: ' + name.toString() + ' = ' + ret.toString());
518 + function saveLocalStorage(name, value) {
519 + // console.log('saving: ' + name.toString() + ' = ' + value.toString());
520 + try {
521 + if(typeof Storage !== "undefined" && typeof localStorage === 'object') {
522 + localStorage.setItem(name, value.toString());
523 + return true;
524 + }
525 + }
526 + catch(error) {
527 + ;
528 + }
529
516 - return ret;
517 - }
530 + return false;
531 + }
532
519 - function saveLocalStorage(name, value) {
520 - // console.log('saving: ' + name.toString() + ' = ' + value.toString());
521 - try {
522 - if(typeof Storage !== "undefined" && typeof localStorage === 'object') {
523 - localStorage.setItem(name, value.toString());
524 - return true;
525 - }
533 + function getTheme(def) {
534 + var ret = loadLocalStorage('netdataTheme');
535 + if(typeof ret === 'undefined' || ret === null || ret === 'undefined')
536 + return def;
537 + else
538 + return ret;
539 }
527 - catch(error) {
528 - ;
540 +
541 + function setTheme(theme) {
542 + if(theme === netdataTheme) return false;
543 + return saveLocalStorage('netdataTheme', theme);
544 }
545
531 - return false;
532 - }
546 + var netdataTheme = getTheme('slate');
547 + var netdataShowHelp = true;
548
534 - function getTheme(def) {
535 - var ret = loadLocalStorage('netdataTheme');
536 - if(typeof ret === 'undefined' || ret === null || ret === 'undefined')
537 - return def;
549 + if(urlOptions.theme !== null) {
550 + setTheme(urlOptions.theme);
551 + netdataTheme = urlOptions.theme;
552 + }
553 else
539 - return ret;
540 - }
541 -
542 - function setTheme(theme) {
543 - if(theme === netdataTheme) return false;
544 - return saveLocalStorage('netdataTheme', theme);
545 - }
546 -
547 - var netdataTheme = getTheme('slate');
548 - var netdataShowHelp = true;
549 -
550 - if(urlOptions.theme !== null) {
551 - setTheme(urlOptions.theme);
552 - netdataTheme = urlOptions.theme;
553 - }
554 - else
555 - urlOptions.theme = netdataTheme;
554 + urlOptions.theme = netdataTheme;
555
557 - if(urlOptions.help !== null) {
558 - saveLocalStorage('options.show_help', urlOptions.help);
559 - netdataShowHelp = urlOptions.help;
560 - }
561 - else {
562 - urlOptions.help = loadLocalStorage('options.show_help');
563 - }
556 + if(urlOptions.help !== null) {
557 + saveLocalStorage('options.show_help', urlOptions.help);
558 + netdataShowHelp = urlOptions.help;
559 + }
560 + else {
561 + urlOptions.help = loadLocalStorage('options.show_help');
562 + }
563
565 - // --------------------------------------------------------------------
566 - // registry call back to render my-netdata menu
564 + // --------------------------------------------------------------------
565 + // registry call back to render my-netdata menu
566
568 - var netdataRegistryCallback = function(machines_array) {
569 - var el = '';
570 - var a1 = '';
571 - var found = 0;
567 + var netdataRegistryCallback = function(machines_array) {
568 + var el = '';
569 + var a1 = '';
570 + var found = 0;
571
573 - if(machines_array === null) {
574 - var ret = loadLocalStorage("registryCallback");
575 - if(typeof ret !== 'undefined' && ret !== null) {
576 - machines_array = JSON.parse(ret);
577 - console.log("failed to contact the registry - loaded registry data from browser local storage");
572 + if(machines_array === null) {
573 + var ret = loadLocalStorage("registryCallback");
574 + if(typeof ret !== 'undefined' && ret !== null) {
575 + machines_array = JSON.parse(ret);
576 + console.log("failed to contact the registry - loaded registry data from browser local storage");
577 + }
578 }
579 - }
579
581 - if(machines_array) {
582 - saveLocalStorage("registryCallback", JSON.stringify(machines_array));
580 + if(machines_array) {
581 + saveLocalStorage("registryCallback", JSON.stringify(machines_array));
582
584 - var machines = machines_array.sort(function (a, b) {
585 - if (a.name > b.name) return -1;
586 - if (a.name < b.name) return 1;
587 - return 0;
588 - });
583 + var machines = machines_array.sort(function (a, b) {
584 + if (a.name > b.name) return -1;
585 + if (a.name < b.name) return 1;
586 + return 0;
587 + });
588
590 - var len = machines.length;
591 - while(len--) {
592 - var u = machines[len];
593 - found++;
594 - el += '<li id="registry_server_' + u.guid + '"><a class="registry_link" href="' + u.url + '" onClick="return gotoServerModalHandler(\'' + u.guid + '\');">' + u.name + '</a></li>';
595 - a1 += '<li id="registry_action_' + u.guid + '"><a href="#" onclick="deleteRegistryModalHandler(\'' + u.guid + '\',\'' + u.name + '\',\'' + u.url + '\'); return false;"><i class="fa fa-trash-o" aria-hidden="true" style="color: #999;"></i></a></li>';
589 + var len = machines.length;
590 + while(len--) {
591 + var u = machines[len];
592 + found++;
593 + el += '<li id="registry_server_' + u.guid + '"><a class="registry_link" href="' + u.url + '" onClick="return gotoServerModalHandler(\'' + u.guid + '\');">' + u.name + '</a></li>';
594 + a1 += '<li id="registry_action_' + u.guid + '"><a href="#" onclick="deleteRegistryModalHandler(\'' + u.guid + '\',\'' + u.name + '\',\'' + u.url + '\'); return false;"><i class="fa fa-trash-o" aria-hidden="true" style="color: #999;"></i></a></li>';
595 + }
596 }
597 - }
598 -
599 - if(!found) {
600 - if(machines)
601 - el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #666;" target="_blank">your netdata server list is empty...</a></li>';
602 - else
603 - el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #666;" target="_blank">failed to contact the registry...</a></li>';
604 -
605 - a1 += '<li><a href="#" onClick="return false;">&nbsp;</a></li>';
606 -
607 - el += '<li role="separator" class="divider"></li>' +
608 - '<li><a href="//london.netdata.rocks/default.html">UK - London (DigitalOcean.com)</a></li>' +
609 - '<li><a href="//newyork.netdata.rocks/default.html">US - New York (DigitalOcean.com)</a></li>' +
610 - '<li><a href="//sanfrancisco.netdata.rocks/default.html">US - San Francisco (DigitalOcean.com)</a></li>' +
611 - '<li><a href="//atlanta.netdata.rocks/default.html">US - Atlanta (CDN77.com)</a></li>' +
612 - '<li><a href="//frankfurt.netdata.rocks/default.html">Germany - Frankfurt (DigitalOcean.com)</a></li>' +
613 - '<li><a href="//toronto.netdata.rocks/default.html">Canada - Toronto (DigitalOcean.com)</a></li>' +
614 - '<li><a href="//singapore.netdata.rocks/default.html">Japan - Singapore (DigitalOcean.com)</a></li>' +
615 - '<li><a href="//bangalore.netdata.rocks/default.html">India - Bangalore (DigitalOcean.com)</a></li>';
616 - a1 += '<li role="separator" class="divider"></li>' +
617 - '<li><a href="#">&nbsp;</a></li>' +
618 - '<li><a href="#">&nbsp;</a></li>'+
619 - '<li><a href="#">&nbsp;</a></li>'+
620 - '<li><a href="#">&nbsp;</a></li>'+
621 - '<li><a href="#">&nbsp;</a></li>'+
622 - '<li><a href="#">&nbsp;</a></li>'+
623 - '<li><a href="#">&nbsp;</a></li>'+
624 - '<li><a href="#">&nbsp;</a></li>';
625 - }
597
627 - el += '<li role="separator" class="divider"></li>';
628 - a1 += '<li role="separator" class="divider"></li>';
598 + if(!found) {
599 + if(machines)
600 + el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #666;" target="_blank">your netdata server list is empty...</a></li>';
601 + else
602 + el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #666;" target="_blank">failed to contact the registry...</a></li>';
603 +
604 + a1 += '<li><a href="#" onClick="return false;">&nbsp;</a></li>';
605 +
606 + el += '<li role="separator" class="divider"></li>' +
607 + '<li><a href="//london.netdata.rocks/default.html">UK - London (DigitalOcean.com)</a></li>' +
608 + '<li><a href="//newyork.netdata.rocks/default.html">US - New York (DigitalOcean.com)</a></li>' +
609 + '<li><a href="//sanfrancisco.netdata.rocks/default.html">US - San Francisco (DigitalOcean.com)</a></li>' +
610 + '<li><a href="//atlanta.netdata.rocks/default.html">US - Atlanta (CDN77.com)</a></li>' +
611 + '<li><a href="//frankfurt.netdata.rocks/default.html">Germany - Frankfurt (DigitalOcean.com)</a></li>' +
612 + '<li><a href="//toronto.netdata.rocks/default.html">Canada - Toronto (DigitalOcean.com)</a></li>' +
613 + '<li><a href="//singapore.netdata.rocks/default.html">Japan - Singapore (DigitalOcean.com)</a></li>' +
614 + '<li><a href="//bangalore.netdata.rocks/default.html">India - Bangalore (DigitalOcean.com)</a></li>';
615 + a1 += '<li role="separator" class="divider"></li>' +
616 + '<li><a href="#">&nbsp;</a></li>' +
617 + '<li><a href="#">&nbsp;</a></li>'+
618 + '<li><a href="#">&nbsp;</a></li>'+
619 + '<li><a href="#">&nbsp;</a></li>'+
620 + '<li><a href="#">&nbsp;</a></li>'+
621 + '<li><a href="#">&nbsp;</a></li>'+
622 + '<li><a href="#">&nbsp;</a></li>'+
623 + '<li><a href="#">&nbsp;</a></li>';
624 + }
625
630 - el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #999;" target="_blank">What is this?</a></li>';
631 - a1 += '<li><a href="#" style="color: #999;" onclick="switchRegistryModalHandler(); return false;"><i class="fa fa-sliders" aria-hidden="true" style="color: #999;"></i></a></li>'
626 + el += '<li role="separator" class="divider"></li>';
627 + a1 += '<li role="separator" class="divider"></li>';
628
633 - document.getElementById('mynetdata_servers').innerHTML = el;
634 - document.getElementById('mynetdata_servers2').innerHTML = el;
635 - document.getElementById('mynetdata_actions1').innerHTML = a1;
629 + el += '<li><a href="https://github.com/firehol/netdata/wiki/mynetdata-menu-item" style="color: #999;" target="_blank">What is this?</a></li>';
630 + a1 += '<li><a href="#" style="color: #999;" onclick="switchRegistryModalHandler(); return false;"><i class="fa fa-sliders" aria-hidden="true" style="color: #999;"></i></a></li>'
631
637 - gotoServerInit();
638 - };
632 + document.getElementById('mynetdata_servers').innerHTML = el;
633 + document.getElementById('mynetdata_servers2').innerHTML = el;
634 + document.getElementById('mynetdata_actions1').innerHTML = a1;
635
640 - var this_is_demo = null; // FIXME
641 - function isdemo() {
642 - if(this_is_demo !== null) return this_is_demo;
643 - this_is_demo = false;
636 + gotoServerInit();
637 + };
638
645 - try {
646 - if(typeof document.location.hostname === 'string') {
647 - if(document.location.hostname.endsWith('.my-netdata.io') ||
648 - document.location.hostname.endsWith('.mynetdata.io') ||
649 - document.location.hostname.endsWith('.netdata.rocks') ||
650 - document.location.hostname.endsWith('.firehol.org') ||
651 - document.location.hostname.endsWith('.netdata.online'))
652 - this_is_demo = true;
639 + var this_is_demo = null; // FIXME
640 + function isdemo() {
641 + if(this_is_demo !== null) return this_is_demo;
642 + this_is_demo = false;
643 +
644 + try {
645 + if(typeof document.location.hostname === 'string') {
646 + if(document.location.hostname.endsWith('.my-netdata.io') ||
647 + document.location.hostname.endsWith('.mynetdata.io') ||
648 + document.location.hostname.endsWith('.netdata.rocks') ||
649 + document.location.hostname.endsWith('.firehol.org') ||
650 + document.location.hostname.endsWith('.netdata.online'))
651 + this_is_demo = true;
652 + }
653 + }
654 + catch(error) {
655 + ;
656 }
654 - }
655 - catch(error) {
656 - ;
657 - }
657
659 - return this_is_demo;
660 - }
658 + return this_is_demo;
659 + }
660
662 - function netdataURL(url) {
663 - if(typeof url === 'undefined')
664 - url = document.location.toString();
661 + function netdataURL(url) {
662 + if(typeof url === 'undefined')
663 + url = document.location.toString();
664
666 - if(url.indexOf('#') !== -1)
667 - url = url.substring(0, url.indexOf('#'));
665 + if(url.indexOf('#') !== -1)
666 + url = url.substring(0, url.indexOf('#'));
667
669 - var hash = urlOptions.genHash();
668 + var hash = urlOptions.genHash();
669
671 - // console.log('netdataURL: ' + url + hash);
670 + // console.log('netdataURL: ' + url + hash);
671
673 - return url + hash;
674 - }
672 + return url + hash;
673 + }
674
676 - function netdataReload(url) {
677 - var t = netdataURL(url);
678 - // console.log('netdataReload: ' + t);
679 - document.location = t;
675 + function netdataReload(url) {
676 + var t = netdataURL(url);
677 + // console.log('netdataReload: ' + t);
678 + document.location = t;
679
681 - // since we play with hash
682 - // this is needed to reload the page
683 - location.reload();
684 - }
680 + // since we play with hash
681 + // this is needed to reload the page
682 + location.reload();
683 + }
684
686 - var gotoServerValidateRemaining = 0;
687 - var gotoServerMiddleClick = false;
688 - var gotoServerStop = false;
689 - function gotoServerValidateUrl(id, guid, url) {
690 - var penaldy = 0;
691 - var error = 'failed';
685 + var gotoServerValidateRemaining = 0;
686 + var gotoServerMiddleClick = false;
687 + var gotoServerStop = false;
688 + function gotoServerValidateUrl(id, guid, url) {
689 + var penaldy = 0;
690 + var error = 'failed';
691
693 - if(document.location.toString().startsWith('http://') && url.toString().startsWith('https://'))
694 - // we penalize https only if the current url is http
695 - // to allow the user walk through all its servers.
696 - penaldy = 500;
692 + if(document.location.toString().startsWith('http://') && url.toString().startsWith('https://'))
693 + // we penalize https only if the current url is http
694 + // to allow the user walk through all its servers.
695 + penaldy = 500;
696
698 - else if(document.location.toString().startsWith('https://') && url.toString().startsWith('http://'))
699 - error = 'can\'t check';
697 + else if(document.location.toString().startsWith('https://') && url.toString().startsWith('http://'))
698 + error = 'can\'t check';
699
701 - var finalURL = netdataURL(url);
700 + var finalURL = netdataURL(url);
701
703 - setTimeout(function() {
704 - document.getElementById('gotoServerList').innerHTML += '<tr><td style="padding-left: 20px;"><a href="' + finalURL + '" target="_blank">' + url + '</a></td><td style="padding-left: 30px;"><code id="' + guid + '-' + id + '-status">checking...</code></td></tr>';
702 + setTimeout(function() {
703 + document.getElementById('gotoServerList').innerHTML += '<tr><td style="padding-left: 20px;"><a href="' + finalURL + '" target="_blank">' + url + '</a></td><td style="padding-left: 30px;"><code id="' + guid + '-' + id + '-status">checking...</code></td></tr>';
704
706 - NETDATA.registry.hello(url, function(data) {
707 - if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid === guid) {
708 - // console.log('OK ' + id + ' URL: ' + url);
709 - document.getElementById(guid + '-' + id + '-status').innerHTML = "OK";
705 + NETDATA.registry.hello(url, function(data) {
706 + if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid === guid) {
707 + // console.log('OK ' + id + ' URL: ' + url);
708 + document.getElementById(guid + '-' + id + '-status').innerHTML = "OK";
709
711 - if(!gotoServerStop) {
712 - gotoServerStop = true;
710 + if(!gotoServerStop) {
711 + gotoServerStop = true;
712
714 - if(gotoServerMiddleClick) {
715 - window.open(finalURL, '_blank');
716 - gotoServerMiddleClick = false;
717 - document.getElementById('gotoServerResponse').innerHTML = '<b>Opening new window to ' + NETDATA.registry.machines[guid].name + '<br/><a href="' + finalURL + '">' + url + '</a></b><br/>(check your pop-up blocker if it fails)';
718 - }
719 - else {
720 - document.getElementById('gotoServerResponse').innerHTML += 'found it! It is at:<br/><small>' + url + '</small>';
721 - document.location = finalURL;
713 + if(gotoServerMiddleClick) {
714 + window.open(finalURL, '_blank');
715 + gotoServerMiddleClick = false;
716 + document.getElementById('gotoServerResponse').innerHTML = '<b>Opening new window to ' + NETDATA.registry.machines[guid].name + '<br/><a href="' + finalURL + '">' + url + '</a></b><br/>(check your pop-up blocker if it fails)';
717 + }
718 + else {
719 + document.getElementById('gotoServerResponse').innerHTML += 'found it! It is at:<br/><small>' + url + '</small>';
720 + document.location = finalURL;
721 + }
722 }
723 }
724 - }
725 - else {
726 - if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid !== guid)
727 - error = 'wrong machine';
728 -
729 - document.getElementById(guid + '-' + id + '-status').innerHTML = error;
730 - gotoServerValidateRemaining--;
731 - if(gotoServerValidateRemaining <= 0) {
732 - gotoServerMiddleClick = false;
733 - document.getElementById('gotoServerResponse').innerHTML = '<b>Sorry! I cannot find any operational URL for this server</b>';
734 - }
735 - }
736 - });
737 - }, (id * 50) + penaldy);
738 - }
739 -
740 - function gotoServerModalHandler(guid) {
741 - // console.log('goto server: ' + guid);
742 -
743 - gotoServerStop = false;
744 - var checked = {};
745 - var len = NETDATA.registry.machines[guid].alternate_urls.length;
746 - var count = 0;
747 -
748 - document.getElementById('gotoServerResponse').innerHTML = '';
749 - document.getElementById('gotoServerList').innerHTML = '';
750 - document.getElementById('gotoServerName').innerHTML = NETDATA.registry.machines[guid].name;
751 - $('#gotoServerModal').modal('show');
752 -
753 - gotoServerValidateRemaining = len;
754 - while(len--) {
755 - var url = NETDATA.registry.machines[guid].alternate_urls[len];
756 - checked[url] = true;
757 - gotoServerValidateUrl(count++, guid, url);
758 - }
724 + else {
725 + if(typeof data !== 'undefined' && data !== null && typeof data.machine_guid === 'string' && data.machine_guid !== guid)
726 + error = 'wrong machine';
727
760 - setTimeout(function() {
761 - if(gotoServerStop === false) {
762 - document.getElementById('gotoServerResponse').innerHTML = '<b>Added all the known URLs for this machine.</b>';
763 - NETDATA.registry.search(guid, function(data) {
764 - // console.log(data);
765 - len = data.urls.length;
766 - while(len--) {
767 - var url = data.urls[len][1];
768 - // console.log(url);
769 - if(typeof checked[url] === 'undefined') {
770 - gotoServerValidateRemaining++;
771 - checked[url] = true;
772 - gotoServerValidateUrl(count++, guid, url);
728 + document.getElementById(guid + '-' + id + '-status').innerHTML = error;
729 + gotoServerValidateRemaining--;
730 + if(gotoServerValidateRemaining <= 0) {
731 + gotoServerMiddleClick = false;
732 + document.getElementById('gotoServerResponse').innerHTML = '<b>Sorry! I cannot find any operational URL for this server</b>';
733 }
734 }
735 });
776 - }
777 - }, 2000);
778 - return false;
779 - }
736 + }, (id * 50) + penaldy);
737 + }
738
781 - function gotoServerInit() {
782 - $(".registry_link").on('click', function(e) {
783 - if(e.which === 2) {
784 - e.preventDefault();
785 - gotoServerMiddleClick = true;
786 - }
787 - else {
788 - gotoServerMiddleClick = false;
789 - }
739 + function gotoServerModalHandler(guid) {
740 + // console.log('goto server: ' + guid);
741
791 - return true;
792 - });
793 - }
742 + gotoServerStop = false;
743 + var checked = {};
744 + var len = NETDATA.registry.machines[guid].alternate_urls.length;
745 + var count = 0;
746
795 - function switchRegistryModalHandler() {
796 - document.getElementById('switchRegistryPersonGUID').value = NETDATA.registry.person_guid;
797 - document.getElementById('switchRegistryURL').innerHTML = NETDATA.registry.server;
798 - document.getElementById('switchRegistryResponse').innerHTML = '';
799 - $('#switchRegistryModal').modal('show');
800 - }
747 + document.getElementById('gotoServerResponse').innerHTML = '';
748 + document.getElementById('gotoServerList').innerHTML = '';
749 + document.getElementById('gotoServerName').innerHTML = NETDATA.registry.machines[guid].name;
750 + $('#gotoServerModal').modal('show');
751
802 - function notifyForSwitchRegistry() {
803 - var n = document.getElementById('switchRegistryPersonGUID').value;
752 + gotoServerValidateRemaining = len;
753 + while(len--) {
754 + var url = NETDATA.registry.machines[guid].alternate_urls[len];
755 + checked[url] = true;
756 + gotoServerValidateUrl(count++, guid, url);
757 + }
758
805 - if(n !== '' && n.length === 36) {
806 - NETDATA.registry.switch(n, function(result) {
807 - if(result !== null) {
808 - $('#switchRegistryModal').modal('hide');
809 - NETDATA.registry.init();
810 - }
811 - else {
812 - document.getElementById('switchRegistryResponse').innerHTML = "<b>Sorry! The registry rejected your request.</b>";
759 + setTimeout(function() {
760 + if(gotoServerStop === false) {
761 + document.getElementById('gotoServerResponse').innerHTML = '<b>Added all the known URLs for this machine.</b>';
762 + NETDATA.registry.search(guid, function(data) {
763 + // console.log(data);
764 + len = data.urls.length;
765 + while(len--) {
766 + var url = data.urls[len][1];
767 + // console.log(url);
768 + if(typeof checked[url] === 'undefined') {
769 + gotoServerValidateRemaining++;
770 + checked[url] = true;
771 + gotoServerValidateUrl(count++, guid, url);
772 + }
773 + }
774 + });
775 }
814 - });
776 + }, 2000);
777 + return false;
778 }
816 - else
817 - document.getElementById('switchRegistryResponse').innerHTML = "<b>The ID you have entered is not a GUID.</b>";
818 - }
819 -
820 - var deleteRegistryUrl = null;
821 - function deleteRegistryModalHandler(guid, name, url) {
822 - deleteRegistryUrl = url;
823 - document.getElementById('deleteRegistryServerName').innerHTML = name;
824 - document.getElementById('deleteRegistryServerName2').innerHTML = name;
825 - document.getElementById('deleteRegistryServerURL').innerHTML = url;
826 - document.getElementById('deleteRegistryResponse').innerHTML = '';
827 - $('#deleteRegistryModal').modal('show');
828 - }
779
830 - function notifyForDeleteRegistry() {
831 - if(deleteRegistryUrl) {
832 - NETDATA.registry.delete(deleteRegistryUrl, function(result) {
833 - if(result !== null) {
834 - deleteRegistryUrl = null;
835 - $('#deleteRegistryModal').modal('hide');
836 - NETDATA.registry.init();
780 + function gotoServerInit() {
781 + $(".registry_link").on('click', function(e) {
782 + if(e.which === 2) {
783 + e.preventDefault();
784 + gotoServerMiddleClick = true;
785 }
786 else {
839 - document.getElementById('deleteRegistryResponse').innerHTML = "<b>Sorry! this command was rejected by the registry server.</b>";
787 + gotoServerMiddleClick = false;
788 }
789 +
790 + return true;
791 });
792 }
843 - }
793
845 - var options = {
846 - sparklines_registry: {},
847 - menus: {},
848 - submenu_names: {},
849 - data: null,
850 - hostname: 'netdata_server', // will be overwritten by the netdata server
851 - categories: new Array(),
852 - categories_idx: {},
853 - families: new Array(),
854 - families_idx: {},
855 -
856 - chartsPerRow: 0,
857 - chartsMinWidth: 1450,
858 - chartsHeight: 180,
859 - sparklinesHeight: 60,
860 - };
861 -
862 - // generate a sparkline
863 - // used in the documentation
864 - function sparkline(chart, dimension, units) {
865 - var key = chart + '.' + dimension;
866 -
867 - if(typeof units === 'undefined')
868 - units = '';
869 -
870 - if(typeof options.sparklines_registry[key] === 'undefined')
871 - options.sparklines_registry[key] = { count: 1 };
872 - else
873 - options.sparklines_registry[key].count++;
794 + function switchRegistryModalHandler() {
795 + document.getElementById('switchRegistryPersonGUID').value = NETDATA.registry.person_guid;
796 + document.getElementById('switchRegistryURL').innerHTML = NETDATA.registry.server;
797 + document.getElementById('switchRegistryResponse').innerHTML = '';
798 + $('#switchRegistryModal').modal('show');
799 + }
800
875 - key = key + '.' + options.sparklines_registry[key].count;
801 + function notifyForSwitchRegistry() {
802 + var n = document.getElementById('switchRegistryPersonGUID').value;
803
877 - var h = '<div data-netdata="' + chart + '" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dimensions="' + dimension + '" data-show-value-of-' + dimension + '-at="' + key + '"></div> (<span id="' + key + '" style="display: inline-block; min-width: 50px; text-align: right;">X</span>' + units + ')';
804 + if(n !== '' && n.length === 36) {
805 + NETDATA.registry.switch(n, function(result) {
806 + if(result !== null) {
807 + $('#switchRegistryModal').modal('hide');
808 + NETDATA.registry.init();
809 + }
810 + else {
811 + document.getElementById('switchRegistryResponse').innerHTML = "<b>Sorry! The registry rejected your request.</b>";
812 + }
813 + });
814 + }
815 + else
816 + document.getElementById('switchRegistryResponse').innerHTML = "<b>The ID you have entered is not a GUID.</b>";
817 + }
818
879 - return h;
880 - }
819 + var deleteRegistryUrl = null;
820 + function deleteRegistryModalHandler(guid, name, url) {
821 + deleteRegistryUrl = url;
822 + document.getElementById('deleteRegistryServerName').innerHTML = name;
823 + document.getElementById('deleteRegistryServerName2').innerHTML = name;
824 + document.getElementById('deleteRegistryServerURL').innerHTML = url;
825 + document.getElementById('deleteRegistryResponse').innerHTML = '';
826 + $('#deleteRegistryModal').modal('show');
827 + }
828
882 - function chartsPerRow(total) {
883 - if(options.chartsPerRow === 0) {
884 - width = Math.floor(total / options.chartsMinWidth);
885 - if(width === 0) width = 1;
886 - return width;
829 + function notifyForDeleteRegistry() {
830 + if(deleteRegistryUrl) {
831 + NETDATA.registry.delete(deleteRegistryUrl, function(result) {
832 + if(result !== null) {
833 + deleteRegistryUrl = null;
834 + $('#deleteRegistryModal').modal('hide');
835 + NETDATA.registry.init();
836 + }
837 + else {
838 + document.getElementById('deleteRegistryResponse').innerHTML = "<b>Sorry! this command was rejected by the registry server.</b>";
839 + }
840 + });
841 + }
842 }
888 - else return options.chartsPerRow;
889 - }
843
891 - function prioritySort(a, b) {
892 - if(a.priority < b.priority) return -1;
893 - if(a.priority > b.priority) return 1;
894 - if(a.name < b.name) return -1;
895 - return 1;
896 - }
844 + var options = {
845 + sparklines_registry: {},
846 + menus: {},
847 + submenu_names: {},
848 + data: null,
849 + hostname: 'netdata_server', // will be overwritten by the netdata server
850 + categories: new Array(),
851 + categories_idx: {},
852 + families: new Array(),
853 + families_idx: {},
854 +
855 + chartsPerRow: 0,
856 + chartsMinWidth: 1450,
857 + chartsHeight: 180,
858 + sparklinesHeight: 60,
859 + };
860
898 - function sortObjectByPriority(object) {
899 - var idx = {};
900 - var sorted = new Array();
861 + // generate a sparkline
862 + // used in the documentation
863 + function sparkline(chart, dimension, units) {
864 + var key = chart + '.' + dimension;
865
902 - for(var i in object) {
903 - if(typeof idx[i] === 'undefined') {
904 - idx[i] = object[i];
905 - sorted.push(i);
906 - }
907 - }
866 + if(typeof units === 'undefined')
867 + units = '';
868
909 - sorted.sort(function(a, b) {
910 - if(idx[a].priority < idx[b].priority) return -1;
911 - if(idx[a].priority > idx[b].priority) return 1;
912 - if(a < b) return -1;
913 - return 1;
914 - });
869 + if(typeof options.sparklines_registry[key] === 'undefined')
870 + options.sparklines_registry[key] = { count: 1 };
871 + else
872 + options.sparklines_registry[key].count++;
873
916 - return sorted;
917 - }
874 + key = key + '.' + options.sparklines_registry[key].count;
875
876 + var h = '<div data-netdata="' + chart + '" data-after="-120" data-width="25%" data-height="15px" data-chart-library="dygraph" data-dygraph-theme="sparkline" data-dimensions="' + dimension + '" data-show-value-of-' + dimension + '-at="' + key + '"></div> (<span id="' + key + '" style="display: inline-block; min-width: 50px; text-align: right;">X</span>' + units + ')';
877
920 - // ----------------------------------------------------------------------------
921 - // scroll to a section, without changing the browser history
878 + return h;
879 + }
880
923 - function scrollToId(hash) {
924 - if(hash && hash != '' && document.getElementById(hash) !== null) {
925 - var offset = $('#' + hash).offset();
926 - if(typeof offset !== 'undefined')
927 - $('html, body').animate({ scrollTop: offset.top }, 0);
881 + function chartsPerRow(total) {
882 + if(options.chartsPerRow === 0) {
883 + width = Math.floor(total / options.chartsMinWidth);
884 + if(width === 0) width = 1;
885 + return width;
886 + }
887 + else return options.chartsPerRow;
888 }
889
930 - // we must return false to prevent the default action
931 - return false;
932 - }
890 + function prioritySort(a, b) {
891 + if(a.priority < b.priority) return -1;
892 + if(a.priority > b.priority) return 1;
893 + if(a.name < b.name) return -1;
894 + return 1;
895 + }
896
934 - // ----------------------------------------------------------------------------
935 -
936 - var netdataDashboard = {
937 - menu: {},
938 - submenu: {},
939 - context: {},
940 -
941 - gaugeChart: function(title, width, dimensions, colors) {
942 - if(typeof colors === 'undefined')
943 - colors = '';
944 -
945 - if(typeof dimensions === 'undefined')
946 - dimensions = '';
947 -
948 - return '<div data-netdata="CHART_UNIQUE_ID"'
949 - + ' data-dimensions="' + dimensions + '"'
950 - + ' data-chart-library="gauge"'
951 - + ' data-gauge-adjust="width"'
952 - + ' data-title="' + title + '"'
953 - + ' data-width="' + width + '"'
954 - + ' data-before="0"'
955 - + ' data-after="-CHART_DURATION"'
956 - + ' data-points="CHART_DURATION"'
957 - + ' data-colors="' + colors + '"'
958 - + ' role="application"></div>';
959 - },
960 -
961 - anyAttribute: function(obj, attr, key, def) {
962 - if(typeof obj[key] !== 'undefined') {
963 - if(typeof obj[key][attr] !== 'undefined')
964 - return obj[key][attr];
965 - }
966 - return def;
967 - },
897 + function sortObjectByPriority(object) {
898 + var idx = {};
899 + var sorted = new Array();
900
969 - menuTitle: function(chart) {
970 - if(typeof chart.menu_pattern !== 'undefined') {
971 - return (netdataDashboard.anyAttribute(netdataDashboard.menu, 'title', chart.menu_pattern, chart.menu_pattern).toString()
972 - + '&nbsp;' + chart.type.slice(-(chart.type.length - chart.menu_pattern.length - 1)).toString()).replace(/_/g, ' ');
901 + for(var i in object) {
902 + if(typeof idx[i] === 'undefined') {
903 + idx[i] = object[i];
904 + sorted.push(i);
905 + }
906 }
907
975 - return (netdataDashboard.anyAttribute(netdataDashboard.menu, 'title', chart.menu, chart.menu)).toString().replace(/_/g, ' ');
976 - },
977 -
978 - menuIcon: function(chart) {
979 - if(typeof chart.menu_pattern !== 'undefined')
980 - return netdataDashboard.anyAttribute(netdataDashboard.menu, 'icon', chart.menu_pattern, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>').toString();
908 + sorted.sort(function(a, b) {
909 + if(idx[a].priority < idx[b].priority) return -1;
910 + if(idx[a].priority > idx[b].priority) return 1;
911 + if(a < b) return -1;
912 + return 1;
913 + });
914
982 - return netdataDashboard.anyAttribute(netdataDashboard.menu, 'icon', chart.menu, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>');
983 - },
915 + return sorted;
916 + }
917
985 - menuInfo: function(menu) {
986 - return netdataDashboard.anyAttribute(netdataDashboard.menu, 'info', menu, null);
987 - },
918
989 - menuHeight: function(menu, relative) {
990 - return netdataDashboard.anyAttribute(netdataDashboard.menu, 'height', menu, 1.0) * relative;
991 - },
919 + // ----------------------------------------------------------------------------
920 + // scroll to a section, without changing the browser history
921
993 - submenuTitle: function(menu, submenu) {
994 - var key = menu + '.' + submenu;
995 - var title = netdataDashboard.anyAttribute(netdataDashboard.submenu, 'title', key, submenu).toString().replace(/_/g, ' ');;
996 - if(title.length > 28) {
997 - var a = title.substring(0, 13);
998 - var b = title.substring(title.length - 12, title.length);
999 - return a + '...' + b;
922 + function scrollToId(hash) {
923 + if(hash && hash != '' && document.getElementById(hash) !== null) {
924 + var offset = $('#' + hash).offset();
925 + if(typeof offset !== 'undefined')
926 + $('html, body').animate({ scrollTop: offset.top }, 0);
927 }
1001 - return title;
1002 - },
1003 -
1004 - submenuInfo: function(menu, submenu) {
1005 - var key = menu + '.' + submenu;
1006 - return netdataDashboard.anyAttribute(netdataDashboard.submenu, 'info', key, null);
1007 - },
1008 -
1009 - submenuHeight: function(menu, submenu, relative) {
1010 - var key = menu + '.' + submenu;
1011 - return netdataDashboard.anyAttribute(netdataDashboard.submenu, 'height', key, 1.0) * relative;
1012 - },
1013 -
1014 - contextInfo: function(id) {
1015 - if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].info !== 'undefined')
1016 - return '<div class="chart-message netdata-chart-alignment" role="document">' + netdataDashboard.context[id].info + '</div>';
1017 - else
1018 - return '';
1019 - },
928
1021 - contextValueRange: function(id) {
1022 - if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].valueRange !== 'undefined')
1023 - return netdataDashboard.context[id].valueRange;
1024 - else
1025 - return '[null, null]';
1026 - },
929 + // we must return false to prevent the default action
930 + return false;
931 + }
932
1028 - contextHeight: function(id, def) {
1029 - if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].height !== 'undefined')
1030 - return def * netdataDashboard.context[id].height;
1031 - else
933 + // ----------------------------------------------------------------------------
934 +
935 + var netdataDashboard = {
936 + menu: {},
937 + submenu: {},
938 + context: {},
939 +
940 + gaugeChart: function(title, width, dimensions, colors) {
941 + if(typeof colors === 'undefined')
942 + colors = '';
943 +
944 + if(typeof dimensions === 'undefined')
945 + dimensions = '';
946 +
947 + return '<div data-netdata="CHART_UNIQUE_ID"'
948 + + ' data-dimensions="' + dimensions + '"'
949 + + ' data-chart-library="gauge"'
950 + + ' data-gauge-adjust="width"'
951 + + ' data-title="' + title + '"'
952 + + ' data-width="' + width + '"'
953 + + ' data-before="0"'
954 + + ' data-after="-CHART_DURATION"'
955 + + ' data-points="CHART_DURATION"'
956 + + ' data-colors="' + colors + '"'
957 + + ' role="application"></div>';
958 + },
959 +
960 + anyAttribute: function(obj, attr, key, def) {
961 + if(typeof obj[key] !== 'undefined') {
962 + if(typeof obj[key][attr] !== 'undefined')
963 + return obj[key][attr];
964 + }
965 return def;
1033 - }
1034 - };
1035 -
1036 - // ----------------------------------------------------------------------------
1037 -
1038 - // enrich the data structure returned by netdata
1039 - // to reflect our menu system and content
1040 - function enrichChartData(chart) {
1041 - var tmp = chart.type.split('_')[0];
1042 -
1043 - switch(tmp) {
1044 - case 'ap':
1045 - case 'net':
1046 - case 'disk':
1047 - chart.menu = tmp;
1048 - break;
1049 -
1050 - case 'cgroup':
1051 - chart.menu = chart.type;
1052 - if(chart.id.match(/.*[\._\/-:]qemu[\._\/-:]*/) || chart.id.match(/.*[\._\/-:]kvm[\._\/-:]*/))
1053 - chart.menu_pattern = 'cgqemu';
1054 - else
1055 - chart.menu_pattern = 'cgroup';
1056 - break;
1057 -
1058 - case 'apache':
1059 - case 'exim':
1060 - case 'dovecot':
1061 - case 'hddtemp':
1062 - case 'ipfs':
1063 - case 'memcached':
1064 - case 'mysql':
1065 - case 'named':
1066 - case 'nginx':
1067 - case 'nut':
1068 - case 'phpfpm':
1069 - case 'postfix':
1070 - case 'postgres':
1071 - case 'redis':
1072 - case 'retroshare':
1073 - case 'smawebbox':
1074 - case 'snmp':
1075 - case 'squid':
1076 - case 'tomcat':
1077 - chart.menu = chart.type;
1078 - chart.menu_pattern = tmp;
1079 - break;
1080 -
1081 - case 'tc':
1082 - chart.menu = tmp;
1083 -
1084 - // find a name for this device from fireqos info
1085 - // we strip '_(in|out)' or '(in|out)_'
1086 - if(typeof options.submenu_names[chart.family] === 'undefined' || options.submenu_names[chart.family] === chart.family) {
1087 - var n = chart.name.split('.')[1];
1088 - if(n.endsWith('_in'))
1089 - options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_in'));
1090 - else if(n.endsWith('_out'))
1091 - options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_out'));
1092 - else if(n.startsWith('in_'))
1093 - options.submenu_names[chart.family] = n.slice(3, n.length);
1094 - else if(n.startsWith('out_'))
1095 - options.submenu_names[chart.family] = n.slice(4, n.length);
966 + },
967 +
968 + menuTitle: function(chart) {
969 + if(typeof chart.menu_pattern !== 'undefined') {
970 + return (netdataDashboard.anyAttribute(netdataDashboard.menu, 'title', chart.menu_pattern, chart.menu_pattern).toString()
971 + + '&nbsp;' + chart.type.slice(-(chart.type.length - chart.menu_pattern.length - 1)).toString()).replace(/_/g, ' ');
972 }
973
1098 - // increase the priority of IFB devices
1099 - // to have inbound appear before outbound
1100 - if(chart.id.match(/.*-ifb$/))
1101 - chart.priority--;
974 + return (netdataDashboard.anyAttribute(netdataDashboard.menu, 'title', chart.menu, chart.menu)).toString().replace(/_/g, ' ');
975 + },
976
1103 - break;
977 + menuIcon: function(chart) {
978 + if(typeof chart.menu_pattern !== 'undefined')
979 + return netdataDashboard.anyAttribute(netdataDashboard.menu, 'icon', chart.menu_pattern, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>').toString();
980
1105 - default:
1106 - chart.menu = chart.type;
1107 - break;
1108 - }
981 + return netdataDashboard.anyAttribute(netdataDashboard.menu, 'icon', chart.menu, '<i class="fa fa-puzzle-piece" aria-hidden="true"></i>');
982 + },
983
1110 - chart.submenu = chart.family;
1111 - }
984 + menuInfo: function(menu) {
985 + return netdataDashboard.anyAttribute(netdataDashboard.menu, 'info', menu, null);
986 + },
987
1113 - // ----------------------------------------------------------------------------
1114 -
1115 - function headMain(charts, duration) {
1116 - var head = '';
1117 -
1118 - if(typeof charts['system.swap'] !== 'undefined')
1119 - head += '<div style="margin-right: 10px;" data-netdata="system.swap"'
1120 - + ' data-dimensions="used"'
1121 - + ' data-append-options="percentage"'
1122 - + ' data-chart-library="easypiechart"'
1123 - + ' data-title="Used Swap"'
1124 - + ' data-units="%"'
1125 - + ' data-easypiechart-max-value="100"'
1126 - + ' data-width="8%"'
1127 - + ' data-before="0"'
1128 - + ' data-after="-' + duration.toString() + '"'
1129 - + ' data-points="' + duration.toString() + '"'
1130 - + ' data-colors="#DD4400"'
1131 - + ' role="application"></div>';
1132 -
1133 - if(typeof charts['system.io'] !== 'undefined') {
1134 - head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1135 - + ' data-dimensions="in"'
1136 - + ' data-chart-library="easypiechart"'
1137 - + ' data-title="Disk Read"'
1138 - + ' data-width="10%"'
1139 - + ' data-before="0"'
1140 - + ' data-after="-' + duration.toString() + '"'
1141 - + ' data-points="' + duration.toString() + '"'
1142 - + ' role="application"></div>';
1143 -
1144 - head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1145 - + ' data-dimensions="out"'
1146 - + ' data-chart-library="easypiechart"'
1147 - + ' data-title="Disk Write"'
1148 - + ' data-width="10%"'
1149 - + ' data-before="0"'
1150 - + ' data-after="-' + duration.toString() + '"'
1151 - + ' data-points="' + duration.toString() + '"'
1152 - + ' role="application"></div>';
1153 - }
988 + menuHeight: function(menu, relative) {
989 + return netdataDashboard.anyAttribute(netdataDashboard.menu, 'height', menu, 1.0) * relative;
990 + },
991
1155 - if(typeof charts['system.cpu'] !== 'undefined')
1156 - head += '<div data-netdata="system.cpu"'
1157 - + ' data-chart-library="gauge"'
1158 - + ' data-title="CPU"'
1159 - + ' data-units="%"'
1160 - + ' data-gauge-max-value="100"'
1161 - + ' data-width="18%"'
1162 - + ' data-after="-' + duration.toString() + '"'
1163 - + ' data-points="' + duration.toString() + '"'
1164 - + ' data-colors="' + NETDATA.colors[12] + '"'
1165 - + ' role="application"></div>';
1166 -
1167 - if(typeof charts['system.ipv4'] !== 'undefined') {
1168 - head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1169 - + ' data-dimensions="received"'
1170 - + ' data-chart-library="easypiechart"'
1171 - + ' data-title="IPv4 Inbound"'
1172 - + ' data-width="10%"'
1173 - + ' data-before="0"'
1174 - + ' data-after="-' + duration.toString() + '"'
1175 - + ' data-points="' + duration.toString() + '"'
1176 - + ' role="application"></div>';
1177 -
1178 - head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1179 - + ' data-dimensions="sent"'
1180 - + ' data-chart-library="easypiechart"'
1181 - + ' data-title="IPv4 Outbound"'
1182 - + ' data-width="10%"'
1183 - + ' data-before="0"'
1184 - + ' data-after="-' + duration.toString() + '"'
1185 - + ' data-points="' + duration.toString() + '"'
1186 - + ' role="application"></div>';
1187 - }
1188 - else if(typeof charts['system.ipv6'] !== 'undefined') {
1189 - head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"'
1190 - + ' data-dimensions="received"'
1191 - + ' data-chart-library="easypiechart"'
1192 - + ' data-title="IPv6 Inbound"'
1193 - + ' data-units="kbps"'
1194 - + ' data-width="10%"'
1195 - + ' data-before="0"'
1196 - + ' data-after="-' + duration.toString() + '"'
1197 - + ' data-points="' + duration.toString() + '"'
1198 - + ' role="application"></div>';
1199 -
1200 - head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"'
1201 - + ' data-dimensions="sent"'
1202 - + ' data-chart-library="easypiechart"'
1203 - + ' data-title="IPv6 Outbound"'
1204 - + ' data-units="kbps"'
1205 - + ' data-width="10%"'
1206 - + ' data-before="0"'
1207 - + ' data-after="-' + duration.toString() + '"'
1208 - + ' data-points="' + duration.toString() + '"'
1209 - + ' role="application"></div>';
1210 - }
992 + submenuTitle: function(menu, submenu) {
993 + var key = menu + '.' + submenu;
994 + var title = netdataDashboard.anyAttribute(netdataDashboard.submenu, 'title', key, submenu).toString().replace(/_/g, ' ');;
995 + if(title.length > 28) {
996 + var a = title.substring(0, 13);
997 + var b = title.substring(title.length - 12, title.length);
998 + return a + '...' + b;
999 + }
1000 + return title;
1001 + },
1002 +
1003 + submenuInfo: function(menu, submenu) {
1004 + var key = menu + '.' + submenu;
1005 + return netdataDashboard.anyAttribute(netdataDashboard.submenu, 'info', key, null);
1006 + },
1007 +
1008 + submenuHeight: function(menu, submenu, relative) {
1009 + var key = menu + '.' + submenu;
1010 + return netdataDashboard.anyAttribute(netdataDashboard.submenu, 'height', key, 1.0) * relative;
1011 + },
1012 +
1013 + contextInfo: function(id) {
1014 + if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].info !== 'undefined')
1015 + return '<div class="chart-message netdata-chart-alignment" role="document">' + netdataDashboard.context[id].info + '</div>';
1016 + else
1017 + return '';
1018 + },
1019
1212 - if(typeof charts['system.ram'] !== 'undefined')
1213 - head += '<div style="margin-right: 10px;" data-netdata="system.ram"'
1214 - + ' data-dimensions="used|buffers|active|wired"' // active and wired are FreeBSD stats
1215 - + ' data-append-options="percentage"'
1216 - + ' data-chart-library="easypiechart"'
1217 - + ' data-title="Used RAM"'
1218 - + ' data-units="%"'
1219 - + ' data-easypiechart-max-value="100"'
1220 - + ' data-width="8%"'
1221 - + ' data-after="-' + duration.toString() + '"'
1222 - + ' data-points="' + duration.toString() + '"'
1223 - + ' data-colors="' + NETDATA.colors[7] + '"'
1224 - + ' role="application"></div>';
1225 -
1226 - return head;
1227 - }
1020 + contextValueRange: function(id) {
1021 + if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].valueRange !== 'undefined')
1022 + return netdataDashboard.context[id].valueRange;
1023 + else
1024 + return '[null, null]';
1025 + },
1026
1229 - function generateHeadCharts(type, chart, duration) {
1230 - var head = '';
1231 - var hcharts = netdataDashboard.anyAttribute(netdataDashboard.context, type, chart.context, []);
1232 - if(hcharts.length > 0) {
1233 - var hi = 0, hlen = hcharts.length;
1234 - while(hi < hlen) {
1235 - if(typeof hcharts[hi] === 'function')
1236 - head += hcharts[hi](chart.id).replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id);
1027 + contextHeight: function(id, def) {
1028 + if(typeof netdataDashboard.context[id] !== 'undefined' && typeof netdataDashboard.context[id].height !== 'undefined')
1029 + return def * netdataDashboard.context[id].height;
1030 else
1238 - head += hcharts[hi].replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id);
1239 - hi++;
1031 + return def;
1032 }
1241 - }
1242 - return head;
1243 - }
1033 + };
1034
1245 - function renderPage(menus, data) {
1246 - var div = document.getElementById('charts_div');
1247 - var pcent_width = Math.floor(100 / chartsPerRow($(div).width()));
1248 -
1249 - // find the proper duration for per-second updates
1250 - var duration = Math.round(($(div).width() * pcent_width / 100 * data.update_every / 3) / 60) * 60;
1251 - var html = '';
1252 - var sidebar = '<ul class="nav dashboard-sidenav" data-spy="affix" id="sidebar_ul">';
1253 - var mainhead = headMain(data.charts, duration);
1254 -
1255 - // sort the menus
1256 - var main = sortObjectByPriority(menus);
1257 - var i = 0, len = main.length;
1258 - while(i < len) {
1259 - var menu = main[i++];
1260 -
1261 - // generate an entry at the main menu
1262 -
1263 - var menuid = NETDATA.name2id('menu_' + menu);
1264 - sidebar += '<li class=""><a href="#' + menuid + '" onClick="return scrollToId(\'' + menuid + '\');">' + menus[menu].icon + ' ' + menus[menu].title + '</a><ul class="nav">';
1265 - html += '<div role="section"><div role="sectionhead"><h1 id="' + menuid + '" role="heading">' + menus[menu].title + '</h1></div><div role="document">';
1266 -
1267 - if(menus[menu].info !== null)
1268 - html += menus[menu].info;
1269 -
1270 - // console.log(' >> ' + menu + ' (' + menus[menu].priority + '): ' + menus[menu].title);
1271 -
1272 - var shtml = '';
1273 - var mhead = '<div class="netdata-chart-row">' + mainhead;
1274 - mainhead = '';
1275 -
1276 - // sort the submenus of this menu
1277 - var sub = sortObjectByPriority(menus[menu].submenus);
1278 - var si = 0, slen = sub.length;
1279 - while(si < slen) {
1280 - var submenu = sub[si++];
1281 -
1282 - // generate an entry at the submenu
1283 - var submenuid = NETDATA.name2id('menu_' + menu + '_submenu_' + submenu);
1284 - sidebar += '<li class><a href="#' + submenuid + '" onClick="return scrollToId(\'' + submenuid + '\');">' + menus[menu].submenus[submenu].title + '</a></li>';
1285 - shtml += '<div class="netdata-group-container" id="' + submenuid + '" style="display: inline-block; width: ' + pcent_width.toString() + '%"><h2 id="' + submenuid + '" class="netdata-chart-alignment" role="heading">' + menus[menu].submenus[submenu].title + '</h2>';
1286 -
1287 - if(menus[menu].submenus[submenu].info !== null)
1288 - shtml += '<div class="chart-message netdata-chart-alignment" role="document">' + menus[menu].submenus[submenu].info + '</div>';
1289 -
1290 - var head = '<div class="netdata-chart-row">';
1291 - var chtml = '';
1292 -
1293 - // console.log(' \------- ' + submenu + ' (' + menus[menu].submenus[submenu].priority + '): ' + menus[menu].submenus[submenu].title);
1294 -
1295 - // sort the charts in this submenu of this menu
1296 - menus[menu].submenus[submenu].charts.sort(prioritySort);
1297 - var ci = 0, clen = menus[menu].submenus[submenu].charts.length;
1298 - while(ci < clen) {
1299 - var chart = menus[menu].submenus[submenu].charts[ci++];
1300 -
1301 - // generate the submenu heading charts
1302 - mhead += generateHeadCharts('mainheads', chart, duration);
1303 - head += generateHeadCharts('heads', chart, duration);
1304 -
1305 - // generate the chart
1306 - chtml += netdataDashboard.contextInfo(chart.context) + '<div id="chart_' + NETDATA.name2id(chart.id) + '" data-netdata="' + chart.id + '"'
1307 - + ' data-width="' + pcent_width.toString() + '%"'
1308 - + ' data-height="' + netdataDashboard.contextHeight(chart.context, options.chartsHeight).toString() + 'px"'
1309 - + ' data-dygraph-valuerange="' + netdataDashboard.contextValueRange(chart.context) + '"'
1310 - + ' data-before="0"'
1311 - + ' data-after="-' + duration.toString() + '"'
1312 - + ' data-id="' + NETDATA.name2id(options.hostname + '/' + chart.id) + '"'
1313 - + ' data-colors="' + netdataDashboard.anyAttribute(netdataDashboard.context, 'colors', chart.context, '') + '"'
1314 - + ' role="application"></div>';
1315 -
1316 - // console.log(' \------- ' + chart.id + ' (' + chart.priority + '): ' + chart.context + ' height: ' + menus[menu].submenus[submenu].height);
1317 - }
1035 + // ----------------------------------------------------------------------------
1036
1319 - head += '</div>';
1320 - shtml += head + chtml + '</div>';
1321 - }
1037 + // enrich the data structure returned by netdata
1038 + // to reflect our menu system and content
1039 + function enrichChartData(chart) {
1040 + var tmp = chart.type.split('_')[0];
1041
1323 - mhead += '</div>';
1324 - sidebar += '</ul></li>';
1325 - html += mhead + shtml + '</div></div><hr role="separator"/>';
1326 - }
1042 + switch(tmp) {
1043 + case 'ap':
1044 + case 'net':
1045 + case 'disk':
1046 + chart.menu = tmp;
1047 + break;
1048
1328 - sidebar += '<li class="" style="padding-top:15px;"><a href="https://github.com/firehol/netdata/wiki/Add-more-charts-to-netdata" target="_blank"><i class="fa fa-plus" aria-hidden="true"></i> add more charts</a></li>';
1329 - sidebar += '<li class=""><a href="https://github.com/firehol/netdata/wiki/Add-more-alarms-to-netdata" target="_blank"><i class="fa fa-plus" aria-hidden="true"></i> add more alarms</a></li>';
1330 - 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 ' + Math.round(data.history / 3600).toLocaleString() + ' ' + ((data.history == 3600)?'hour':'hours').toString() + ' of real-time history.</small></li>';
1331 - sidebar += '</ul>';
1332 - div.innerHTML = html;
1333 - document.getElementById('sidebar').innerHTML = sidebar;
1334 - finalizePage();
1335 - }
1049 + case 'cgroup':
1050 + chart.menu = chart.type;
1051 + if(chart.id.match(/.*[\._\/-:]qemu[\._\/-:]*/) || chart.id.match(/.*[\._\/-:]kvm[\._\/-:]*/))
1052 + chart.menu_pattern = 'cgqemu';
1053 + else
1054 + chart.menu_pattern = 'cgroup';
1055 + break;
1056 +
1057 + case 'apache':
1058 + case 'exim':
1059 + case 'dovecot':
1060 + case 'hddtemp':
1061 + case 'ipfs':
1062 + case 'memcached':
1063 + case 'mysql':
1064 + case 'named':
1065 + case 'nginx':
1066 + case 'nut':
1067 + case 'phpfpm':
1068 + case 'postfix':
1069 + case 'postgres':
1070 + case 'redis':
1071 + case 'retroshare':
1072 + case 'smawebbox':
1073 + case 'snmp':
1074 + case 'squid':
1075 + case 'tomcat':
1076 + chart.menu = chart.type;
1077 + chart.menu_pattern = tmp;
1078 + break;
1079 +
1080 + case 'tc':
1081 + chart.menu = tmp;
1082 +
1083 + // find a name for this device from fireqos info
1084 + // we strip '_(in|out)' or '(in|out)_'
1085 + if(typeof options.submenu_names[chart.family] === 'undefined' || options.submenu_names[chart.family] === chart.family) {
1086 + var n = chart.name.split('.')[1];
1087 + if(n.endsWith('_in'))
1088 + options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_in'));
1089 + else if(n.endsWith('_out'))
1090 + options.submenu_names[chart.family] = n.slice(0, n.lastIndexOf('_out'));
1091 + else if(n.startsWith('in_'))
1092 + options.submenu_names[chart.family] = n.slice(3, n.length);
1093 + else if(n.startsWith('out_'))
1094 + options.submenu_names[chart.family] = n.slice(4, n.length);
1095 + }
1096
1337 - function renderChartsAndMenu(data) {
1338 - var menus = options.menus;
1339 - var charts = data.charts;
1340 -
1341 - for(var c in charts) {
1342 - enrichChartData(charts[c]);
1343 -
1344 - // create the menu
1345 - if(typeof menus[charts[c].menu] === 'undefined') {
1346 - menus[charts[c].menu] = {
1347 - priority: charts[c].priority,
1348 - submenus: {},
1349 - title: netdataDashboard.menuTitle(charts[c]),
1350 - icon: netdataDashboard.menuIcon(charts[c]),
1351 - info: netdataDashboard.menuInfo(charts[c].menu),
1352 - height: netdataDashboard.menuHeight(charts[c].menu, options.chartsHeight)
1353 - };
1097 + // increase the priority of IFB devices
1098 + // to have inbound appear before outbound
1099 + if(chart.id.match(/.*-ifb$/))
1100 + chart.priority--;
1101 +
1102 + break;
1103 +
1104 + default:
1105 + chart.menu = chart.type;
1106 + break;
1107 }
1108
1356 - if(charts[c].priority < menus[charts[c].menu].priority)
1357 - menus[charts[c].menu].priority = charts[c].priority;
1358 -
1359 - // create the submenu
1360 - if(typeof menus[charts[c].menu].submenus[charts[c].submenu] === 'undefined') {
1361 - menus[charts[c].menu].submenus[charts[c].submenu] = {
1362 - priority: charts[c].priority,
1363 - charts: new Array(),
1364 - title: null,
1365 - info: netdataDashboard.submenuInfo(charts[c].menu, charts[c].submenu),
1366 - height: netdataDashboard.submenuHeight(charts[c].menu, charts[c].submenu, menus[charts[c].menu].height)
1367 - };
1109 + chart.submenu = chart.family;
1110 + }
1111 +
1112 + // ----------------------------------------------------------------------------
1113 +
1114 + function headMain(charts, duration) {
1115 + var head = '';
1116 +
1117 + if(typeof charts['system.swap'] !== 'undefined')
1118 + head += '<div style="margin-right: 10px;" data-netdata="system.swap"'
1119 + + ' data-dimensions="used"'
1120 + + ' data-append-options="percentage"'
1121 + + ' data-chart-library="easypiechart"'
1122 + + ' data-title="Used Swap"'
1123 + + ' data-units="%"'
1124 + + ' data-easypiechart-max-value="100"'
1125 + + ' data-width="8%"'
1126 + + ' data-before="0"'
1127 + + ' data-after="-' + duration.toString() + '"'
1128 + + ' data-points="' + duration.toString() + '"'
1129 + + ' data-colors="#DD4400"'
1130 + + ' role="application"></div>';
1131 +
1132 + if(typeof charts['system.io'] !== 'undefined') {
1133 + head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1134 + + ' data-dimensions="in"'
1135 + + ' data-chart-library="easypiechart"'
1136 + + ' data-title="Disk Read"'
1137 + + ' data-width="10%"'
1138 + + ' data-before="0"'
1139 + + ' data-after="-' + duration.toString() + '"'
1140 + + ' data-points="' + duration.toString() + '"'
1141 + + ' role="application"></div>';
1142 +
1143 + head += '<div style="margin-right: 10px;" data-netdata="system.io"'
1144 + + ' data-dimensions="out"'
1145 + + ' data-chart-library="easypiechart"'
1146 + + ' data-title="Disk Write"'
1147 + + ' data-width="10%"'
1148 + + ' data-before="0"'
1149 + + ' data-after="-' + duration.toString() + '"'
1150 + + ' data-points="' + duration.toString() + '"'
1151 + + ' role="application"></div>';
1152 }
1153
1370 - if(charts[c].priority < menus[charts[c].menu].submenus[charts[c].submenu].priority)
1371 - menus[charts[c].menu].submenus[charts[c].submenu].priority = charts[c].priority;
1154 + if(typeof charts['system.cpu'] !== 'undefined')
1155 + head += '<div data-netdata="system.cpu"'
1156 + + ' data-chart-library="gauge"'
1157 + + ' data-title="CPU"'
1158 + + ' data-units="%"'
1159 + + ' data-gauge-max-value="100"'
1160 + + ' data-width="18%"'
1161 + + ' data-after="-' + duration.toString() + '"'
1162 + + ' data-points="' + duration.toString() + '"'
1163 + + ' data-colors="' + NETDATA.colors[12] + '"'
1164 + + ' role="application"></div>';
1165 +
1166 + if(typeof charts['system.ipv4'] !== 'undefined') {
1167 + head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1168 + + ' data-dimensions="received"'
1169 + + ' data-chart-library="easypiechart"'
1170 + + ' data-title="IPv4 Inbound"'
1171 + + ' data-width="10%"'
1172 + + ' data-before="0"'
1173 + + ' data-after="-' + duration.toString() + '"'
1174 + + ' data-points="' + duration.toString() + '"'
1175 + + ' role="application"></div>';
1176 +
1177 + head += '<div style="margin-right: 10px;" data-netdata="system.ipv4"'
1178 + + ' data-dimensions="sent"'
1179 + + ' data-chart-library="easypiechart"'
1180 + + ' data-title="IPv4 Outbound"'
1181 + + ' data-width="10%"'
1182 + + ' data-before="0"'
1183 + + ' data-after="-' + duration.toString() + '"'
1184 + + ' data-points="' + duration.toString() + '"'
1185 + + ' role="application"></div>';
1186 + }
1187 + else if(typeof charts['system.ipv6'] !== 'undefined') {
1188 + head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"'
1189 + + ' data-dimensions="received"'
1190 + + ' data-chart-library="easypiechart"'
1191 + + ' data-title="IPv6 Inbound"'
1192 + + ' data-units="kbps"'
1193 + + ' data-width="10%"'
1194 + + ' data-before="0"'
1195 + + ' data-after="-' + duration.toString() + '"'
1196 + + ' data-points="' + duration.toString() + '"'
1197 + + ' role="application"></div>';
1198 +
1199 + head += '<div style="margin-right: 10px;" data-netdata="system.ipv6"'
1200 + + ' data-dimensions="sent"'
1201 + + ' data-chart-library="easypiechart"'
1202 + + ' data-title="IPv6 Outbound"'
1203 + + ' data-units="kbps"'
1204 + + ' data-width="10%"'
1205 + + ' data-before="0"'
1206 + + ' data-after="-' + duration.toString() + '"'
1207 + + ' data-points="' + duration.toString() + '"'
1208 + + ' role="application"></div>';
1209 + }
1210
1373 - // index the chart in the menu/submenu
1374 - menus[charts[c].menu].submenus[charts[c].submenu].charts.push(charts[c]);
1211 + if(typeof charts['system.ram'] !== 'undefined')
1212 + head += '<div style="margin-right: 10px;" data-netdata="system.ram"'
1213 + + ' data-dimensions="used|buffers|active|wired"' // active and wired are FreeBSD stats
1214 + + ' data-append-options="percentage"'
1215 + + ' data-chart-library="easypiechart"'
1216 + + ' data-title="Used RAM"'
1217 + + ' data-units="%"'
1218 + + ' data-easypiechart-max-value="100"'
1219 + + ' data-width="8%"'
1220 + + ' data-after="-' + duration.toString() + '"'
1221 + + ' data-points="' + duration.toString() + '"'
1222 + + ' data-colors="' + NETDATA.colors[7] + '"'
1223 + + ' role="application"></div>';
1224 +
1225 + return head;
1226 }
1227
1377 - // propagate the descriptive subname given to QoS
1378 - // to all the other submenus with the same name
1379 - for(var m in menus) {
1380 - for(var s in menus[m].submenus) {
1381 - // set the family using a name
1382 - if(typeof options.submenu_names[s] !== 'undefined') {
1383 - menus[m].submenus[s].title = s + ' (' + options.submenu_names[s] + ')';
1384 - }
1385 - else {
1386 - menus[m].submenus[s].title = netdataDashboard.submenuTitle(m, s);
1228 + function generateHeadCharts(type, chart, duration) {
1229 + var head = '';
1230 + var hcharts = netdataDashboard.anyAttribute(netdataDashboard.context, type, chart.context, []);
1231 + if(hcharts.length > 0) {
1232 + var hi = 0, hlen = hcharts.length;
1233 + while(hi < hlen) {
1234 + if(typeof hcharts[hi] === 'function')
1235 + head += hcharts[hi](chart.id).replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id);
1236 + else
1237 + head += hcharts[hi].replace('CHART_DURATION', duration.toString()).replace('CHART_UNIQUE_ID', chart.id);
1238 + hi++;
1239 }
1240 }
1241 + return head;
1242 }
1243
1391 - renderPage(menus, data);
1392 - }
1244 + function renderPage(menus, data) {
1245 + var div = document.getElementById('charts_div');
1246 + var pcent_width = Math.floor(100 / chartsPerRow($(div).width()));
1247 +
1248 + // find the proper duration for per-second updates
1249 + var duration = Math.round(($(div).width() * pcent_width / 100 * data.update_every / 3) / 60) * 60;
1250 + var html = '';
1251 + var sidebar = '<ul class="nav dashboard-sidenav" data-spy="affix" id="sidebar_ul">';
1252 + var mainhead = headMain(data.charts, duration);
1253 +
1254 + // sort the menus
1255 + var main = sortObjectByPriority(menus);
1256 + var i = 0, len = main.length;
1257 + while(i < len) {
1258 + var menu = main[i++];
1259 +
1260 + // generate an entry at the main menu
1261 +
1262 + var menuid = NETDATA.name2id('menu_' + menu);
1263 + sidebar += '<li class=""><a href="#' + menuid + '" onClick="return scrollToId(\'' + menuid + '\');">' + menus[menu].icon + ' ' + menus[menu].title + '</a><ul class="nav">';
1264 + html += '<div role="section"><div role="sectionhead"><h1 id="' + menuid + '" role="heading">' + menus[menu].title + '</h1></div><div role="document">';
1265 +
1266 + if(menus[menu].info !== null)
1267 + html += menus[menu].info;
1268 +
1269 + // console.log(' >> ' + menu + ' (' + menus[menu].priority + '): ' + menus[menu].title);
1270 +
1271 + var shtml = '';
1272 + var mhead = '<div class="netdata-chart-row">' + mainhead;
1273 + mainhead = '';
1274 +
1275 + // sort the submenus of this menu
1276 + var sub = sortObjectByPriority(menus[menu].submenus);
1277 + var si = 0, slen = sub.length;
1278 + while(si < slen) {
1279 + var submenu = sub[si++];
1280 +
1281 + // generate an entry at the submenu
1282 + var submenuid = NETDATA.name2id('menu_' + menu + '_submenu_' + submenu);
1283 + sidebar += '<li class><a href="#' + submenuid + '" onClick="return scrollToId(\'' + submenuid + '\');">' + menus[menu].submenus[submenu].title + '</a></li>';
1284 + shtml += '<div class="netdata-group-container" id="' + submenuid + '" style="display: inline-block; width: ' + pcent_width.toString() + '%"><h2 id="' + submenuid + '" class="netdata-chart-alignment" role="heading">' + menus[menu].submenus[submenu].title + '</h2>';
1285 +
1286 + if(menus[menu].submenus[submenu].info !== null)
1287 + shtml += '<div class="chart-message netdata-chart-alignment" role="document">' + menus[menu].submenus[submenu].info + '</div>';
1288 +
1289 + var head = '<div class="netdata-chart-row">';
1290 + var chtml = '';
1291 +
1292 + // console.log(' \------- ' + submenu + ' (' + menus[menu].submenus[submenu].priority + '): ' + menus[menu].submenus[submenu].title);
1293 +
1294 + // sort the charts in this submenu of this menu
1295 + menus[menu].submenus[submenu].charts.sort(prioritySort);
1296 + var ci = 0, clen = menus[menu].submenus[submenu].charts.length;
1297 + while(ci < clen) {
1298 + var chart = menus[menu].submenus[submenu].charts[ci++];
1299 +
1300 + // generate the submenu heading charts
1301 + mhead += generateHeadCharts('mainheads', chart, duration);
1302 + head += generateHeadCharts('heads', chart, duration);
1303 +
1304 + // generate the chart
1305 + chtml += netdataDashboard.contextInfo(chart.context) + '<div id="chart_' + NETDATA.name2id(chart.id) + '" data-netdata="' + chart.id + '"'
1306 + + ' data-width="' + pcent_width.toString() + '%"'
1307 + + ' data-height="' + netdataDashboard.contextHeight(chart.context, options.chartsHeight).toString() + 'px"'
1308 + + ' data-dygraph-valuerange="' + netdataDashboard.contextValueRange(chart.context) + '"'
1309 + + ' data-before="0"'
1310 + + ' data-after="-' + duration.toString() + '"'
1311 + + ' data-id="' + NETDATA.name2id(options.hostname + '/' + chart.id) + '"'
1312 + + ' data-colors="' + netdataDashboard.anyAttribute(netdataDashboard.context, 'colors', chart.context, '') + '"'
1313 + + ' role="application"></div>';
1314 +
1315 + // console.log(' \------- ' + chart.id + ' (' + chart.priority + '): ' + chart.context + ' height: ' + menus[menu].submenus[submenu].height);
1316 + }
1317
1394 - // ----------------------------------------------------------------------------
1395 -
1396 - function loadJs(url, callback) {
1397 - $.ajax({
1398 - url: url,
1399 - cache: true,
1400 - dataType: "script",
1401 - xhrFields: { withCredentials: true } // required for the cookie
1402 - })
1403 - .fail(function() {
1404 - alert('Cannot load required JS library: ' + url);
1405 - })
1406 - .always(function() {
1407 - if(typeof callback === 'function')
1408 - callback();
1409 - })
1410 - }
1318 + head += '</div>';
1319 + shtml += head + chtml + '</div>';
1320 + }
1321
1412 - var bootstrapTableLoaded = false;
1413 - function loadBootstrapTable(callback) {
1414 - if(bootstrapTableLoaded === false) {
1415 - bootstrapTableLoaded === true;
1416 - loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-1.11.0.min.js', function() {
1417 - loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-export-1.11.0.min.js', function() {
1418 - loadJs(NETDATA.serverDefault + 'lib/tableExport-1.6.0.min.js', callback);
1419 - })
1420 - });
1322 + mhead += '</div>';
1323 + sidebar += '</ul></li>';
1324 + html += mhead + shtml + '</div></div><hr role="separator"/>';
1325 + }
1326 +
1327 + sidebar += '<li class="" style="padding-top:15px;"><a href="https://github.com/firehol/netdata/wiki/Add-more-charts-to-netdata" target="_blank"><i class="fa fa-plus" aria-hidden="true"></i> add more charts</a></li>';
1328 + sidebar += '<li class=""><a href="https://github.com/firehol/netdata/wiki/Add-more-alarms-to-netdata" target="_blank"><i class="fa fa-plus" aria-hidden="true"></i> add more alarms</a></li>';
1329 + 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 ' + Math.round(data.history / 3600).toLocaleString() + ' ' + ((data.history == 3600)?'hour':'hours').toString() + ' of real-time history.</small></li>';
1330 + sidebar += '</ul>';
1331 + div.innerHTML = html;
1332 + document.getElementById('sidebar').innerHTML = sidebar;
1333 + finalizePage();
1334 }
1422 - else callback();
1423 - }
1335
1425 - function alarmsUpdateModal() {
1426 - var active = '<h3>Raised Alarms</h3><table class="table">';
1427 - var all = '<h3>All Running Alarms</h3><div class="panel-group" id="alarms_all_accordion" role="tablist" aria-multiselectable="true">';
1428 - var footer = '<hr/><a href="https://github.com/firehol/netdata/wiki/Generating-Badges" target="_blank">netdata badges</a> refresh automatically. Their color indicates the state of the alarm: <span style="color: #e05d44"><b>&nbsp;red&nbsp;</b></span> is critical, <span style="color:#fe7d37"><b>&nbsp;orange&nbsp;</b></span> is warning, <span style="color: #4c1"><b>&nbsp;bright green&nbsp;</b></span> is ok, <span style="color: #9f9f9f"><b>&nbsp;light grey&nbsp;</b></span> is undefined (i.e. no data or no status), <span style="color: #000"><b>&nbsp;black&nbsp;</b></span> is not initialized. You can copy and paste their URLs to embed them in any web page.<br/>netdata can send notifications for these alarms. Check <a href="https://github.com/firehol/netdata/blob/master/conf.d/health_alarm_notify.conf">this configuration file</a> for more information.';
1336 + function renderChartsAndMenu(data) {
1337 + var menus = options.menus;
1338 + var charts = data.charts;
1339 +
1340 + for(var c in charts) {
1341 + enrichChartData(charts[c]);
1342 +
1343 + // create the menu
1344 + if(typeof menus[charts[c].menu] === 'undefined') {
1345 + menus[charts[c].menu] = {
1346 + priority: charts[c].priority,
1347 + submenus: {},
1348 + title: netdataDashboard.menuTitle(charts[c]),
1349 + icon: netdataDashboard.menuIcon(charts[c]),
1350 + info: netdataDashboard.menuInfo(charts[c].menu),
1351 + height: netdataDashboard.menuHeight(charts[c].menu, options.chartsHeight)
1352 + };
1353 + }
1354
1430 - NETDATA.alarms.get('all', function(data) {
1431 - options.alarm_families = new Array();
1355 + if(charts[c].priority < menus[charts[c].menu].priority)
1356 + menus[charts[c].menu].priority = charts[c].priority;
1357 +
1358 + // create the submenu
1359 + if(typeof menus[charts[c].menu].submenus[charts[c].submenu] === 'undefined') {
1360 + menus[charts[c].menu].submenus[charts[c].submenu] = {
1361 + priority: charts[c].priority,
1362 + charts: new Array(),
1363 + title: null,
1364 + info: netdataDashboard.submenuInfo(charts[c].menu, charts[c].submenu),
1365 + height: netdataDashboard.submenuHeight(charts[c].menu, charts[c].submenu, menus[charts[c].menu].height)
1366 + };
1367 + }
1368
1433 - alarmsCallback(data);
1369 + if(charts[c].priority < menus[charts[c].menu].submenus[charts[c].submenu].priority)
1370 + menus[charts[c].menu].submenus[charts[c].submenu].priority = charts[c].priority;
1371
1435 - if(data === null) {
1436 - document.getElementById('alarms_active').innerHTML =
1437 - document.getElementById('alarms_all').innerHTML =
1438 - document.getElementById('alarms_log').innerHTML =
1439 - 'failed to load alarm data!';
1440 - return;
1372 + // index the chart in the menu/submenu
1373 + menus[charts[c].menu].submenus[charts[c].submenu].charts.push(charts[c]);
1374 }
1375
1443 - function alarmid4human(id) {
1444 - if(id === 0)
1445 - return '-';
1446 -
1447 - return id.toString();
1376 + // propagate the descriptive subname given to QoS
1377 + // to all the other submenus with the same name
1378 + for(var m in menus) {
1379 + for(var s in menus[m].submenus) {
1380 + // set the family using a name
1381 + if(typeof options.submenu_names[s] !== 'undefined') {
1382 + menus[m].submenus[s].title = s + ' (' + options.submenu_names[s] + ')';
1383 + }
1384 + else {
1385 + menus[m].submenus[s].title = netdataDashboard.submenuTitle(m, s);
1386 + }
1387 + }
1388 }
1389
1450 - function timestamp4human(timestamp, space) {
1451 - if(timestamp === 0)
1452 - return '-';
1390 + renderPage(menus, data);
1391 + }
1392
1454 - if(typeof space === 'undefined')
1455 - space = '&nbsp;';
1393 + // ----------------------------------------------------------------------------
1394 +
1395 + function loadJs(url, callback) {
1396 + $.ajax({
1397 + url: url,
1398 + cache: true,
1399 + dataType: "script",
1400 + xhrFields: { withCredentials: true } // required for the cookie
1401 + })
1402 + .fail(function() {
1403 + alert('Cannot load required JS library: ' + url);
1404 + })
1405 + .always(function() {
1406 + if(typeof callback === 'function')
1407 + callback();
1408 + })
1409 + }
1410
1457 - var t = new Date(timestamp * 1000);
1458 - var now = new Date();
1411 + var bootstrapTableLoaded = false;
1412 + function loadBootstrapTable(callback) {
1413 + if(bootstrapTableLoaded === false) {
1414 + bootstrapTableLoaded === true;
1415 + loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-1.11.0.min.js', function() {
1416 + loadJs(NETDATA.serverDefault + 'lib/bootstrap-table-export-1.11.0.min.js', function() {
1417 + loadJs(NETDATA.serverDefault + 'lib/tableExport-1.6.0.min.js', callback);
1418 + })
1419 + });
1420 + }
1421 + else callback();
1422 + }
1423
1460 - if(t.toDateString() == now.toDateString())
1461 - return t.toLocaleTimeString();
1424 + function alarmsUpdateModal() {
1425 + var active = '<h3>Raised Alarms</h3><table class="table">';
1426 + var all = '<h3>All Running Alarms</h3><div class="panel-group" id="alarms_all_accordion" role="tablist" aria-multiselectable="true">';
1427 + var footer = '<hr/><a href="https://github.com/firehol/netdata/wiki/Generating-Badges" target="_blank">netdata badges</a> refresh automatically. Their color indicates the state of the alarm: <span style="color: #e05d44"><b>&nbsp;red&nbsp;</b></span> is critical, <span style="color:#fe7d37"><b>&nbsp;orange&nbsp;</b></span> is warning, <span style="color: #4c1"><b>&nbsp;bright green&nbsp;</b></span> is ok, <span style="color: #9f9f9f"><b>&nbsp;light grey&nbsp;</b></span> is undefined (i.e. no data or no status), <span style="color: #000"><b>&nbsp;black&nbsp;</b></span> is not initialized. You can copy and paste their URLs to embed them in any web page.<br/>netdata can send notifications for these alarms. Check <a href="https://github.com/firehol/netdata/blob/master/conf.d/health_alarm_notify.conf">this configuration file</a> for more information.';
1428
1463 - return t.toLocaleDateString() + space + t.toLocaleTimeString();
1464 - }
1429 + NETDATA.alarms.get('all', function(data) {
1430 + options.alarm_families = new Array();
1431
1466 - function seconds4human(seconds, options) {
1467 - var default_options = {
1468 - now: 'now',
1469 - space: '&nbsp;',
1470 - negative_suffix: 'ago',
1471 - hour: 'hour',
1472 - hours: 'hours',
1473 - minute: 'minute',
1474 - minutes: 'minutes',
1475 - second: 'second',
1476 - seconds: 'seconds',
1477 - and: 'and'
1478 - };
1432 + alarmsCallback(data);
1433
1480 - if(typeof options !== 'object')
1481 - options = default_options;
1482 - else {
1483 - var x;
1484 - for(x in default_options) {
1485 - if(typeof options[x] !== 'string')
1486 - options[x] = default_options[x];
1487 - }
1434 + if(data === null) {
1435 + document.getElementById('alarms_active').innerHTML =
1436 + document.getElementById('alarms_all').innerHTML =
1437 + document.getElementById('alarms_log').innerHTML =
1438 + 'failed to load alarm data!';
1439 + return;
1440 }
1441
1490 - if(typeof seconds === 'string')
1491 - seconds = parseInt(seconds);
1442 + function alarmid4human(id) {
1443 + if(id === 0)
1444 + return '-';
1445 +
1446 + return id.toString();
1447 + }
1448
1493 - if(seconds === 0)
1494 - return options.now;
1449 + function timestamp4human(timestamp, space) {
1450 + if(timestamp === 0)
1451 + return '-';
1452
1496 - var suffix = '';
1497 - if(seconds < 0) {
1498 - seconds = -seconds;
1499 - if(options.negative_suffix !== '') suffix = options.space + options.negative_suffix;
1453 + if(typeof space === 'undefined')
1454 + space = '&nbsp;';
1455 +
1456 + var t = new Date(timestamp * 1000);
1457 + var now = new Date();
1458 +
1459 + if(t.toDateString() == now.toDateString())
1460 + return t.toLocaleTimeString();
1461 +
1462 + return t.toLocaleDateString() + space + t.toLocaleTimeString();
1463 }
1464
1502 - var hours = Math.floor(seconds / 3600);
1503 - seconds -= (hours * 3600);
1465 + function seconds4human(seconds, options) {
1466 + var default_options = {
1467 + now: 'now',
1468 + space: '&nbsp;',
1469 + negative_suffix: 'ago',
1470 + hour: 'hour',
1471 + hours: 'hours',
1472 + minute: 'minute',
1473 + minutes: 'minutes',
1474 + second: 'second',
1475 + seconds: 'seconds',
1476 + and: 'and'
1477 + };
1478 +
1479 + if(typeof options !== 'object')
1480 + options = default_options;
1481 + else {
1482 + var x;
1483 + for(x in default_options) {
1484 + if(typeof options[x] !== 'string')
1485 + options[x] = default_options[x];
1486 + }
1487 + }
1488 +
1489 + if(typeof seconds === 'string')
1490 + seconds = parseInt(seconds);
1491
1505 - var minutes = Math.floor(seconds / 60);
1506 - seconds -= (minutes * 60);
1492 + if(seconds === 0)
1493 + return options.now;
1494
1508 - var txt = '';
1495 + var suffix = '';
1496 + if(seconds < 0) {
1497 + seconds = -seconds;
1498 + if(options.negative_suffix !== '') suffix = options.space + options.negative_suffix;
1499 + }
1500
1510 - if(hours > 1) txt += hours.toString() + options.space + options.hours;
1511 - else if(hours === 1) txt += hours.toString() + options.space + options.hour;
1501 + var hours = Math.floor(seconds / 3600);
1502 + seconds -= (hours * 3600);
1503
1513 - if(hours > 0 && minutes > 0 && seconds == 0)
1514 - txt += options.space + options.and + options.space;
1515 - else if(hours > 0 && minutes > 0 && seconds > 0)
1516 - txt += ',' + options.space;
1504 + var minutes = Math.floor(seconds / 60);
1505 + seconds -= (minutes * 60);
1506
1518 - if(minutes > 1) txt += minutes.toString() + options.space + options.minutes;
1519 - else if(minutes === 1) txt += minutes.toString() + options.space + options.minute;
1507 + var txt = '';
1508
1521 - if((minutes > 0 || minutes > 0) && seconds > 0)
1522 - txt += options.space + options.and + options.space;
1509 + if(hours > 1) txt += hours.toString() + options.space + options.hours;
1510 + else if(hours === 1) txt += hours.toString() + options.space + options.hour;
1511
1524 - if(seconds > 1) txt += Math.floor(seconds).toString() + options.space + options.seconds;
1525 - else if(seconds === 1) txt += Math.floor(seconds).toString() + options.space + options.second;
1512 + if(hours > 0 && minutes > 0 && seconds == 0)
1513 + txt += options.space + options.and + options.space;
1514 + else if(hours > 0 && minutes > 0 && seconds > 0)
1515 + txt += ',' + options.space;
1516
1527 - return txt + suffix;
1528 - }
1517 + if(minutes > 1) txt += minutes.toString() + options.space + options.minutes;
1518 + else if(minutes === 1) txt += minutes.toString() + options.space + options.minute;
1519
1530 - function alarm_lookup_explain(alarm, chart) {
1531 - var dimensions = ' of all values ';
1520 + if((minutes > 0 || minutes > 0) && seconds > 0)
1521 + txt += options.space + options.and + options.space;
1522
1533 - if(chart.dimensions.length > 1)
1534 - dimensions = ' of the sum of all dimensions ';
1523 + if(seconds > 1) txt += Math.floor(seconds).toString() + options.space + options.seconds;
1524 + else if(seconds === 1) txt += Math.floor(seconds).toString() + options.space + options.second;
1525
1536 - if(typeof alarm.lookup_dimensions !== 'undefined') {
1537 - var d = alarm.lookup_dimensions.replace('|', ',');
1538 - var x = d.split(',');
1539 - if(x.length > 1)
1540 - dimensions = 'of the sum of dimensions <code>' + alarm.lookup_dimensions + '</code> ';
1541 - else
1542 - dimensions = 'of all values of dimension <code>' + alarm.lookup_dimensions + '</code> ';
1526 + return txt + suffix;
1527 }
1528
1545 - return '<code>' + alarm.lookup_method + '</code> '
1546 - + dimensions + ', of chart <code>' + alarm.chart + '</code>'
1547 - + ', starting <code>' + seconds4human(alarm.lookup_after + alarm.lookup_before) + '</code> and up to <code>' + seconds4human(alarm.lookup_before) + '</code>'
1548 - + ((alarm.lookup_options)?(', with options <code>' + alarm.lookup_options.replace(' ', ',&nbsp;') + '</code>'):'')
1549 - + '.';
1550 - }
1529 + function alarm_lookup_explain(alarm, chart) {
1530 + var dimensions = ' of all values ';
1531
1552 - function alarm_to_html(alarm, full) {
1553 - var chart = options.data.charts[alarm.chart];
1532 + if(chart.dimensions.length > 1)
1533 + dimensions = ' of the sum of all dimensions ';
1534
1555 - var html = '<tr><td class="text-center" style="vertical-align:middle" width="40%"><b>' + alarm.chart + '</b><br/>&nbsp;<br/><embed src="' + NETDATA.alarms.server + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto" type="image/svg+xml" height="20"/><br/>&nbsp;<br/><span style="font-size: 18px">' + alarm.info + '</span><br/>&nbsp;<br/>role: <b>' + alarm.recipient + '</b><br/>&nbsp;<br/><b><i class="fa fa-line-chart" aria-hidden="true"></i></b><small>&nbsp;&nbsp;<a href="#" onClick="NETDATA.alarms.scrollToChart(\'' + alarm.chart + '\'); $(\'#alarmsModal\').modal(\'hide\'); return false;">jump to chart</a></small></td>'
1556 - + '<td><table class="table">'
1557 - + ((typeof alarm.warn !== 'undefined')?('<tr><td width="10%" style="text-align:right">warning&nbsp;when</td><td><span style="font-family: monospace; color:#fe7d37; font-weight: bold;">' + alarm.warn + '</span></td></tr>'):'')
1558 - + ((typeof alarm.crit !== 'undefined')?('<tr><td width="10%" style="text-align:right">critical&nbsp;when</td><td><span style="font-family: monospace; color: #e05d44; font-weight: bold;">' + alarm.crit + '</span></td></tr>'):'');
1535 + if(typeof alarm.lookup_dimensions !== 'undefined') {
1536 + var d = alarm.lookup_dimensions.replace('|', ',');
1537 + var x = d.split(',');
1538 + if(x.length > 1)
1539 + dimensions = 'of the sum of dimensions <code>' + alarm.lookup_dimensions + '</code> ';
1540 + else
1541 + dimensions = 'of all values of dimension <code>' + alarm.lookup_dimensions + '</code> ';
1542 + }
1543
1560 - if(full === true) {
1561 - html += ((typeof alarm.lookup_after !== 'undefined')?('<tr><td width="10%" style="text-align:right">db&nbsp;lookup</td><td>' + alarm_lookup_explain(alarm, chart) + '</td></tr>'):'')
1562 - + ((typeof alarm.calc !== 'undefined')?('<tr><td width="10%" style="text-align:right">calculation</td><td><span style="font-family: monospace;">' + alarm.calc + '</span></td></tr>'):'')
1563 - + ((chart.green !== null)?('<tr><td width="10%" style="text-align:right">green&nbsp;threshold</td><td><code>' + chart.green + ' ' + chart.units + '</code></td></tr>'):'')
1564 - + ((chart.red !== null)?('<tr><td width="10%" style="text-align:right">red&nbsp;threshold</td><td><code>' + chart.red + ' ' + chart.units + '</code></td></tr>'):'');
1544 + return '<code>' + alarm.lookup_method + '</code> '
1545 + + dimensions + ', of chart <code>' + alarm.chart + '</code>'
1546 + + ', starting <code>' + seconds4human(alarm.lookup_after + alarm.lookup_before) + '</code> and up to <code>' + seconds4human(alarm.lookup_before) + '</code>'
1547 + + ((alarm.lookup_options)?(', with options <code>' + alarm.lookup_options.replace(' ', ',&nbsp;') + '</code>'):'')
1548 + + '.';
1549 }
1550
1567 - var delay = '';
1568 - if((alarm.delay_up_duration > 0 || alarm.delay_down_duration > 0) && alarm.delay_multiplier != 0 && alarm.delay_max_duration > 0) {
1569 - if(alarm.delay_up_duration == alarm.delay_down_duration) {
1570 - delay += '<small><br/>hysteresis ' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' });
1551 + function alarm_to_html(alarm, full) {
1552 + var chart = options.data.charts[alarm.chart];
1553 +
1554 + var html = '<tr><td class="text-center" style="vertical-align:middle" width="40%"><b>' + alarm.chart + '</b><br/>&nbsp;<br/><embed src="' + NETDATA.alarms.server + '/api/v1/badge.svg?chart=' + alarm.chart + '&alarm=' + alarm.name + '&refresh=auto" type="image/svg+xml" height="20"/><br/>&nbsp;<br/><span style="font-size: 18px">' + alarm.info + '</span><br/>&nbsp;<br/>role: <b>' + alarm.recipient + '</b><br/>&nbsp;<br/><b><i class="fa fa-line-chart" aria-hidden="true"></i></b><small>&nbsp;&nbsp;<a href="#" onClick="NETDATA.alarms.scrollToChart(\'' + alarm.chart + '\'); $(\'#alarmsModal\').modal(\'hide\'); return false;">jump to chart</a></small></td>'
1555 + + '<td><table class="table">'
1556 + + ((typeof alarm.warn !== 'undefined')?('<tr><td width="10%" style="text-align:right">warning&nbsp;when</td><td><span style="font-family: monospace; color:#fe7d37; font-weight: bold;">' + alarm.warn + '</span></td></tr>'):'')
1557 + + ((typeof alarm.crit !== 'undefined')?('<tr><td width="10%" style="text-align:right">critical&nbsp;when</td><td><span style="font-family: monospace; color: #e05d44; font-weight: bold;">' + alarm.crit + '</span></td></tr>'):'');
1558 +
1559 + if(full === true) {
1560 + html += ((typeof alarm.lookup_after !== 'undefined')?('<tr><td width="10%" style="text-align:right">db&nbsp;lookup</td><td>' + alarm_lookup_explain(alarm, chart) + '</td></tr>'):'')
1561 + + ((typeof alarm.calc !== 'undefined')?('<tr><td width="10%" style="text-align:right">calculation</td><td><span style="font-family: monospace;">' + alarm.calc + '</span></td></tr>'):'')
1562 + + ((chart.green !== null)?('<tr><td width="10%" style="text-align:right">green&nbsp;threshold</td><td><code>' + chart.green + ' ' + chart.units + '</code></td></tr>'):'')
1563 + + ((chart.red !== null)?('<tr><td width="10%" style="text-align:right">red&nbsp;threshold</td><td><code>' + chart.red + ' ' + chart.units + '</code></td></tr>'):'');
1564 }
1572 - else {
1573 - delay = '<small><br/>hysteresis ';
1574 - if(alarm.delay_up_duration > 0) {
1575 - delay += 'on&nbsp;escalation&nbsp;<code>' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' }) + '</code>, ';
1565 +
1566 + var delay = '';
1567 + if((alarm.delay_up_duration > 0 || alarm.delay_down_duration > 0) && alarm.delay_multiplier != 0 && alarm.delay_max_duration > 0) {
1568 + if(alarm.delay_up_duration == alarm.delay_down_duration) {
1569 + delay += '<small><br/>hysteresis ' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' });
1570 + }
1571 + else {
1572 + delay = '<small><br/>hysteresis ';
1573 + if(alarm.delay_up_duration > 0) {
1574 + delay += 'on&nbsp;escalation&nbsp;<code>' + seconds4human(alarm.delay_up_duration, { negative_suffix: '' }) + '</code>, ';
1575 + }
1576 + if(alarm.delay_down_duration > 0) {
1577 + delay += 'on&nbsp;recovery&nbsp;<code>' + seconds4human(alarm.delay_down_duration, { negative_suffix: '' }) + '</code>, ';
1578 + }
1579 }
1577 - if(alarm.delay_down_duration > 0) {
1578 - delay += 'on&nbsp;recovery&nbsp;<code>' + seconds4human(alarm.delay_down_duration, { negative_suffix: '' }) + '</code>, ';
1580 + if(alarm.delay_multiplier != 1.0) {
1581 + delay += 'multiplied&nbsp;by&nbsp;<code>' + alarm.delay_multiplier.toString() + '</code>';
1582 + delay += ',&nbsp;up&nbsp;to&nbsp;<code>' + seconds4human(alarm.delay_max_duration, { negative_suffix: '' }) + '</code>';
1583 }
1584 + delay += '</small>';
1585 }
1581 - if(alarm.delay_multiplier != 1.0) {
1582 - delay += 'multiplied&nbsp;by&nbsp;<code>' + alarm.delay_multiplier.toString() + '</code>';
1583 - delay += ',&nbsp;up&nbsp;to&nbsp;<code>' + seconds4human(alarm.delay_max_duration, { negative_suffix: '' }) + '</code>';
1584 - }
1585 - delay += '</small>';
1586 - }
1586
1588 - html += '<tr><td width="10%" style="text-align:right">check&nbsp;every</td><td>' + seconds4human(alarm.update_every, { negative_suffix: '' }) + '</td></tr>'
1589 - + '<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span>' + delay + '</td></tr>'
1590 - + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>'
1591 - + '</table></td></tr>';
1587 + html += '<tr><td width="10%" style="text-align:right">check&nbsp;every</td><td>' + seconds4human(alarm.update_every, { negative_suffix: '' }) + '</td></tr>'
1588 + + '<tr><td width="10%" style="text-align:right">execute</td><td><span style="font-family: monospace;">' + alarm.exec + '</span>' + delay + '</td></tr>'
1589 + + '<tr><td width="10%" style="text-align:right">source</td><td><span style="font-family: monospace;">' + alarm.source + '</span></td></tr>'
1590 + + '</table></td></tr>';
1591
1593 - return html;
1594 - }
1595 -
1596 - function alarm_family_show(id) {
1597 - var html = '<table class="table">';
1598 - var family = options.alarm_families[id];
1599 - var len = family.arr.length;
1600 - while(len--) {
1601 - var alarm = family.arr[len];
1602 - html += alarm_to_html(alarm, true);
1592 + return html;
1593 }
1604 - html += '</table>';
1594
1606 - $('#alarm_all_' + id.toString()).html(html);
1607 - }
1608 -
1609 - // find the proper family of each alarm
1610 - var now = Date.now();
1611 - var x;
1612 - var count_active = 0;
1613 - var count_all = 0;
1614 - var families = {};
1615 - var families_sort = new Array();
1616 - for(x in data.alarms) {
1617 - var alarm = data.alarms[x];
1618 - var family = alarm.family;
1619 -
1620 - // find the chart
1621 - var chart = options.data.charts[alarm.chart];
1622 - if(typeof chart === 'undefined')
1623 - chart = options.data.charts_by_name[alarm.chart];
1595 + function alarm_family_show(id) {
1596 + var html = '<table class="table">';
1597 + var family = options.alarm_families[id];
1598 + var len = family.arr.length;
1599 + while(len--) {
1600 + var alarm = family.arr[len];
1601 + html += alarm_to_html(alarm, true);
1602 + }
1603 + html += '</table>';
1604
1625 - // not found - this should never happen!
1626 - if(typeof chart === 'undefined') {
1627 - console.log('WARNING: alarm ' + x + ' is linked to chart ' + alarm.chart + ', which is not found in the list of chart got from the server.');
1628 - chart = { priority: 9999999 };
1605 + $('#alarm_all_' + id.toString()).html(html);
1606 }
1630 - else if(typeof chart.menu !== 'undefined' && typeof chart.submenu !== 'undefined')
1631 - // the family based on the chart
1632 - family = chart.menu + ' - ' + chart.submenu;
1633 -
1634 - if(typeof families[family] === 'undefined') {
1635 - families[family] = {
1636 - name: family,
1637 - arr: new Array(),
1638 - priority: chart.priority
1639 - };
1607
1641 - families_sort.push(families[family]);
1642 - }
1608 + // find the proper family of each alarm
1609 + var now = Date.now();
1610 + var x;
1611 + var count_active = 0;
1612 + var count_all = 0;
1613 + var families = {};
1614 + var families_sort = new Array();
1615 + for(x in data.alarms) {
1616 + var alarm = data.alarms[x];
1617 + var family = alarm.family;
1618 +
1619 + // find the chart
1620 + var chart = options.data.charts[alarm.chart];
1621 + if(typeof chart === 'undefined')
1622 + chart = options.data.charts_by_name[alarm.chart];
1623 +
1624 + // not found - this should never happen!
1625 + if(typeof chart === 'undefined') {
1626 + console.log('WARNING: alarm ' + x + ' is linked to chart ' + alarm.chart + ', which is not found in the list of chart got from the server.');
1627 + chart = { priority: 9999999 };
1628 + }
1629 + else if(typeof chart.menu !== 'undefined' && typeof chart.submenu !== 'undefined')
1630 + // the family based on the chart
1631 + family = chart.menu + ' - ' + chart.submenu;
1632 +
1633 + if(typeof families[family] === 'undefined') {
1634 + families[family] = {
1635 + name: family,
1636 + arr: new Array(),
1637 + priority: chart.priority
1638 + };
1639 +
1640 + families_sort.push(families[family]);
1641 + }
1642
1644 - if(chart.priority < families[family].priority)
1645 - families[family].priority = chart.priority;
1643 + if(chart.priority < families[family].priority)
1644 + families[family].priority = chart.priority;
1645
1647 - families[family].arr.unshift(alarm);
1648 - }
1646 + families[family].arr.unshift(alarm);
1647 + }
1648
1650 - // sort the families, like the dashboard menu does
1651 - var families_sorted = families_sort.sort(function (a, b) {
1652 - if (a.priority > b.priority) return -1;
1653 - if (a.priority < b.priority) return 1;
1654 - return 0;
1655 - });
1649 + // sort the families, like the dashboard menu does
1650 + var families_sorted = families_sort.sort(function (a, b) {
1651 + if (a.priority > b.priority) return -1;
1652 + if (a.priority < b.priority) return 1;
1653 + return 0;
1654 + });
1655
1657 - var fc = 0;
1658 - var len = families_sorted.length;
1659 - while(len--) {
1660 - var family = families_sorted[len].name;
1661 - var active_family_added = false;
1662 - var expanded = 'true';
1663 - var collapsed = '';
1664 - var cin = 'in';
1665 -
1666 - if(fc !== 0) {
1667 - all += "</table></div></div></div>";
1668 - expanded = 'false';
1669 - collapsed = 'class="collapsed"'
1670 - cin = '';
1671 - }
1656 + var fc = 0;
1657 + var len = families_sorted.length;
1658 + while(len--) {
1659 + var family = families_sorted[len].name;
1660 + var active_family_added = false;
1661 + var expanded = 'true';
1662 + var collapsed = '';
1663 + var cin = 'in';
1664 +
1665 + if(fc !== 0) {
1666 + all += "</table></div></div></div>";
1667 + expanded = 'false';
1668 + collapsed = 'class="collapsed"'
1669 + cin = '';
1670 + }
1671
1673 - all += '<div class="panel panel-default"><div class="panel-heading" role="tab" id="alarm_all_heading_' + fc.toString() + '"><h4 class="panel-title"><a ' + collapsed + ' role="button" data-toggle="collapse" data-parent="#alarms_all_accordion" href="#alarm_all_' + fc.toString() + '" aria-expanded="' + expanded + '" aria-controls="alarm_all_' + fc.toString() + '">' + family.toString() + '</a></h4></div><div id="alarm_all_' + fc.toString() + '" class="panel-collapse collapse ' + cin + '" role="tabpanel" aria-labelledby="alarm_all_heading_' + fc.toString() + '" data-alarm-id="' + fc.toString() + '"><div class="panel-body" id="alarm_all_body_' + fc.toString() + '">';
1672 + all += '<div class="panel panel-default"><div class="panel-heading" role="tab" id="alarm_all_heading_' + fc.toString() + '"><h4 class="panel-title"><a ' + collapsed + ' role="button" data-toggle="collapse" data-parent="#alarms_all_accordion" href="#alarm_all_' + fc.toString() + '" aria-expanded="' + expanded + '" aria-controls="alarm_all_' + fc.toString() + '">' + family.toString() + '</a></h4></div><div id="alarm_all_' + fc.toString() + '" class="panel-collapse collapse ' + cin + '" role="tabpanel" aria-labelledby="alarm_all_heading_' + fc.toString() + '" data-alarm-id="' + fc.toString() + '"><div class="panel-body" id="alarm_all_body_' + fc.toString() + '">';
1673
1675 - options.alarm_families[fc] = families[family];
1674 + options.alarm_families[fc] = families[family];
1675
1677 - fc++;
1676 + fc++;
1677
1679 - var arr = families[family].arr;
1680 - var c = arr.length;
1681 - while(c--) {
1682 - var alarm = arr[c];
1683 - if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') {
1684 - if(!active_family_added) {
1685 - active_family_added = true;
1686 - active += '<tr><th class="text-center" colspan="2"><h4>' + family + '</h4></th></tr>';
1678 + var arr = families[family].arr;
1679 + var c = arr.length;
1680 + while(c--) {
1681 + var alarm = arr[c];
1682 + if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL') {
1683 + if(!active_family_added) {
1684 + active_family_added = true;
1685 + active += '<tr><th class="text-center" colspan="2"><h4>' + family + '</h4></th></tr>';
1686 + }
1687 + count_active++;
1688 + active += alarm_to_html(alarm, true);
1689 }
1688 - count_active++;
1689 - active += alarm_to_html(alarm, true);
1690 - }
1690
1692 - count_all++;
1691 + count_all++;
1692 + }
1693 }
1694 - }
1695 - active += "</table>";
1696 - if(families_sorted.length > 0) all += "</div></div></div>";
1697 - all += "</div>";
1694 + active += "</table>";
1695 + if(families_sorted.length > 0) all += "</div></div></div>";
1696 + all += "</div>";
1697
1699 - if(!count_active)
1700 - active += "<h4>Everything is normal. No raised alarms.</h4>";
1701 - else
1702 - active += footer;
1698 + if(!count_active)
1699 + active += "<h4>Everything is normal. No raised alarms.</h4>";
1700 + else
1701 + active += footer;
1702
1704 - if(!count_all)
1705 - all += "<h4>No alarms are running in this system.</h4>";
1706 - else
1707 - all += footer;
1703 + if(!count_all)
1704 + all += "<h4>No alarms are running in this system.</h4>";
1705 + else
1706 + all += footer;
1707
1709 - document.getElementById('alarms_active').innerHTML = active;
1710 - document.getElementById('alarms_all').innerHTML = all;
1708 + document.getElementById('alarms_active').innerHTML = active;
1709 + document.getElementById('alarms_all').innerHTML = all;
1710
1712 - if(families_sorted.length > 0) alarm_family_show(0);
1711 + if(families_sorted.length > 0) alarm_family_show(0);
1712
1714 - // register bootstrap events
1715 - $('#alarms_all_accordion').on('show.bs.collapse', function (d) {
1716 - var target = $(d.target);
1717 - var id = $(target).data('alarm-id');
1718 - alarm_family_show(id);
1719 - });
1720 - $('#alarms_all_accordion').on('hidden.bs.collapse', function (d) {
1721 - var target = $(d.target);
1722 - var id = $(target).data('alarm-id');
1723 - $('#alarm_all_' + id.toString()).html('');
1724 - });
1713 + // register bootstrap events
1714 + $('#alarms_all_accordion').on('show.bs.collapse', function (d) {
1715 + var target = $(d.target);
1716 + var id = $(target).data('alarm-id');
1717 + alarm_family_show(id);
1718 + });
1719 + $('#alarms_all_accordion').on('hidden.bs.collapse', function (d) {
1720 + var target = $(d.target);
1721 + var id = $(target).data('alarm-id');
1722 + $('#alarm_all_' + id.toString()).html('');
1723 + });
1724
1726 - document.getElementById('alarms_log').innerHTML = '<h3>Alarm Log</h3><table id="alarms_log_table"></table>';
1727 -
1728 - loadBootstrapTable(function () {
1729 - $('#alarms_log_table').bootstrapTable({
1730 - url: NETDATA.alarms.server + '/api/v1/alarm_log?all',
1731 - cache: false,
1732 - pagination: true,
1733 - pageSize: 10,
1734 - showPaginationSwitch: false,
1735 - search: true,
1736 - searchTimeOut: 300,
1737 - searchAlign: 'left',
1738 - showColumns: true,
1739 - showExport: true,
1740 - exportDataType: 'basic',
1741 - exportOptions: {
1742 - fileName: 'netdata_alarm_log'
1743 - },
1744 - rowStyle: function(row, index) {
1745 - switch(row.status) {
1746 - case 'CRITICAL' : return { classes: 'danger' }; break;
1747 - case 'WARNING' : return { classes: 'warning' }; break;
1748 - case 'UNDEFINED': return { classes: 'info' }; break;
1749 - case 'CLEAR' : return { classes: 'success' }; break;
1750 - }
1751 - return {};
1752 - },
1753 - showFooter: false,
1754 - showHeader: true,
1755 - showRefresh: true,
1756 - showToggle: false,
1757 - sortable: true,
1758 - silentSort: false,
1759 - columns: [
1760 - {
1761 - field: 'when',
1762 - title: 'Event Date',
1763 - valign: 'middle',
1764 - titleTooltip: 'The date and time the even took place',
1765 - formatter: function(value, row, index) { return timestamp4human(value, ' '); },
1766 - align: 'center',
1767 - valign: 'middle',
1768 - switchable: false,
1769 - sortable: true
1770 - },
1771 - {
1772 - field: 'hostname',
1773 - title: 'Host',
1774 - valign: 'middle',
1775 - titleTooltip: 'The host that generated this event',
1776 - align: 'center',
1777 - valign: 'middle',
1778 - visible: false,
1779 - sortable: true
1725 + document.getElementById('alarms_log').innerHTML = '<h3>Alarm Log</h3><table id="alarms_log_table"></table>';
1726 +
1727 + loadBootstrapTable(function () {
1728 + $('#alarms_log_table').bootstrapTable({
1729 + url: NETDATA.alarms.server + '/api/v1/alarm_log?all',
1730 + cache: false,
1731 + pagination: true,
1732 + pageSize: 10,
1733 + showPaginationSwitch: false,
1734 + search: true,
1735 + searchTimeOut: 300,
1736 + searchAlign: 'left',
1737 + showColumns: true,
1738 + showExport: true,
1739 + exportDataType: 'basic',
1740 + exportOptions: {
1741 + fileName: 'netdata_alarm_log'
1742 },
1781 - {
1782 - field: 'unique_id',
1783 - title: 'Unique ID',
1784 - titleTooltip: 'The host unique ID for this event',
1785 - formatter: function(value, row, index) { return alarmid4human(value); },
1786 - align: 'center',
1787 - valign: 'middle',
1788 - visible: false,
1789 - sortable: true
1790 - },
1791 - {
1792 - field: 'alarm_id',
1793 - title: 'Alarm ID',
1794 - titleTooltip: 'The ID of the alarm that generated this event',
1795 - formatter: function(value, row, index) { return alarmid4human(value); },
1796 - align: 'center',
1797 - valign: 'middle',
1798 - visible: false,
1799 - sortable: true
1800 - },
1801 - {
1802 - field: 'alarm_event_id',
1803 - title: 'Alarm Event ID',
1804 - titleTooltip: 'The incremental ID of this event for the given alarm',
1805 - formatter: function(value, row, index) { return alarmid4human(value); },
1806 - align: 'center',
1807 - valign: 'middle',
1808 - visible: false,
1809 - sortable: true
1810 - },
1811 - {
1812 - field: 'chart',
1813 - title: 'Chart',
1814 - titleTooltip: 'The chart the alarm is attached to',
1815 - align: 'center',
1816 - valign: 'middle',
1817 - switchable: false,
1818 - sortable: true
1819 - },
1820 - {
1821 - field: 'family',
1822 - title: 'Family',
1823 - titleTooltip: 'The family of the chart the alarm is attached to',
1824 - align: 'center',
1825 - valign: 'middle',
1826 - visible: false,
1827 - sortable: true
1743 + rowStyle: function(row, index) {
1744 + switch(row.status) {
1745 + case 'CRITICAL' : return { classes: 'danger' }; break;
1746 + case 'WARNING' : return { classes: 'warning' }; break;
1747 + case 'UNDEFINED': return { classes: 'info' }; break;
1748 + case 'CLEAR' : return { classes: 'success' }; break;
1749 + }
1750 + return {};
1751 },
1829 - {
1830 - field: 'name',
1831 - title: 'Alarm',
1832 - titleTooltip: 'The alarm name that generated this event',
1833 - formatter: function(value, row, index) {
1834 - return value.toString().replace(/_/g, ' ');
1752 + showFooter: false,
1753 + showHeader: true,
1754 + showRefresh: true,
1755 + showToggle: false,
1756 + sortable: true,
1757 + silentSort: false,
1758 + columns: [
1759 + {
1760 + field: 'when',
1761 + title: 'Event Date',
1762 + valign: 'middle',
1763 + titleTooltip: 'The date and time the even took place',
1764 + formatter: function(value, row, index) { return timestamp4human(value, ' '); },
1765 + align: 'center',
1766 + valign: 'middle',
1767 + switchable: false,
1768 + sortable: true
1769 },
1836 - align: 'center',
1837 - valign: 'middle',
1838 - switchable: false,
1839 - sortable: true
1840 - },
1841 - {
1842 - field: 'old_value',
1843 - title: 'Old Value',
1844 - titleTooltip: 'The value of the alarm, just before this event',
1845 - formatter: function(value, row, index) {
1846 - return ((value !== null)?Math.round(value * 100) / 100:'NaN').toString();
1770 + {
1771 + field: 'hostname',
1772 + title: 'Host',
1773 + valign: 'middle',
1774 + titleTooltip: 'The host that generated this event',
1775 + align: 'center',
1776 + valign: 'middle',
1777 + visible: false,
1778 + sortable: true
1779 },
1848 - align: 'center',
1849 - valign: 'middle',
1850 - visible: false,
1851 - sortable: true
1852 - },
1853 - {
1854 - field: 'value',
1855 - title: 'Value',
1856 - titleTooltip: 'The value of the alarm, that triggered this event',
1857 - formatter: function(value, row, index) {
1858 - return ((value !== null)?Math.round(value * 100) / 100:'NaN').toString();
1780 + {
1781 + field: 'unique_id',
1782 + title: 'Unique ID',
1783 + titleTooltip: 'The host unique ID for this event',
1784 + formatter: function(value, row, index) { return alarmid4human(value); },
1785 + align: 'center',
1786 + valign: 'middle',
1787 + visible: false,
1788 + sortable: true
1789 },
1860 - align: 'right',
1861 - valign: 'middle',
1862 - sortable: true
1863 - },
1864 - {
1865 - field: 'units',
1866 - title: 'Units',
1867 - titleTooltip: 'The units of the value of the alarm',
1868 - align: 'left',
1869 - valign: 'middle',
1870 - sortable: true
1871 - },
1872 - {
1873 - field: 'old_status',
1874 - title: 'Old Status',
1875 - titleTooltip: 'The status of the alarm, just before this event',
1876 - align: 'center',
1877 - valign: 'middle',
1878 - visible: false,
1879 - sortable: true
1880 - },
1881 - {
1882 - field: 'status',
1883 - title: 'Status',
1884 - titleTooltip: 'The status of the alarm, that was set due to this event',
1885 - align: 'center',
1886 - valign: 'middle',
1887 - switchable: false,
1888 - sortable: true
1889 - },
1890 - {
1891 - field: 'duration',
1892 - title: 'Last Duration',
1893 - titleTooltip: 'The duration the alarm was at its previous state, just before this event',
1894 - formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); },
1895 - align: 'center',
1896 - valign: 'middle',
1897 - visible: false,
1898 - sortable: true
1899 - },
1900 - {
1901 - field: 'non_clear_duration',
1902 - title: 'Raised Duration',
1903 - titleTooltip: 'The duration the alarm was raised, just before this event',
1904 - formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); },
1905 - align: 'center',
1906 - valign: 'middle',
1907 - visible: false,
1908 - sortable: true
1909 - },
1910 - {
1911 - field: 'recipient',
1912 - title: 'Recipient',
1913 - titleTooltip: 'The recipient of this event',
1914 - align: 'center',
1915 - valign: 'middle',
1916 - visible: false,
1917 - sortable: true
1918 - },
1919 - {
1920 - field: 'processed',
1921 - title: 'Processed Status',
1922 - titleTooltip: 'True when this event is processed',
1923 - formatter: function(value, row, index) {
1924 - if(value === true)
1925 - return 'DONE';
1926 - else
1927 - return 'PENDING';
1790 + {
1791 + field: 'alarm_id',
1792 + title: 'Alarm ID',
1793 + titleTooltip: 'The ID of the alarm that generated this event',
1794 + formatter: function(value, row, index) { return alarmid4human(value); },
1795 + align: 'center',
1796 + valign: 'middle',
1797 + visible: false,
1798 + sortable: true
1799 },
1929 - align: 'center',
1930 - valign: 'middle',
1931 - visible: false,
1932 - sortable: true
1933 - },
1934 - {
1935 - field: 'updated',
1936 - title: 'Updated Status',
1937 - titleTooltip: 'True when this event has been updated by another event',
1938 - formatter: function(value, row, index) {
1939 - if(value === true)
1940 - return 'UPDATED';
1941 - else
1942 - return 'CURRENT';
1800 + {
1801 + field: 'alarm_event_id',
1802 + title: 'Alarm Event ID',
1803 + titleTooltip: 'The incremental ID of this event for the given alarm',
1804 + formatter: function(value, row, index) { return alarmid4human(value); },
1805 + align: 'center',
1806 + valign: 'middle',
1807 + visible: false,
1808 + sortable: true
1809 },
1944 - align: 'center',
1945 - valign: 'middle',
1946 - visible: false,
1947 - sortable: true
1948 - },
1949 - {
1950 - field: 'updated_by_id',
1951 - title: 'Updated By ID',
1952 - titleTooltip: 'The unique ID of the event that obsoleted this one',
1953 - formatter: function(value, row, index) { return alarmid4human(value); },
1954 - align: 'center',
1955 - valign: 'middle',
1956 - visible: false,
1957 - sortable: true
1958 - },
1959 - {
1960 - field: 'updates_id',
1961 - title: 'Updates ID',
1962 - titleTooltip: 'The unique ID of the event obsoleted because of this event',
1963 - formatter: function(value, row, index) { return alarmid4human(value); },
1964 - align: 'center',
1965 - valign: 'middle',
1966 - visible: false,
1967 - sortable: true
1968 - },
1969 - {
1970 - field: 'exec',
1971 - title: 'Script',
1972 - titleTooltip: 'The script to handle the event notification',
1973 - align: 'center',
1974 - valign: 'middle',
1975 - visible: false,
1976 - sortable: true
1977 - },
1978 - {
1979 - field: 'exec_run',
1980 - title: 'Script Run At',
1981 - titleTooltip: 'The date and time the script has been ran',
1982 - formatter: function(value, row, index) { return timestamp4human(value, ' '); },
1983 - align: 'center',
1984 - valign: 'middle',
1985 - visible: false,
1986 - sortable: true
1987 - },
1988 - {
1989 - field: 'exec_code',
1990 - title: 'Script Return Value',
1991 - titleTooltip: 'The return code of the script',
1992 - formatter: function(value, row, index) {
1993 - if(value === 0)
1994 - return 'OK (returned 0)';
1995 - else
1996 - return 'FAILED (with code ' + value.toString() + ')';
1810 + {
1811 + field: 'chart',
1812 + title: 'Chart',
1813 + titleTooltip: 'The chart the alarm is attached to',
1814 + align: 'center',
1815 + valign: 'middle',
1816 + switchable: false,
1817 + sortable: true
1818 },
1998 - align: 'center',
1999 - valign: 'middle',
2000 - visible: false,
2001 - sortable: true
2002 - },
2003 - {
2004 - field: 'delay',
2005 - title: 'Script Delay',
2006 - titleTooltip: 'The hysteresis of the notification',
2007 - formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); },
2008 - align: 'center',
2009 - valign: 'middle',
2010 - visible: false,
2011 - sortable: true
2012 - },
2013 - {
2014 - field: 'delay_up_to_timestamp',
2015 - title: 'Script Delay Run At',
2016 - titleTooltip: 'The date and time the script should be run, after hysteresis',
2017 - formatter: function(value, row, index) { return timestamp4human(value, ' '); },
2018 - align: 'center',
2019 - valign: 'middle',
2020 - visible: false,
2021 - sortable: true
2022 - },
2023 - {
2024 - field: 'info',
2025 - title: 'Description',
2026 - titleTooltip: 'A short description of the alarm',
2027 - align: 'center',
2028 - valign: 'middle',
2029 - visible: false,
2030 - sortable: true
2031 - },
2032 - {
2033 - field: 'source',
2034 - title: 'Alarm Source',
2035 - titleTooltip: 'The source of configuration of the alarm',
2036 - align: 'center',
2037 - valign: 'middle',
2038 - visible: false,
2039 - sortable: true
2040 - }
2041 - ]
1819 + {
1820 + field: 'family',
1821 + title: 'Family',
1822 + titleTooltip: 'The family of the chart the alarm is attached to',
1823 + align: 'center',
1824 + valign: 'middle',
1825 + visible: false,
1826 + sortable: true
1827 + },
1828 + {
1829 + field: 'name',
1830 + title: 'Alarm',
1831 + titleTooltip: 'The alarm name that generated this event',
1832 + formatter: function(value, row, index) {
1833 + return value.toString().replace(/_/g, ' ');
1834 + },
1835 + align: 'center',
1836 + valign: 'middle',
1837 + switchable: false,
1838 + sortable: true
1839 + },
1840 + {
1841 + field: 'old_value',
1842 + title: 'Old Value',
1843 + titleTooltip: 'The value of the alarm, just before this event',
1844 + formatter: function(value, row, index) {
1845 + return ((value !== null)?Math.round(value * 100) / 100:'NaN').toString();
1846 + },
1847 + align: 'center',
1848 + valign: 'middle',
1849 + visible: false,
1850 + sortable: true
1851 + },
1852 + {
1853 + field: 'value',
1854 + title: 'Value',
1855 + titleTooltip: 'The value of the alarm, that triggered this event',
1856 + formatter: function(value, row, index) {
1857 + return ((value !== null)?Math.round(value * 100) / 100:'NaN').toString();
1858 + },
1859 + align: 'right',
1860 + valign: 'middle',
1861 + sortable: true
1862 + },
1863 + {
1864 + field: 'units',
1865 + title: 'Units',
1866 + titleTooltip: 'The units of the value of the alarm',
1867 + align: 'left',
1868 + valign: 'middle',
1869 + sortable: true
1870 + },
1871 + {
1872 + field: 'old_status',
1873 + title: 'Old Status',
1874 + titleTooltip: 'The status of the alarm, just before this event',
1875 + align: 'center',
1876 + valign: 'middle',
1877 + visible: false,
1878 + sortable: true
1879 + },
1880 + {
1881 + field: 'status',
1882 + title: 'Status',
1883 + titleTooltip: 'The status of the alarm, that was set due to this event',
1884 + align: 'center',
1885 + valign: 'middle',
1886 + switchable: false,
1887 + sortable: true
1888 + },
1889 + {
1890 + field: 'duration',
1891 + title: 'Last Duration',
1892 + titleTooltip: 'The duration the alarm was at its previous state, just before this event',
1893 + formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); },
1894 + align: 'center',
1895 + valign: 'middle',
1896 + visible: false,
1897 + sortable: true
1898 + },
1899 + {
1900 + field: 'non_clear_duration',
1901 + title: 'Raised Duration',
1902 + titleTooltip: 'The duration the alarm was raised, just before this event',
1903 + formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); },
1904 + align: 'center',
1905 + valign: 'middle',
1906 + visible: false,
1907 + sortable: true
1908 + },
1909 + {
1910 + field: 'recipient',
1911 + title: 'Recipient',
1912 + titleTooltip: 'The recipient of this event',
1913 + align: 'center',
1914 + valign: 'middle',
1915 + visible: false,
1916 + sortable: true
1917 + },
1918 + {
1919 + field: 'processed',
1920 + title: 'Processed Status',
1921 + titleTooltip: 'True when this event is processed',
1922 + formatter: function(value, row, index) {
1923 + if(value === true)
1924 + return 'DONE';
1925 + else
1926 + return 'PENDING';
1927 + },
1928 + align: 'center',
1929 + valign: 'middle',
1930 + visible: false,
1931 + sortable: true
1932 + },
1933 + {
1934 + field: 'updated',
1935 + title: 'Updated Status',
1936 + titleTooltip: 'True when this event has been updated by another event',
1937 + formatter: function(value, row, index) {
1938 + if(value === true)
1939 + return 'UPDATED';
1940 + else
1941 + return 'CURRENT';
1942 + },
1943 + align: 'center',
1944 + valign: 'middle',
1945 + visible: false,
1946 + sortable: true
1947 + },
1948 + {
1949 + field: 'updated_by_id',
1950 + title: 'Updated By ID',
1951 + titleTooltip: 'The unique ID of the event that obsoleted this one',
1952 + formatter: function(value, row, index) { return alarmid4human(value); },
1953 + align: 'center',
1954 + valign: 'middle',
1955 + visible: false,
1956 + sortable: true
1957 + },
1958 + {
1959 + field: 'updates_id',
1960 + title: 'Updates ID',
1961 + titleTooltip: 'The unique ID of the event obsoleted because of this event',
1962 + formatter: function(value, row, index) { return alarmid4human(value); },
1963 + align: 'center',
1964 + valign: 'middle',
1965 + visible: false,
1966 + sortable: true
1967 + },
1968 + {
1969 + field: 'exec',
1970 + title: 'Script',
1971 + titleTooltip: 'The script to handle the event notification',
1972 + align: 'center',
1973 + valign: 'middle',
1974 + visible: false,
1975 + sortable: true
1976 + },
1977 + {
1978 + field: 'exec_run',
1979 + title: 'Script Run At',
1980 + titleTooltip: 'The date and time the script has been ran',
1981 + formatter: function(value, row, index) { return timestamp4human(value, ' '); },
1982 + align: 'center',
1983 + valign: 'middle',
1984 + visible: false,
1985 + sortable: true
1986 + },
1987 + {
1988 + field: 'exec_code',
1989 + title: 'Script Return Value',
1990 + titleTooltip: 'The return code of the script',
1991 + formatter: function(value, row, index) {
1992 + if(value === 0)
1993 + return 'OK (returned 0)';
1994 + else
1995 + return 'FAILED (with code ' + value.toString() + ')';
1996 + },
1997 + align: 'center',
1998 + valign: 'middle',
1999 + visible: false,
2000 + sortable: true
2001 + },
2002 + {
2003 + field: 'delay',
2004 + title: 'Script Delay',
2005 + titleTooltip: 'The hysteresis of the notification',
2006 + formatter: function(value, row, index) { return seconds4human(value, { negative_suffix: '', space: ' ', now: 'no time' }); },
2007 + align: 'center',
2008 + valign: 'middle',
2009 + visible: false,
2010 + sortable: true
2011 + },
2012 + {
2013 + field: 'delay_up_to_timestamp',
2014 + title: 'Script Delay Run At',
2015 + titleTooltip: 'The date and time the script should be run, after hysteresis',
2016 + formatter: function(value, row, index) { return timestamp4human(value, ' '); },
2017 + align: 'center',
2018 + valign: 'middle',
2019 + visible: false,
2020 + sortable: true
2021 + },
2022 + {
2023 + field: 'info',
2024 + title: 'Description',
2025 + titleTooltip: 'A short description of the alarm',
2026 + align: 'center',
2027 + valign: 'middle',
2028 + visible: false,
2029 + sortable: true
2030 + },
2031 + {
2032 + field: 'source',
2033 + title: 'Alarm Source',
2034 + titleTooltip: 'The source of configuration of the alarm',
2035 + align: 'center',
2036 + valign: 'middle',
2037 + visible: false,
2038 + sortable: true
2039 + }
2040 + ]
2041 + });
2042 + // console.log($('#alarms_log_table').bootstrapTable('getOptions'));
2043 });
2043 - // console.log($('#alarms_log_table').bootstrapTable('getOptions'));
2044 });
2045 - });
2046 - }
2045 + }
2046 +
2047 + function alarmsCallback(data) {
2048 + var count = 0;
2049 + for(x in data.alarms) {
2050 + var alarm = data.alarms[x];
2051 + if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL')
2052 + count++;
2053 + }
2054
2048 - function alarmsCallback(data) {
2049 - var count = 0;
2050 - for(x in data.alarms) {
2051 - var alarm = data.alarms[x];
2052 - if(alarm.status === 'WARNING' || alarm.status === 'CRITICAL')
2053 - count++;
2055 + if(count > 0)
2056 + document.getElementById('alarms_count_badge').innerHTML = count.toString();
2057 + else
2058 + document.getElementById('alarms_count_badge').innerHTML = '';
2059 }
2060
2056 - if(count > 0)
2057 - document.getElementById('alarms_count_badge').innerHTML = count.toString();
2058 - else
2059 - document.getElementById('alarms_count_badge').innerHTML = '';
2060 - }
2061 + function initializeDynamicDashboard(netdata_url) {
2062 + if(typeof netdata_url === 'undefined' || netdata_url === null)
2063 + netdata_url = NETDATA.serverDefault;
2064 +
2065 + // initialize clickable alarms
2066 + NETDATA.alarms.chart_div_offset = 100;
2067 + NETDATA.alarms.chart_div_id_prefix = 'chart_';
2068 + NETDATA.alarms.chart_div_animation_duration = 0;
2069 +
2070 + NETDATA.pause(function() {
2071 + NETDATA.alarms.callback = alarmsCallback;
2072 +
2073 + // download all the charts the server knows
2074 + NETDATA.chartRegistry.downloadAll(netdata_url, function(data) {
2075 + if(data !== null) {
2076 + options.hostname = data.hostname;
2077 + options.data = data;
2078 +
2079 + // update the dashboard hostname
2080 + document.getElementById('hostname').innerHTML = options.hostname;
2081 + document.getElementById('hostname').href = NETDATA.serverDefault;
2082 +
2083 + // update the dashboard title
2084 + document.title = options.hostname + ' netdata dashboard';
2085 +
2086 + // close the splash screen
2087 + $("#loadOverlay").css("display","none");
2088 +
2089 + // create a chart_by_name index
2090 + data.charts_by_name = {};
2091 + var charts = data.charts;
2092 + var x;
2093 + for(x in charts) {
2094 + var chart = charts[x];
2095 + data.charts_by_name[chart.name] = chart;
2096 + }
2097
2062 - function initializeDynamicDashboard(netdata_url) {
2063 - if(typeof netdata_url === 'undefined' || netdata_url === null)
2064 - netdata_url = NETDATA.serverDefault;
2065 -
2066 - // initialize clickable alarms
2067 - NETDATA.alarms.chart_div_offset = 100;
2068 - NETDATA.alarms.chart_div_id_prefix = 'chart_';
2069 - NETDATA.alarms.chart_div_animation_duration = 0;
2070 -
2071 - NETDATA.pause(function() {
2072 - NETDATA.alarms.callback = alarmsCallback;
2073 -
2074 - // download all the charts the server knows
2075 - NETDATA.chartRegistry.downloadAll(netdata_url, function(data) {
2076 - if(data !== null) {
2077 - options.hostname = data.hostname;
2078 - options.data = data;
2079 -
2080 - // update the dashboard hostname
2081 - document.getElementById('hostname').innerHTML = options.hostname;
2082 - document.getElementById('hostname').href = NETDATA.serverDefault;
2083 -
2084 - // update the dashboard title
2085 - document.title = options.hostname + ' netdata dashboard';
2086 -
2087 - // close the splash screen
2088 - $("#loadOverlay").css("display","none");
2089 -
2090 - // create a chart_by_name index
2091 - data.charts_by_name = {};
2092 - var charts = data.charts;
2093 - var x;
2094 - for(x in charts) {
2095 - var chart = charts[x];
2096 - data.charts_by_name[chart.name] = chart;
2098 + // render all charts
2099 + renderChartsAndMenu(data);
2100 }
2098 -
2099 - // render all charts
2100 - renderChartsAndMenu(data);
2101 - }
2101 + });
2102 });
2103 - });
2104 - }
2103 + }
2104
2106 - // ----------------------------------------------------------------------------
2105 + // ----------------------------------------------------------------------------
2106
2108 - function versionLog(msg) {
2109 - document.getElementById('versionCheckLog').innerHTML = msg;
2110 - }
2107 + function versionLog(msg) {
2108 + document.getElementById('versionCheckLog').innerHTML = msg;
2109 + }
2110
2112 - function getNetdataVersion(callback) {
2113 - versionLog('Downloading installed version info from netdata...');
2114 -
2115 - $.ajax({
2116 - url: 'version.txt',
2117 - async: true,
2118 - cache: false,
2119 - xhrFields: { withCredentials: true } // required for the cookie
2120 - })
2121 - .done(function(data) {
2122 - data = data.replace(/(\r\n|\n|\r| |\t)/gm,"");
2123 - if(data.length !== 40) {
2124 - versionLog('Received version string is invalid.');
2111 + function getNetdataVersion(callback) {
2112 + versionLog('Downloading installed version info from netdata...');
2113 +
2114 + $.ajax({
2115 + url: 'version.txt',
2116 + async: true,
2117 + cache: false,
2118 + xhrFields: { withCredentials: true } // required for the cookie
2119 + })
2120 + .done(function(data) {
2121 + data = data.replace(/(\r\n|\n|\r| |\t)/gm,"");
2122 + if(data.length !== 40) {
2123 + versionLog('Received version string is invalid.');
2124 + callback(null);
2125 + }
2126 + else {
2127 + versionLog('Installed version of netdata is ' + data);
2128 + document.getElementById('netdataVersion').innerHTML = data;
2129 + callback(data);
2130 + }
2131 + })
2132 + .fail(function() {
2133 + versionLog('Failed to download installed version info from netdata!');
2134 callback(null);
2126 - }
2127 - else {
2128 - versionLog('Installed version of netdata is ' + data);
2129 - document.getElementById('netdataVersion').innerHTML = data;
2130 - callback(data);
2131 - }
2132 - })
2133 - .fail(function() {
2134 - versionLog('Failed to download installed version info from netdata!');
2135 - callback(null);
2136 - });
2137 - }
2138 -
2139 - function getGithubLatestCommit(callback) {
2140 - versionLog('Downloading latest version info from github...');
2141 -
2142 - $.ajax({
2143 - url: 'https://api.github.com/repos/firehol/netdata/commits',
2144 - async: true,
2145 - cache: false
2146 - })
2147 - .done(function(data) {
2148 - versionLog('Latest version info from github is ' + data[0].sha);
2149 - callback(data[0].sha);
2150 - })
2151 - .fail(function() {
2152 - versionLog('Failed to download installed version info from github!');
2153 - callback(null);
2154 - });
2155 - }
2156 -
2157 - function checkForUpdate(callback) {
2158 - getNetdataVersion(function(sha1) {
2159 - if(sha1 === null) callback(null, null);
2135 + });
2136 + }
2137
2161 - getGithubLatestCommit(function(sha2) {
2162 - callback(sha1, sha2);
2138 + function getGithubLatestCommit(callback) {
2139 + versionLog('Downloading latest version info from github...');
2140 +
2141 + $.ajax({
2142 + url: 'https://api.github.com/repos/firehol/netdata/commits',
2143 + async: true,
2144 + cache: false
2145 + })
2146 + .done(function(data) {
2147 + versionLog('Latest version info from github is ' + data[0].sha);
2148 + callback(data[0].sha);
2149 + })
2150 + .fail(function() {
2151 + versionLog('Failed to download installed version info from github!');
2152 + callback(null);
2153 });
2164 - });
2154 + }
2155
2166 - return null;
2167 - }
2156 + function checkForUpdate(callback) {
2157 + getNetdataVersion(function(sha1) {
2158 + if(sha1 === null) callback(null, null);
2159
2169 - function notifyForUpdate(force) {
2170 - versionLog('<p>checking for updates...</p>');
2160 + getGithubLatestCommit(function(sha2) {
2161 + callback(sha1, sha2);
2162 + });
2163 + });
2164
2172 - var now = Date.now();
2165 + return null;
2166 + }
2167
2174 - if(typeof force === 'undefined' || force !== true) {
2175 - var last = loadLocalStorage('last_update_check');
2168 + function notifyForUpdate(force) {
2169 + versionLog('<p>checking for updates...</p>');
2170
2177 - if(typeof last === 'string')
2178 - last = parseInt(last);
2179 - else
2180 - last = 0;
2171 + var now = Date.now();
2172
2182 - if(now - last < 3600000 * 8) {
2183 - // no need to check it - too soon
2184 - return;
2185 - }
2186 - }
2173 + if(typeof force === 'undefined' || force !== true) {
2174 + var last = loadLocalStorage('last_update_check');
2175
2188 - checkForUpdate(function(sha1, sha2) {
2189 - var save = false;
2176 + if(typeof last === 'string')
2177 + last = parseInt(last);
2178 + else
2179 + last = 0;
2180
2191 - if(sha1 === null) {
2192 - save = false;
2193 - versionLog('<p><big>Failed to get your netdata version!</big></p><p>You can always get the latest version of netdata from <a href="https://github.com/firehol/netdata" target="_blank">its github page</a>.</p>');
2194 - }
2195 - else if(sha2 === null) {
2196 - save = false;
2197 - versionLog('<p><big>Failed to get the latest version from github.</big></p><p>You can always get the latest version of netdata from <a href="https://github.com/firehol/netdata" target="_blank">its github page</a>.</p>');
2198 - }
2199 - else if(sha1 === sha2) {
2200 - save = true;
2201 - versionLog('<p><big>You already have the latest version of netdata!</big></p><p>No update yet?<br/>Probably, we need some motivation to keep going on!</p><p>If you haven\'t already, <a href="https://github.com/firehol/netdata" target="_blank">give netdata a <b>Star</b> at its github page</a>.</p>');
2181 + if(now - last < 3600000 * 8) {
2182 + // no need to check it - too soon
2183 + return;
2184 + }
2185 }
2203 - else {
2204 - save = true;
2205 - var compare = 'https://github.com/firehol/netdata/compare/' + sha1.toString() + '...' + sha2.toString();
2206 -
2207 - versionLog('<p><big><strong>New version of netdata available!</strong></big></p><p>Latest version: ' + sha2.toString() + '</p><p><a href="' + compare + '" target="_blank">Click here for the changes log</a> since your installed version, and<br/><a href="https://github.com/firehol/netdata/wiki/Updating-Netdata" target="_blank">click here for directions on updating</a> your netdata installation.</p><p>We suggest to review the changes log for new features you may be interested, or important bug fixes you may need.<br/>Keeping your netdata updated, is generally a good idea.</p>');
2186
2209 - document.getElementById('update_badge').innerHTML = '!';
2210 - }
2187 + checkForUpdate(function(sha1, sha2) {
2188 + var save = false;
2189
2212 - if(save)
2213 - saveLocalStorage('last_update_check', now.toString());
2214 - });
2215 - }
2190 + if(sha1 === null) {
2191 + save = false;
2192 + versionLog('<p><big>Failed to get your netdata version!</big></p><p>You can always get the latest version of netdata from <a href="https://github.com/firehol/netdata" target="_blank">its github page</a>.</p>');
2193 + }
2194 + else if(sha2 === null) {
2195 + save = false;
2196 + versionLog('<p><big>Failed to get the latest version from github.</big></p><p>You can always get the latest version of netdata from <a href="https://github.com/firehol/netdata" target="_blank">its github page</a>.</p>');
2197 + }
2198 + else if(sha1 === sha2) {
2199 + save = true;
2200 + versionLog('<p><big>You already have the latest version of netdata!</big></p><p>No update yet?<br/>Probably, we need some motivation to keep going on!</p><p>If you haven\'t already, <a href="https://github.com/firehol/netdata" target="_blank">give netdata a <b>Star</b> at its github page</a>.</p>');
2201 + }
2202 + else {
2203 + save = true;
2204 + var compare = 'https://github.com/firehol/netdata/compare/' + sha1.toString() + '...' + sha2.toString();
2205
2217 - // ----------------------------------------------------------------------------
2218 -
2219 - function finalizePage() {
2220 - // resize all charts - without starting the background thread
2221 - // this has to be done while NETDATA is paused
2222 - // if we ommit this, the affix menu will be wrong, since all
2223 - // the Dom elements are initially zero-sized
2224 - NETDATA.parseDom();
2225 -
2226 - if(urlOptions.pan_and_zoom === true)
2227 - NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before);
2228 -
2229 - // ------------------------------------------------------------------------
2230 - // https://github.com/viralpatel/jquery.shorten/blob/master/src/jquery.shorten.js
2231 - $.fn.shorten = function(settings) {
2232 - "use strict";
2233 -
2234 - var config = {
2235 - showChars: 750,
2236 - minHideChars: 10,
2237 - ellipsesText: "...",
2238 - moreText: '<i class="fa fa-expand" aria-hidden="true"></i> show more information',
2239 - lessText: '<i class="fa fa-compress" aria-hidden="true"></i> show less information',
2240 - onLess: function() { NETDATA.onscroll(); },
2241 - onMore: function() { NETDATA.onscroll(); },
2242 - errMsg: null,
2243 - force: false
2244 - };
2206 + versionLog('<p><big><strong>New version of netdata available!</strong></big></p><p>Latest version: ' + sha2.toString() + '</p><p><a href="' + compare + '" target="_blank">Click here for the changes log</a> since your installed version, and<br/><a href="https://github.com/firehol/netdata/wiki/Updating-Netdata" target="_blank">click here for directions on updating</a> your netdata installation.</p><p>We suggest to review the changes log for new features you may be interested, or important bug fixes you may need.<br/>Keeping your netdata updated, is generally a good idea.</p>');
2207
2246 - if (settings) {
2247 - $.extend(config, settings);
2248 - }
2208 + document.getElementById('update_badge').innerHTML = '!';
2209 + }
2210
2250 - if ($(this).data('jquery.shorten') && !config.force) {
2251 - return false;
2252 - }
2253 - $(this).data('jquery.shorten', true);
2211 + if(save)
2212 + saveLocalStorage('last_update_check', now.toString());
2213 + });
2214 + }
2215
2255 - $(document).off("click", '.morelink');
2216 + // ----------------------------------------------------------------------------
2217 +
2218 + function finalizePage() {
2219 + // resize all charts - without starting the background thread
2220 + // this has to be done while NETDATA is paused
2221 + // if we ommit this, the affix menu will be wrong, since all
2222 + // the Dom elements are initially zero-sized
2223 + NETDATA.parseDom();
2224 +
2225 + if(urlOptions.pan_and_zoom === true)
2226 + NETDATA.globalPanAndZoom.setMaster(NETDATA.options.targets[0], urlOptions.after, urlOptions.before);
2227 +
2228 + // ------------------------------------------------------------------------
2229 + // https://github.com/viralpatel/jquery.shorten/blob/master/src/jquery.shorten.js
2230 + $.fn.shorten = function(settings) {
2231 + "use strict";
2232 +
2233 + var config = {
2234 + showChars: 750,
2235 + minHideChars: 10,
2236 + ellipsesText: "...",
2237 + moreText: '<i class="fa fa-expand" aria-hidden="true"></i> show more information',
2238 + lessText: '<i class="fa fa-compress" aria-hidden="true"></i> show less information',
2239 + onLess: function() { NETDATA.onscroll(); },
2240 + onMore: function() { NETDATA.onscroll(); },
2241 + errMsg: null,
2242 + force: false
2243 + };
2244
2257 - $(document).on({
2258 - click: function() {
2245 + if (settings) {
2246 + $.extend(config, settings);
2247 + }
2248
2260 - var $this = $(this);
2261 - if ($this.hasClass('less')) {
2262 - $this.removeClass('less');
2263 - $this.html(config.moreText);
2264 - $this.parent().prev().animate({'height':'0'+'%'}, 0, function () { $this.parent().prev().prev().show(); }).hide(0, function() {
2265 - config.onLess();
2266 - });
2267 -
2268 - } else {
2269 - $this.addClass('less');
2270 - $this.html(config.lessText);
2271 - $this.parent().prev().animate({'height':'100'+'%'}, 0, function () { $this.parent().prev().prev().hide(); }).show(0, function() {
2272 - config.onMore();
2273 - });
2274 - }
2249 + if ($(this).data('jquery.shorten') && !config.force) {
2250 return false;
2251 }
2277 - }, '.morelink');
2252 + $(this).data('jquery.shorten', true);
2253 +
2254 + $(document).off("click", '.morelink');
2255 +
2256 + $(document).on({
2257 + click: function() {
2258 +
2259 + var $this = $(this);
2260 + if ($this.hasClass('less')) {
2261 + $this.removeClass('less');
2262 + $this.html(config.moreText);
2263 + $this.parent().prev().animate({'height':'0'+'%'}, 0, function () { $this.parent().prev().prev().show(); }).hide(0, function() {
2264 + config.onLess();
2265 + });
2266 +
2267 + } else {
2268 + $this.addClass('less');
2269 + $this.html(config.lessText);
2270 + $this.parent().prev().animate({'height':'100'+'%'}, 0, function () { $this.parent().prev().prev().hide(); }).show(0, function() {
2271 + config.onMore();
2272 + });
2273 + }
2274 + return false;
2275 + }
2276 + }, '.morelink');
2277
2279 - return this.each(function() {
2280 - var $this = $(this);
2278 + return this.each(function() {
2279 + var $this = $(this);
2280
2282 - var content = $this.html();
2283 - var contentlen = $this.text().length;
2284 - if (contentlen > config.showChars + config.minHideChars) {
2285 - var c = content.substr(0, config.showChars);
2286 - if (c.indexOf('<') >= 0) // If there's HTML don't want to cut it
2287 - {
2288 - var inTag = false; // I'm in a tag?
2289 - var bag = ''; // Put the characters to be shown here
2290 - var countChars = 0; // Current bag size
2291 - var openTags = []; // Stack for opened tags, so I can close them later
2292 - var tagName = null;
2281 + var content = $this.html();
2282 + var contentlen = $this.text().length;
2283 + if (contentlen > config.showChars + config.minHideChars) {
2284 + var c = content.substr(0, config.showChars);
2285 + if (c.indexOf('<') >= 0) // If there's HTML don't want to cut it
2286 + {
2287 + var inTag = false; // I'm in a tag?
2288 + var bag = ''; // Put the characters to be shown here
2289 + var countChars = 0; // Current bag size
2290 + var openTags = []; // Stack for opened tags, so I can close them later
2291 + var tagName = null;
2292
2294 - for (var i = 0, r = 0; r <= config.showChars; i++) {
2295 - if (content[i] == '<' && !inTag) {
2296 - inTag = true;
2293 + for (var i = 0, r = 0; r <= config.showChars; i++) {
2294 + if (content[i] == '<' && !inTag) {
2295 + inTag = true;
2296
2298 - // This could be "tag" or "/tag"
2299 - tagName = content.substring(i + 1, content.indexOf('>', i));
2297 + // This could be "tag" or "/tag"
2298 + tagName = content.substring(i + 1, content.indexOf('>', i));
2299
2301 - // If its a closing tag
2302 - if (tagName[0] == '/') {
2300 + // If its a closing tag
2301 + if (tagName[0] == '/') {
2302
2303
2305 - if (tagName != '/' + openTags[0]) {
2306 - config.errMsg = 'ERROR en HTML: the top of the stack should be the tag that closes';
2307 - } else {
2308 - openTags.shift(); // Pops the last tag from the open tag stack (the tag is closed in the retult HTML!)
2309 - }
2304 + if (tagName != '/' + openTags[0]) {
2305 + config.errMsg = 'ERROR en HTML: the top of the stack should be the tag that closes';
2306 + } else {
2307 + openTags.shift(); // Pops the last tag from the open tag stack (the tag is closed in the retult HTML!)
2308 + }
2309
2311 - } else {
2312 - // There are some nasty tags that don't have a close tag like <br/>
2313 - if (tagName.toLowerCase() != 'br') {
2314 - openTags.unshift(tagName); // Add to start the name of the tag that opens
2310 + } else {
2311 + // There are some nasty tags that don't have a close tag like <br/>
2312 + if (tagName.toLowerCase() != 'br') {
2313 + openTags.unshift(tagName); // Add to start the name of the tag that opens
2314 + }
2315 }
2316 }
2317 - }
2318 - if (inTag && content[i] == '>') {
2319 - inTag = false;
2320 - }
2317 + if (inTag && content[i] == '>') {
2318 + inTag = false;
2319 + }
2320
2322 - if (inTag) { bag += content.charAt(i); } // Add tag name chars to the result
2323 - else {
2324 - r++;
2325 - if (countChars <= config.showChars) {
2326 - bag += content.charAt(i); // Fix to ie 7 not allowing you to reference string characters using the []
2327 - countChars++;
2328 - } else // Now I have the characters needed
2329 - {
2330 - if (openTags.length > 0) // I have unclosed tags
2321 + if (inTag) { bag += content.charAt(i); } // Add tag name chars to the result
2322 + else {
2323 + r++;
2324 + if (countChars <= config.showChars) {
2325 + bag += content.charAt(i); // Fix to ie 7 not allowing you to reference string characters using the []
2326 + countChars++;
2327 + } else // Now I have the characters needed
2328 {
2332 - //console.log('They were open tags');
2333 - //console.log(openTags);
2334 - for (j = 0; j < openTags.length; j++) {
2335 - //console.log('Cierro tag ' + openTags[j]);
2336 - bag += '</' + openTags[j] + '>'; // Close all tags that were opened
2337 -
2338 - // You could shift the tag from the stack to check if you end with an empty stack, that means you have closed all open tags
2329 + if (openTags.length > 0) // I have unclosed tags
2330 + {
2331 + //console.log('They were open tags');
2332 + //console.log(openTags);
2333 + for (j = 0; j < openTags.length; j++) {
2334 + //console.log('Cierro tag ' + openTags[j]);
2335 + bag += '</' + openTags[j] + '>'; // Close all tags that were opened
2336 +
2337 + // You could shift the tag from the stack to check if you end with an empty stack, that means you have closed all open tags
2338 + }
2339 + break;
2340 }
2340 - break;
2341 }
2342 }
2343 }
2344 + c = $('<div/>').html(bag + '<span class="ellip">' + config.ellipsesText + '</span>').html();
2345 + }else{
2346 + c+=config.ellipsesText;
2347 }
2345 - c = $('<div/>').html(bag + '<span class="ellip">' + config.ellipsesText + '</span>').html();
2346 - }else{
2347 - c+=config.ellipsesText;
2348 +
2349 + var html = '<div class="shortcontent">' + c +
2350 + '</div><div class="allcontent">' + content +
2351 + '</div><span><a href="javascript://nop/" class="morelink">' + config.moreText + '</a></span>';
2352 +
2353 + $this.html(html);
2354 + $this.find(".allcontent").hide(); // Hide all text
2355 + $('.shortcontent p:last', $this).css('margin-bottom', 0); //Remove bottom margin on last paragraph as it's likely shortened
2356 }
2357 + });
2358
2350 - var html = '<div class="shortcontent">' + c +
2351 - '</div><div class="allcontent">' + content +
2352 - '</div><span><a href="javascript://nop/" class="morelink">' + config.moreText + '</a></span>';
2359 + };
2360 + $(".chart-message").shorten();
2361 + // ------------------------------------------------------------------------
2362
2354 - $this.html(html);
2355 - $this.find(".allcontent").hide(); // Hide all text
2356 - $('.shortcontent p:last', $this).css('margin-bottom', 0); //Remove bottom margin on last paragraph as it's likely shortened
2363 + // callback for us to track PanAndZoom operations
2364 + NETDATA.globalPanAndZoom.callback = urlOptions.netdataPanAndZoomCallback;
2365 +
2366 + // let it run (update the charts)
2367 + NETDATA.unpause();
2368 +
2369 + // check if we have to jump to a specific section
2370 + scrollToId(urlOptions.hash.replace('#',''));
2371 +
2372 + if(urlOptions.chart !== null) {
2373 + NETDATA.alarms.scrollToChart(urlOptions.chart);
2374 + //urlOptions.hash = '#' + NETDATA.name2id('menu_' + charts[c].menu + '_submenu_' + charts[c].submenu);
2375 + //urlOptions.hash = '#chart_' + NETDATA.name2id(urlOptions.chart);
2376 + //console.log('hash = ' + urlOptions.hash);
2377 + }
2378 +
2379 + /* activate bootstrap sidebar (affix) */
2380 + $('#sidebar').affix({
2381 + offset: {
2382 + top: (isdemo())?150:0,
2383 + bottom: 0
2384 }
2385 });
2386
2360 - };
2361 - $(".chart-message").shorten();
2362 - // ------------------------------------------------------------------------
2363 -
2364 - // callback for us to track PanAndZoom operations
2365 - NETDATA.globalPanAndZoom.callback = urlOptions.netdataPanAndZoomCallback;
2387 + /* fix scrolling of very long affix lists
2388 + http://stackoverflow.com/questions/21691585/bootstrap-3-1-0-affix-too-long
2389 + */
2390 + $('#sidebar').on('affixed.bs.affix', function() {
2391 + $(this).removeAttr('style');
2392 + });
2393
2367 - // let it run (update the charts)
2368 - NETDATA.unpause();
2394 + /* activate bootstrap scrollspy (needed for sidebar) */
2395 + $(document.body).scrollspy({
2396 + target: '#sidebar',
2397 + offset: $(window).height() / 5 // controls the diff of the <hX> element to the top, to select it
2398 + });
2399
2370 - // check if we have to jump to a specific section
2371 - scrollToId(urlOptions.hash.replace('#',''));
2400 + // change the URL based on the current position of the screen
2401 + $('#sidebar').on('activate.bs.scrollspy', function (e) {
2402 + // console.log(e);
2403 + var el = $(e.target);
2404 + //if(el.find('ul').size() == 0) {
2405 + var hash = el.find('a').attr('href');
2406 + if(typeof hash === 'string' && hash.substring(0, 1) === '#' && urlOptions.hash.startsWith(hash + '_submenu_') === false) {
2407 + urlOptions.hash = hash;
2408 + //console.log(urlOptions.hash);
2409 + urlOptions.hashUpdate();
2410 + }
2411 + //else console.log('hash: not accepting ' + hash);
2412 + //}
2413 + //else console.log('el.find(): not found');
2414 + });
2415
2373 - if(urlOptions.chart !== null) {
2374 - NETDATA.alarms.scrollToChart(urlOptions.chart);
2375 - //urlOptions.hash = '#' + NETDATA.name2id('menu_' + charts[c].menu + '_submenu_' + charts[c].submenu);
2376 - //urlOptions.hash = '#chart_' + NETDATA.name2id(urlOptions.chart);
2377 - //console.log('hash = ' + urlOptions.hash);
2378 - }
2416 + document.getElementById('footer').style.display = 'block';
2417
2380 - /* activate bootstrap sidebar (affix) */
2381 - $('#sidebar').affix({
2382 - offset: {
2383 - top: (isdemo())?150:0,
2384 - bottom: 0
2385 - }
2386 - });
2387 -
2388 - /* fix scrolling of very long affix lists
2389 - http://stackoverflow.com/questions/21691585/bootstrap-3-1-0-affix-too-long
2390 - */
2391 - $('#sidebar').on('affixed.bs.affix', function() {
2392 - $(this).removeAttr('style');
2393 - });
2394 -
2395 - /* activate bootstrap scrollspy (needed for sidebar) */
2396 - $(document.body).scrollspy({
2397 - target: '#sidebar',
2398 - offset: $(window).height() / 5 // controls the diff of the <hX> element to the top, to select it
2399 - });
2400 -
2401 - // change the URL based on the current position of the screen
2402 - $('#sidebar').on('activate.bs.scrollspy', function (e) {
2403 - // console.log(e);
2404 - var el = $(e.target);
2405 - //if(el.find('ul').size() == 0) {
2406 - var hash = el.find('a').attr('href');
2407 - if(typeof hash === 'string' && hash.substring(0, 1) === '#' && urlOptions.hash.startsWith(hash + '_submenu_') === false) {
2408 - urlOptions.hash = hash;
2409 - //console.log(urlOptions.hash);
2410 - urlOptions.hashUpdate();
2411 - }
2412 - //else console.log('hash: not accepting ' + hash);
2413 - //}
2414 - //else console.log('el.find(): not found');
2415 - });
2418 + var update_options_modal = function() {
2419 + // console.log('update_options_modal');
2420
2417 - document.getElementById('footer').style.display = 'block';
2421 + var sync_option = function(option) {
2422 + var self = $('#' + option);
2423
2419 - var update_options_modal = function() {
2420 - // console.log('update_options_modal');
2424 + if(self.prop('checked') !== NETDATA.getOption(option)) {
2425 + // console.log('switching ' + option.toString());
2426 + self.bootstrapToggle(NETDATA.getOption(option)?'on':'off');
2427 + }
2428 + }
2429
2422 - var sync_option = function(option) {
2423 - var self = $('#' + option);
2430 + var theme_sync_option = function(option) {
2431 + var self = $('#' + option);
2432
2425 - if(self.prop('checked') !== NETDATA.getOption(option)) {
2426 - // console.log('switching ' + option.toString());
2427 - self.bootstrapToggle(NETDATA.getOption(option)?'on':'off');
2433 + self.bootstrapToggle(netdataTheme === 'slate'?'on':'off');
2434 }
2429 - }
2435
2431 - var theme_sync_option = function(option) {
2432 - var self = $('#' + option);
2436 + sync_option('eliminate_zero_dimensions');
2437 + sync_option('destroy_on_hide');
2438 + sync_option('async_on_scroll');
2439 + sync_option('parallel_refresher');
2440 + sync_option('concurrent_refreshes');
2441 + sync_option('sync_selection');
2442 + sync_option('sync_pan_and_zoom');
2443 + sync_option('stop_updates_when_focus_is_lost');
2444 + sync_option('smooth_plot');
2445 + sync_option('pan_and_zoom_data_padding');
2446 + sync_option('show_help');
2447 + theme_sync_option('netdata_theme_control');
2448 +
2449 + if(NETDATA.getOption('parallel_refresher') === false) {
2450 + $('#concurrent_refreshes_row').hide();
2451 + }
2452 + else {
2453 + $('#concurrent_refreshes_row').show();
2454 + }
2455 + };
2456 + NETDATA.setOption('setOptionCallback', update_options_modal);
2457 +
2458 + // handle options changes
2459 + $('#eliminate_zero_dimensions').change(function() { NETDATA.setOption('eliminate_zero_dimensions', $(this).prop('checked')); });
2460 + $('#destroy_on_hide').change(function() { NETDATA.setOption('destroy_on_hide', $(this).prop('checked')); });
2461 + $('#async_on_scroll').change(function() { NETDATA.setOption('async_on_scroll', $(this).prop('checked')); });
2462 + $('#parallel_refresher').change(function() { NETDATA.setOption('parallel_refresher', $(this).prop('checked')); });
2463 + $('#concurrent_refreshes').change(function() { NETDATA.setOption('concurrent_refreshes', $(this).prop('checked')); });
2464 + $('#sync_selection').change(function() { NETDATA.setOption('sync_selection', $(this).prop('checked')); });
2465 + $('#sync_pan_and_zoom').change(function() { NETDATA.setOption('sync_pan_and_zoom', $(this).prop('checked')); });
2466 + $('#stop_updates_when_focus_is_lost').change(function() {
2467 + urlOptions.update_always = !$(this).prop('checked');
2468 + urlOptions.hashUpdate();
2469
2434 - self.bootstrapToggle(netdataTheme === 'slate'?'on':'off');
2435 - }
2470 + NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always);
2471 + });
2472 + $('#smooth_plot').change(function() { NETDATA.setOption('smooth_plot', $(this).prop('checked')); });
2473 + $('#pan_and_zoom_data_padding').change(function() { NETDATA.setOption('pan_and_zoom_data_padding', $(this).prop('checked')); });
2474 + $('#show_help').change(function() {
2475 + urlOptions.help = $(this).prop('checked');
2476 + urlOptions.hashUpdate();
2477
2437 - sync_option('eliminate_zero_dimensions');
2438 - sync_option('destroy_on_hide');
2439 - sync_option('async_on_scroll');
2440 - sync_option('parallel_refresher');
2441 - sync_option('concurrent_refreshes');
2442 - sync_option('sync_selection');
2443 - sync_option('sync_pan_and_zoom');
2444 - sync_option('stop_updates_when_focus_is_lost');
2445 - sync_option('smooth_plot');
2446 - sync_option('pan_and_zoom_data_padding');
2447 - sync_option('show_help');
2448 - theme_sync_option('netdata_theme_control');
2449 -
2450 - if(NETDATA.getOption('parallel_refresher') === false) {
2451 - $('#concurrent_refreshes_row').hide();
2452 - }
2453 - else {
2454 - $('#concurrent_refreshes_row').show();
2455 - }
2456 - };
2457 - NETDATA.setOption('setOptionCallback', update_options_modal);
2458 -
2459 - // handle options changes
2460 - $('#eliminate_zero_dimensions').change(function() { NETDATA.setOption('eliminate_zero_dimensions', $(this).prop('checked')); });
2461 - $('#destroy_on_hide').change(function() { NETDATA.setOption('destroy_on_hide', $(this).prop('checked')); });
2462 - $('#async_on_scroll').change(function() { NETDATA.setOption('async_on_scroll', $(this).prop('checked')); });
2463 - $('#parallel_refresher').change(function() { NETDATA.setOption('parallel_refresher', $(this).prop('checked')); });
2464 - $('#concurrent_refreshes').change(function() { NETDATA.setOption('concurrent_refreshes', $(this).prop('checked')); });
2465 - $('#sync_selection').change(function() { NETDATA.setOption('sync_selection', $(this).prop('checked')); });
2466 - $('#sync_pan_and_zoom').change(function() { NETDATA.setOption('sync_pan_and_zoom', $(this).prop('checked')); });
2467 - $('#stop_updates_when_focus_is_lost').change(function() {
2468 - urlOptions.update_always = !$(this).prop('checked');
2469 - urlOptions.hashUpdate();
2470 -
2471 - NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always);
2472 - });
2473 - $('#smooth_plot').change(function() { NETDATA.setOption('smooth_plot', $(this).prop('checked')); });
2474 - $('#pan_and_zoom_data_padding').change(function() { NETDATA.setOption('pan_and_zoom_data_padding', $(this).prop('checked')); });
2475 - $('#show_help').change(function() {
2476 - urlOptions.help = $(this).prop('checked');
2477 - urlOptions.hashUpdate();
2478 -
2479 - NETDATA.setOption('show_help', urlOptions.help);
2480 - netdataReload();
2481 - });
2482 -
2483 - // this has to be the last
2484 - // it reloads the page
2485 - $('#netdata_theme_control').change(function() {
2486 - urlOptions.theme = $(this).prop('checked')?'slate':'white';
2487 - urlOptions.hashUpdate();
2488 -
2489 - if(setTheme(urlOptions.theme))
2478 + NETDATA.setOption('show_help', urlOptions.help);
2479 netdataReload();
2491 - });
2480 + });
2481
2493 - $('#updateModal').on('shown.bs.modal', function() {
2494 - notifyForUpdate(true);
2495 - });
2482 + // this has to be the last
2483 + // it reloads the page
2484 + $('#netdata_theme_control').change(function() {
2485 + urlOptions.theme = $(this).prop('checked')?'slate':'white';
2486 + urlOptions.hashUpdate();
2487
2497 - $('#alarmsModal').on('shown.bs.modal', function() {
2498 - NETDATA.pause(alarmsUpdateModal);
2499 - });
2488 + if(setTheme(urlOptions.theme))
2489 + netdataReload();
2490 + });
2491
2501 - $('#alarmsModal').on('hidden.bs.modal', function() {
2502 - NETDATA.unpause();
2503 - document.getElementById('alarms_active').innerHTML =
2504 - document.getElementById('alarms_all').innerHTML =
2505 - document.getElementById('alarms_log').innerHTML =
2506 - 'loading...';
2507 - });
2492 + $('#updateModal').on('shown.bs.modal', function() {
2493 + notifyForUpdate(true);
2494 + });
2495
2509 - $('#deleteRegistryModal').on('hidden.bs.modal', function() {
2510 - deleteRegistryGuid = null;
2511 - });
2496 + $('#alarmsModal').on('shown.bs.modal', function() {
2497 + NETDATA.pause(alarmsUpdateModal);
2498 + });
2499
2513 - if(isdemo()) {
2514 - // do not to give errors on netdata demo servers for 60 seconds
2515 - NETDATA.options.current.retries_on_data_failures = 60;
2500 + $('#alarmsModal').on('hidden.bs.modal', function() {
2501 + NETDATA.unpause();
2502 + document.getElementById('alarms_active').innerHTML =
2503 + document.getElementById('alarms_all').innerHTML =
2504 + document.getElementById('alarms_log').innerHTML =
2505 + 'loading...';
2506 + });
2507 +
2508 + $('#deleteRegistryModal').on('hidden.bs.modal', function() {
2509 + deleteRegistryGuid = null;
2510 + });
2511
2517 - if(urlOptions.nowelcome !== true) {
2512 + if(isdemo()) {
2513 + // do not to give errors on netdata demo servers for 60 seconds
2514 + NETDATA.options.current.retries_on_data_failures = 60;
2515 +
2516 + if(urlOptions.nowelcome !== true) {
2517 + setTimeout(function() {
2518 + $('#welcomeModal').modal();
2519 + }, 1000);
2520 + }
2521 +
2522 + // google analytics when this is used for the home page of the demo sites
2523 + // this does not run on user's installations
2524 setTimeout(function() {
2519 - $('#welcomeModal').modal();
2520 - }, 1000);
2525 + (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
2526 + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
2527 + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
2528 + })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
2529 +
2530 + ga('create', 'UA-64295674-3', 'auto');
2531 + ga('send', 'pageview');
2532 + }, 2000);
2533 }
2534 + else notifyForUpdate();
2535
2523 - // google analytics when this is used for the home page of the demo sites
2524 - // this does not run on user's installations
2525 - setTimeout(function() {
2526 - (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
2527 - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
2528 - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
2529 - })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
2530 -
2531 - ga('create', 'UA-64295674-3', 'auto');
2532 - ga('send', 'pageview');
2533 - }, 2000);
2536 + if(urlOptions.show_alarms === true)
2537 + setTimeout(function() { $('#alarmsModal').modal('show'); }, 1000);
2538 }
2535 - else notifyForUpdate();
2539
2537 - if(urlOptions.show_alarms === true)
2538 - setTimeout(function() { $('#alarmsModal').modal('show'); }, 1000);
2539 - }
2540 + function resetDashboardOptions() {
2541 + var help = NETDATA.options.current.show_help;
2542
2541 - function resetDashboardOptions() {
2542 - var help = NETDATA.options.current.show_help;
2543 + NETDATA.resetOptions();
2544 + if(setTheme('slate'))
2545 + netdataReload();
2546
2544 - NETDATA.resetOptions();
2545 - if(setTheme('slate'))
2546 - netdataReload();
2547 + if(help !== NETDATA.options.current.show_help)
2548 + netdataReload();
2549 + }
2550
2548 - if(help !== NETDATA.options.current.show_help)
2549 - netdataReload();
2550 - }
2551 + // callback to add the dashboard info to the
2552 + // parallel javascript downloader in netdata
2553 + var netdataPrepCallback = function() {
2554 + NETDATA.requiredCSS.push({
2555 + url: NETDATA.serverDefault + 'css/bootstrap-toggle-2.2.2.min.css',
2556 + isAlreadyLoaded: function() { return false; }
2557 + });
2558
2552 - // callback to add the dashboard info to the
2553 - // parallel javascript downloader in netdata
2554 - var netdataPrepCallback = function() {
2555 - NETDATA.requiredCSS.push({
2556 - url: NETDATA.serverDefault + 'css/bootstrap-toggle-2.2.2.min.css',
2557 - isAlreadyLoaded: function() { return false; }
2558 - });
2559 -
2560 - NETDATA.requiredJs.push({
2561 - url: NETDATA.serverDefault + 'lib/bootstrap-toggle-2.2.2.min.js',
2562 - isAlreadyLoaded: function() { return false; }
2563 - });
2564 -
2565 - NETDATA.requiredJs.push({
2566 - url: NETDATA.serverDefault + 'dashboard_info.js?v20161112-6',
2567 - async: false,
2568 - isAlreadyLoaded: function() { return false; }
2569 - });
2570 -
2571 - if(isdemo()) {
2572 - document.getElementById('masthead').style.display = 'block';
2573 - }
2574 - else {
2575 - if(urlOptions.update_always === true)
2576 - NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always);
2577 - }
2578 - }
2559 + NETDATA.requiredJs.push({
2560 + url: NETDATA.serverDefault + 'lib/bootstrap-toggle-2.2.2.min.js',
2561 + isAlreadyLoaded: function() { return false; }
2562 + });
2563
2580 - // our entry point
2581 - var netdataCallback = initializeDynamicDashboard;
2564 + NETDATA.requiredJs.push({
2565 + url: NETDATA.serverDefault + 'dashboard_info.js?v20161112-6',
2566 + async: false,
2567 + isAlreadyLoaded: function() { return false; }
2568 + });
2569
2583 -</script>
2570 + if(isdemo()) {
2571 + document.getElementById('masthead').style.display = 'block';
2572 + }
2573 + else {
2574 + if(urlOptions.update_always === true)
2575 + NETDATA.setOption('stop_updates_when_focus_is_lost', !urlOptions.update_always);
2576 + }
2577 + }
2578 +
2579 + // our entry point
2580 + var netdataCallback = initializeDynamicDashboard;
2581 + </script>
2582 +</head>
2583
2584 <body data-spy="scroll" data-target="#sidebar">
2585 <div id="loadOverlay" class="loadOverlay" style="background-color: #888; color: #888;">
@@ -2624,7 +2623,7 @@
2623 </div>
2624 <nav class="collapse navbar-collapse navbar-right" role="navigation">
2625 <ul class="nav navbar-nav">
2627 - <li><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal" title="alarms"><i class="fa fa-bell"></i></span>&nbsp;<span class="hidden-sm">Alarms&nbsp;</span><span id="alarms_count_badge" class="badge"></a></li>
2626 + <li><a href="#" class="btn" data-toggle="modal" data-target="#alarmsModal" title="alarms"><i class="fa fa-bell"></i>&nbsp;<span class="hidden-sm">Alarms&nbsp;</span><span id="alarms_count_badge" class="badge"></span></a></li>
2627 <li><a href="#" class="btn" data-toggle="modal" data-target="#optionsModal" title="dashboard settings"><i class="fa fa-sliders"></i>&nbsp;<span class="hidden-sm">Settings</span></a></li>
2628 <li><a href="https://github.com/firehol/netdata/wiki" class="btn" target="_blank" title="netdata community"><i class="fa fa-github"></i>&nbsp;<span class="hidden-sm hidden-md">Community</span></a></li>
2629 <li class="hidden-sm" id="updateButton"><a href="#" class="btn" data-toggle="modal" data-target="#updateModal" title="check for update"><i class="fa fa-cloud-download"></i><span id="update_badge" class="badge"></span>&nbsp;<span class="hidden-sm hidden-md">Update</span></a></li>
@@ -2648,7 +2647,6 @@
2647 </li>
2648 </ul>
2649 </nav>
2651 - </nav>
2650 </div>
2651 </nav>
2652
@@ -3138,9 +3136,9 @@
3136 <br/>
3137 All the browsers with the same ID will identify <b>you</b>, so please don't share this with others.
3138 <p style="text-align: center; padding-top: 10px; padding-bottom: 10px; line-height: 2;">
3141 - <form action="#">
3142 - <input type="text" class="form-control" id="switchRegistryPersonGUID" placeholder="your personal ID" maxlength="36" autocomplete="off" style="text-align: center; font-size: 1.4em;">
3143 - </form>
3139 + <form action="#">
3140 + <input type="text" class="form-control" id="switchRegistryPersonGUID" placeholder="your personal ID" maxlength="36" autocomplete="off" style="text-align: center; font-size: 1.4em;">
3141 + </form>
3142 </p>
3143 Either copy this ID and paste it to another browser, or paste here the ID you have taken from another browser.
3144 <p style="padding-top: 10px;"><small>