@cryptotaxi247 / netdata-1 / commits / 23bf25a35

web notifications are now clickable; web notifications work on firefox; alarm modal now has anchor to show the related chart; menus are now also used for location hash

Costa Tsaousis (ktsaou) committed Sep 23, 2016 at 23:56 UTC 23bf25a3559f1716968b70b7d0362d8f9d1cb2ee
2 files changed +98 -50
web/dashboard.js
+72 -23
@@ -52,6 +52,15 @@
52 // global namespace
53 var NETDATA = window.NETDATA || {};
54
55 + NETDATA.name2id = function(s) {
56 + return s
57 + .replace(/ /g, '_')
58 + .replace(/\(/g, '_')
59 + .replace(/\)/g, '_')
60 + .replace(/\./g, '_')
61 + .replace(/\//g, '_');
62 + };
63 +
64 // ----------------------------------------------------------------------------------------------------------------
65 // Detect the netdata server
66
@@ -5590,13 +5599,22 @@
5599 // Registry of netdata hosts
5600
5601 NETDATA.alarms = {
5593 - notifications: false, // when true, the browser supports notifications (may not be granted though)
5594 - last_notification_id: 0, // the id of the last alarm_log we have raised an alarm for
5602 + onclick: null, // the callback to handle the click - it will be called with the alarm log entry
5603 + chart_div_offset: 100, // give that space above the chart when scrolling to it
5604 + chart_div_id_prefix: 'chart_', // the chart DIV IDs have this prefix (they should be NETDATA.name2id(chart.id))
5605 + chart_div_animation_duration: 0,// the duration of the animation while scrolling to a chart
5606 +
5607 + ms_penalty: 0, // the time penalty of the next alarm
5608 + ms_between_notifications: 500, // firefox moves the alarms off-screen (above, outside the top of the screen)
5609 + // if alarms are shown faster than: one per 500ms
5610 +
5611 + notifications: false, // when true, the browser supports notifications (may not be granted though)
5612 + last_notification_id: 0, // the id of the last alarm_log we have raised an alarm for
5613 // notifications_shown: new Array(),
5614
5597 - server: null, // the server to connect to for fetching alarms
5598 - current: null, // the list of raised alarms - updated in the background
5599 - callback: null, // a callback function to call every time the list of raised alarms is refreshed
5615 + server: null, // the server to connect to for fetching alarms
5616 + current: null, // the list of raised alarms - updated in the background
5617 + callback: null, // a callback function to call every time the list of raised alarms is refreshed
5618
5619 notify: function(entry) {
5620 // console.log('alarm ' + entry.unique_id);
@@ -5690,28 +5708,54 @@
5708 */
5709
5710 if(show === true) {
5693 - // show this notification
5694 - // console.log('new notification: ' + title);
5695 - var n = new Notification(title, {
5696 - body: entry.hostname + ' - ' + entry.chart + ' (' + entry.family + ') - ' + status + ': ' + entry.info,
5697 - tag: tag,
5698 - requireInteraction: interaction,
5699 - icon: NETDATA.serverDefault + icon,
5700 - data: data
5701 - // FIXME: does not seem to work on any web browser
5702 - // onclick: function(event) {
5703 - // event.preventDefault();
5704 - // console.log('clicked: ');
5705 - // console.log(event);
5706 - //}
5707 - });
5711
5709 - // console.log(n);
5710 - // NETDATA.alarms.notifications_shown.push(n);
5711 - // console.log(entry);
5712 + setTimeout(function() {
5713 + // show this notification
5714 + // console.log('new notification: ' + title);
5715 + var n = new Notification(title, {
5716 + body: entry.hostname + ' - ' + entry.chart + ' (' + entry.family + ') - ' + status + ': ' + entry.info,
5717 + tag: tag,
5718 + requireInteraction: interaction,
5719 + icon: NETDATA.serverDefault + icon,
5720 + data: data
5721 + });
5722 +
5723 + n.onclick = function(event) {
5724 + event.preventDefault();
5725 + NETDATA.alarms.onclick(event.target.data);
5726 + };
5727 +
5728 + // console.log(n);
5729 + // NETDATA.alarms.notifications_shown.push(n);
5730 + // console.log(entry);
5731 + }, NETDATA.alarms.ms_penalty);
5732 +
5733 + NETDATA.alarms.ms_penalty += NETDATA.alarms.ms_between_notifications;
5734 }
5735 },
5736
5737 + scrollToChart: function(chart_id) {
5738 + if(typeof chart_id === 'string') {
5739 + var offset = $('#' + NETDATA.alarms.chart_div_id_prefix + NETDATA.name2id(chart_id)).offset();
5740 + if(typeof offset !== 'undefined') {
5741 + $('html, body').animate({ scrollTop: offset.top - NETDATA.alarms.chart_div_offset }, NETDATA.alarms.chart_div_animation_duration);
5742 + return true;
5743 + }
5744 + }
5745 + return false;
5746 + },
5747 +
5748 + scrollToAlarm: function(alarm) {
5749 + if(typeof alarm === 'object') {
5750 + var ret = NETDATA.alarms.scrollToChart(alarm.chart);
5751 +
5752 + if(ret === true && NETDATA.options.page_is_visible === false)
5753 + window.focus();
5754 + // alert('netdata dashboard will now scroll to chart: ' + alarm.chart + '\n\nThis alarm opened to bring the browser window in front of the screen. Click on the dashboard to prevent it from appearing again.');
5755 + }
5756 +
5757 + },
5758 +
5759 notifyAll: function() {
5760 // console.log('FETCHING ALARM LOG');
5761 NETDATA.alarms.get_log(NETDATA.alarms.last_notification_id, function(data) {
@@ -5735,6 +5779,8 @@
5779 return 0;
5780 });
5781
5782 + NETDATA.alarms.ms_penalty = 0;
5783 +
5784 var len = data.length;
5785 while(len--) {
5786 if(data[len].unique_id > NETDATA.alarms.last_notification_id) {
@@ -5842,6 +5888,9 @@
5888 host = host.substring(0, host.length - 1);
5889 NETDATA.alarms.server = host;
5890
5891 + if(NETDATA.alarms.onclick === null)
5892 + NETDATA.alarms.onclick = NETDATA.alarms.scrollToAlarm;
5893 +
5894 if(netdataShowAlarms === true) {
5895 NETDATA.alarms.update_forever();
5896
web/index.html
+26 -27
@@ -622,7 +622,7 @@
622 </script>
623
624 <!-- load the dashboard manager - it will do the rest -->
625 - <script type="text/javascript" src="dashboard.js?v50"></script>
625 + <script type="text/javascript" src="dashboard.js?v51"></script>
626 </head>
627 <body data-spy="scroll" data-target="#sidebar">
628 <div id="loadOverlay" class="loadOverlay" style="background-color: #888; color: #888;">
@@ -2372,15 +2372,6 @@ function enrichChartData(chart) {
2372
2373 // ----------------------------------------------------------------------------
2374
2375 -function name2id(s) {
2376 - return s
2377 - .replace(/ /g, '_')
2378 - .replace(/\(/g, '_')
2379 - .replace(/\)/g, '_')
2380 - .replace(/\./g, '_')
2381 - .replace(/\//g, '_');
2382 -}
2383 -
2375 function headMain(charts, duration) {
2376 var head = '';
2377
@@ -2529,9 +2520,9 @@ function renderPage(menus, data) {
2520
2521 // generate an entry at the main menu
2522
2532 - var menuid = name2id(menu);
2523 + var menuid = NETDATA.name2id('menu_' + menu);
2524 sidebar += '<li class=""><a href="#' + menuid + '" onClick="return scrollToId(\'' + menuid + '\');">' + menus[menu].icon + ' ' + menus[menu].title + '</a><ul class="nav">';
2534 - html += '<div role="section"><div role="sectionhead"><h1 id="' + menuid + '" role="heading">' + menus[menu].title + '</h1></div><div id="menu_' + menuid + '" role="document">';
2525 + html += '<div role="section"><div role="sectionhead"><h1 id="' + menuid + '" role="heading">' + menus[menu].title + '</h1></div><div role="document">';
2526
2527 if(menus[menu].info !== null)
2528 html += menus[menu].info;
@@ -2549,9 +2540,9 @@ function renderPage(menus, data) {
2540 var submenu = sub[si++];
2541
2542 // generate an entry at the submenu
2552 - var submenuid = name2id(menu + '_' + submenu);
2543 + var submenuid = NETDATA.name2id('menu_' + menu + '_submenu_' + submenu);
2544 sidebar += '<li class><a href="#' + submenuid + '" onClick="return scrollToId(\'' + submenuid + '\');">' + menus[menu].submenus[submenu].title + '</a></li>';
2554 - shtml += '<div class="netdata-group-container" id="submenu_' + submenuid + '" style="display: inline-block; width: ' + pcent_width.toString() + '%"><h2 id="' + submenuid + '" class="netdata-chart-alignment" role="heading">' + menus[menu].submenus[submenu].title + '</h2>';
2545 + 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>';
2546
2547 if(menus[menu].submenus[submenu].info !== null)
2548 shtml += '<div class="chart-message netdata-chart-alignment" role="document">' + menus[menu].submenus[submenu].info + '</div>';
@@ -2572,12 +2563,12 @@ function renderPage(menus, data) {
2563 head += generateHeadCharts('heads', chart, duration);
2564
2565 // generate the chart
2575 - chtml += chartInfo(chart.context) + '<div data-netdata="' + chart.id + '"'
2566 + chtml += chartInfo(chart.context) + '<div id="chart_' + NETDATA.name2id(chart.id) + '" data-netdata="' + chart.id + '"'
2567 + ' data-width="' + pcent_width.toString() + '%"'
2568 + ' data-height="' + chartHeight(chart.context, options.chartsHeight).toString() + 'px"'
2569 + ' data-before="0"'
2570 + ' data-after="-' + duration.toString() + '"'
2580 - + ' data-id="' + name2id(options.hostname + '/' + chart.id) + '"'
2571 + + ' data-id="' + NETDATA.name2id(options.hostname + '/' + chart.id) + '"'
2572 + ' data-colors="' + anyAttribute(chartData, 'colors', chart.context, '') + '"'
2573 + ' role="application"></div>';
2574
@@ -2640,7 +2631,7 @@ function renderChartsAndMenu(data) {
2631
2632 // console.log(urlOptions.chart + ' === ' + c);
2633 if(urlOptions.chart === c) {
2643 - urlOptions.hash = '#' + name2id(charts[c].menu + '_' + charts[c].submenu)
2634 + urlOptions.hash = '#' + NETDATA.name2id(charts[c].menu + '_' + charts[c].submenu)
2635 // console.log('hash = ' + urlOptions.hash);
2636 }
2637 }
@@ -2746,7 +2737,7 @@ function alarmsUpdateModal() {
2737 function alarm_to_html(alarm, full) {
2738 var chart = options.data.charts[alarm.chart];
2739
2749 - 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></td>'
2740 + 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>'
2741 + '<td><table class="table">'
2742 + ((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>'):'')
2743 + ((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>'):'');
@@ -2961,10 +2952,15 @@ function alarmsCallback(data) {
2952 document.getElementById('alarms_count_badge').innerHTML = '';
2953 }
2954
2964 -function downloadAllCharts(netdata_url) {
2955 +function initializeDynamicDashboard(netdata_url) {
2956 if(typeof netdata_url === 'undefined' || netdata_url === null)
2957 netdata_url = NETDATA.serverDefault;
2958
2959 + // initialize clickable alarms
2960 + NETDATA.alarms.chart_div_offset = 100;
2961 + NETDATA.alarms.chart_div_id_prefix = 'chart_';
2962 + NETDATA.alarms.chart_div_animation_d0uration = 0;
2963 +
2964 NETDATA.pause(function() {
2965 $("#loadOverlay").css("display","none");
2966
@@ -3289,15 +3285,18 @@ function finalizePage() {
3285
3286 // change the URL based on the current position of the screen
3287 $('#sidebar').on('activate.bs.scrollspy', function (e) {
3288 + // console.log(e);
3289 var el = $(e.target);
3293 - if(el.find('ul').size() == 0) {
3294 - var hash = el.find('a').attr('href');
3295 - if(typeof hash === 'string' && hash.substring(0, 1) == '#') {
3296 - urlOptions.hash = hash;
3297 - // console.log(urlOptions.hash);
3298 - netdataHashUpdate();
3299 - }
3290 + //if(el.find('ul').size() == 0) {
3291 + var hash = el.find('a').attr('href');
3292 + if(typeof hash === 'string' && hash.substring(0, 1) === '#' && urlOptions.hash.startsWith(hash + '_submenu_') === false) {
3293 + urlOptions.hash = hash;
3294 + console.log(urlOptions.hash);
3295 + netdataHashUpdate();
3296 }
3297 + else console.log('hash: not accepting ' + hash);
3298 + //}
3299 + //else console.log('el.find(): not found');
3300 });
3301
3302 document.getElementById('footer').style.display = 'block';
@@ -3421,7 +3420,7 @@ function resetDashboardOptions() {
3420 netdataReload();
3421 }
3422
3424 -downloadAllCharts();
3423 +initializeDynamicDashboard();
3424
3425 </script>
3426