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/> <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/> <br/><span style="font-size: 18px">' + alarm.info + '</span><br/> <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/> <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/> <br/><span style="font-size: 18px">' + alarm.info + '</span><br/> <br/>role: <b>' + alarm.recipient + '</b><br/> <br/><b><i class="fa fa-line-chart" aria-hidden="true"></i></b><small> <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 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 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