Remove dash-example, place in community repo (#11077)
* Remove dash-example, place in community repo * Remove Makefile reference to dash-example.html
Thomas Anderson committed
May 10, 2021 at 10:00 UTC
cd089089f75a4ebc0069415fa50e0e3fd69e1460
3 files changed
-1118
web/gui/Makefile.am
-1
@@ -67,7 +67,6 @@ dist_web_DATA = \
67
refresh-badges.js \
68
sitemap.xml \
69
tv.html \
70
- dash-example.html \
70
version.txt \
71
$(NULL)
72
web/gui/custom/README.md
-62
@@ -69,70 +69,8 @@ header:
69
</html>
70
```
71
72
-## Dash (Multi-Host Dashboard)
73
-
74
-`dash-example.html` is an all-in-one page that automatically fetches graphs from all your hosts. Just add your graphs and charts (or use the defaults) one time using the `dash-*` syntax, and your selections will be automatically replicated for all of your hosts; showing alarms and graphs for all your hosts on **one page!**
75
-
76
-__**Dash will only work if you have implemented netdata streaming using `stream.conf`. It is not part of Netdata Cloud.**__
77
-
78
-`dash-example.html` was created as an experiment to demonstrate the capabilities of netdata in a multi-host environment. If you desire more features, submit a pull request or check out Netdata Cloud!
79
-
80
-### Configure Dash
81
-
82
-First, rename the file so it doesn't get overwritten. For instance, with a webroot at `/usr/share/netdata/web`:
83
-```bash
84
-cp /usr/share/netdata/web/dash-example.html /usr/share/netdata/web/dash.html
85
-```
86
-
87
-> NOTE: Ensure the owner/permissions match those in the rest of the files in the directory. Usually `netdata:netdata` and `0644`.
88
-
89
-Find and change the following lines in `dash.html` to reflect your Netdata URLs. The `REVERSE_PROXY_URL` is optional and only used if you access your Netdata dashboard through a reverse proxy. If it is not set, it defaults to the `NETDATA_HOST` URL.
90
-
91
-```js
92
-/**
93
- * Netdata URLS. If you use a reverse proxy, add it and uncomment the line below
94
- */
95
-NETDATA_HOST = 'https://localhost:19999';
96
-// REVERSE_PROXY_URL = 'https://my-domain.com/stats'
97
-```
98
-
99
-### The `dash-*` Syntax
100
-
101
-If you want to change the graphs or styling to fit your needs, just add an element to the page as shown. Child divs will be generated to create your graph/chart, and charts are replicated for each streamed host.
102
-```
103
-<div class="dash-graph" <---- Use class dash-graph for line graphs, etc
104
- data-dash-netdata="system.cpu" <---- REQUIRED: Use data-dash-netdata to set the data source
105
- data-dygraph-valuerange="[0, 100]"> <---- OPTIONAL: This overrides the default config. Any other data-* attributes will
106
-</div> be added to the generated div, so you can set any desired options here
107
-
108
-<div class="dash-chart" <---- Use class dash-chart for pie charts, etc. CHARTS ARE SQUARE
109
- data-dash-netdata="system.io" <---- REQUIRED: Use data-dash-netdata to set the data source
110
- data-dimensions="in" <---- Use this to override or append default options
111
- data-title="Disk Read" <---- Use this to override or append default options
112
- data-common-units="dash.io"> <---- Use this to override or append default options
113
-</div>
114
-```
115
-
116
-To change the sizes of graphs and charts, find the `DASH_OPTIONS` object in `dash.html` and set your preferences:
117
-```js
118
-/*
119
- * Change your graph/chart dimensions here. Host columns will automatically adjust.
120
- * Charts are square! Their width is the same as their height.
121
- */
122
-DASH_OPTIONS = {
123
- graph_width: '40em',
124
- graph_height: '20em',
125
- chart_width: '10em' // Charts are square
126
-}
127
-```
128
-
129
-To change the display order of your hosts, which is saved in localStorage, click the settings gear in the lower right corner
130
-
131
-We hope you like it!
132
-
72
---
73
135
-
74
## dashboard.js
75
76
To add Netdata charts to any web page (dedicated to Netdata or not), you need to
web/gui/dash-example.html
deleted
-1055
@@ -1,1055 +0,0 @@
1
-<!DOCTYPE html>
2
-<html lang="en">
3
-<head>
4
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
5
- <meta charset="utf-8">
6
- <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
7
- <meta name="viewport" content="width=device-width, initial-scale=1">
8
- <meta name="apple-mobile-web-app-capable" content="yes">
9
- <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
10
-</head>
11
-<body>
12
- <script type="application/javascript">
13
- /*****************
14
- * CONFIGURATION *
15
- *****************/
16
-
17
- /**
18
- * Netdata URLS. If you use a reverse proxy, add it and uncomment the line below
19
- */
20
- NETDATA_HOST = 'https://localhost:19999';
21
- // REVERSE_PROXY_URL = 'https://my-domain.com/stats'
22
-
23
- /**
24
- * Whether to use dark theme in PickNSort. Default is true
25
- */
26
- DARK_THEME = true;
27
-
28
- /**
29
- * How often alarms are refreshed in seconds
30
- */
31
- ALARM_REFRESH_INTERVAL = 6;
32
-
33
- /*
34
- * Change your graph/chart dimensions here. Host columns will automatically adjust.
35
- * Charts are square! Their width is the same as their height.
36
- */
37
- DASH_OPTIONS = {
38
- graph_width: '40em',
39
- graph_height: '20em',
40
- chart_width: '10em' // Charts are square
41
- }
42
-
43
- /*****************
44
- * END CONFIG *
45
- *****************/
46
- </script>
47
-
48
-
49
- <div id="alarms" class="collapsed">
50
- <div class="alarm-collapse-button" onclick="dash.toggle_alarm_collapse()">›</div>
51
- <span class="alarm-count"></span>
52
- <h1>Alarms</h1>
53
- <div class="alarm-host-list"></div>
54
- <div class="settings-button" onclick="dash.reorder_hosts()">⚙︎</div>
55
- </div>
56
- <div id="dash">
57
- <div class="netdata-host-stats-container template">
58
- <div class="netdata-host-name">host</div>
59
- <div class="netdata-host-stats">
60
- <div class="dash-graph"
61
- data-dash-netdata="system.cpu"
62
- data-dygraph-valuerange="[0, 100]">
63
- </div>
64
- <div class="dash-graph"
65
- data-dash-netdata="system.load">
66
- </div>
67
- <div class="dash-graph"
68
- data-dash-netdata="system.ram">
69
- </div>
70
- <div class="dash-graph"
71
- data-dash-netdata="disk_space._">
72
- </div>
73
- <div class="dash-graph"
74
- data-dash-netdata="system.net">
75
- </div>
76
- <div class="dash-graph"
77
- data-dash-netdata="system.processes">
78
- </div>
79
- <div class="dash-graph"
80
- data-dash-netdata="apps.cpu">
81
- </div>
82
- <div class="dash-graph"
83
- data-dash-netdata="apps.mem">
84
- </div>
85
- <div class="dash-charts">
86
- <div class="dash-chart"
87
- data-dash-netdata="system.io"
88
- data-dimensions="in"
89
- data-title="Disk Read"
90
- data-common-units="dash.io">
91
- </div>
92
- <div class="dash-chart"
93
- data-dash-netdata="system.io"
94
- data-dimensions="out"
95
- data-title="Disk Write"
96
- data-common-units="dash.io">
97
- </div>
98
- <div class="dash-chart"
99
- data-dash-netdata="system.cpu"
100
- data-chart-library="gauge"
101
- data-title="CPU"
102
- data-units="%"
103
- data-gauge-max-value="100"
104
- data-colors="#22AA99"
105
- data-gauge-stroke-color="#373B40">
106
- </div>
107
- <div class="dash-chart"
108
- data-dash-netdata="system.net"
109
- data-dimensions="received"
110
- data-title="Net Inbound"
111
- data-common-units="dash.net">
112
- </div>
113
- <div class="dash-chart"
114
- data-dash-netdata="system.net"
115
- data-dimensions="sent"
116
- data-title="Net Outbound"
117
- data-common-units="dash.net">
118
- </div>
119
- <div class="dash-chart"
120
- data-dash-netdata="system.ram"
121
- data-dimensions="used|buffers|active|wired"
122
- data-append-options="percentage"
123
- data-title="Used RAM"
124
- data-units="%"
125
- data-easypiechart-max-value="100"
126
- data-colors="#EE9911">
127
- </div>
128
- </div>
129
- </div>
130
- </div>
131
- </div>
132
-</body>
133
-<script src="https://code.jquery.com/jquery-3.6.0.min.js"
134
- integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
135
- crossorigin="anonymous">
136
-</script>
137
-<script type="application/javascript">
138
-class PickNSort {
139
- // PickNSort.js
140
-
141
- constructor (dark) {
142
- this.items = [];
143
- this.callback = function (output, disabled) { console.log(output, disabled) };
144
- this.reset = function () { this.items = [] };
145
- this.last_output = {
146
- enabled: [],
147
- disabled: []
148
- }
149
-
150
- this.add_css_to_page(dark);
151
- }
152
-
153
- create_modal () {
154
- $("<div></div>", {
155
- id: "picknsort-container"
156
- }).appendTo('body');
157
-
158
- $("<div></div>", {
159
- id: 'picknsort-window'
160
- }).appendTo('#picknsort-container');
161
-
162
- $("<div></div>", {
163
- id: "picknsort-close-button",
164
- text: '\u2573'
165
- }).appendTo('#picknsort-window');
166
-
167
- $("<div></div>", {
168
- id: "picknsort-item-list"
169
- }).appendTo('#picknsort-window')
170
-
171
- $("<div></div>", {
172
- text: "Apply",
173
- id: "picknsort-apply-button"
174
- }).appendTo('#picknsort-window');
175
-
176
- $("<div></div>", {
177
- text: "Reset",
178
- id: "picknsort-reset-button"
179
- }).appendTo('#picknsort-window');
180
-
181
- $('#picknsort-close-button').click(function () {
182
- picknsort.destroy_modal();
183
- picknsort.callback(null, null);
184
- });
185
-
186
- $('#picknsort-apply-button').click(function () {
187
- picknsort.apply();
188
- });
189
-
190
- $('#picknsort-reset-button').click(function () {
191
- picknsort.reset();
192
- });
193
- }
194
-
195
- destroy_modal () {
196
- $('#picknsort-container').remove();
197
- }
198
-
199
- populate_list () {
200
- this.clear_list();
201
-
202
- for (var i=0, len=this.items.length; i<len; i++) {
203
- this.draw_item(i);
204
- }
205
- }
206
-
207
- draw_item (index) {
208
- var item = this.items[index];
209
-
210
- var $item = $("<div></div>").addClass("picknsort-item");
211
-
212
- var $checkbox= $("<div></div>").addClass('picknsort-item-checkbox-wrapper');
213
-
214
- $("<input>", {
215
- type: "checkbox",
216
- checked: item.enabled
217
- }).addClass('picknsort-item-checkbox')
218
- .appendTo($checkbox);
219
-
220
- var $value = $("<div></div>", {
221
- text: item.value
222
- }).addClass("picknsort-item-value");
223
-
224
- var $nav = $("<div></div>").addClass("picknsort-item-nav")
225
- .append("<div class='picknsort-item-down' data-index='" + index + "' onclick='picknsort.shift_down(this)'>↓</div>")
226
- .append("<div class='picknsort-item-up' data-index='" + index + "' onclick='picknsort.shift_up(this)'>↑</div>");
227
-
228
- $item.append($checkbox).append($value).append($nav).appendTo('#picknsort-item-list');
229
- }
230
-
231
- clear_list () {
232
- $('#picknsort-item-list').html('');
233
- }
234
-
235
- popup (callback, reset, options={}) {
236
- this.callback = callback || this.callback;
237
- this.reset = reset || this.reset;
238
- if (!options.enabled) {
239
- options.enabled = this.last_output.enabled;
240
- }
241
- if (!options.disabled) {
242
- options.disabled = this.last_output.disabled;
243
- }
244
-
245
- this.parse_items(options.enabled, options.disabled);
246
- if (this.items.length) {
247
- this.create_modal();
248
- this.populate_list();
249
- }
250
-
251
- }
252
-
253
- parse_items (enabled, disabled) {
254
- this.items = [];
255
-
256
- for (var i=0, len=enabled.length; i<len; i++) {
257
- this.items.push({
258
- value: enabled[i],
259
- enabled: true
260
- });
261
- }
262
-
263
- for (var i=0, len=disabled.length; i<len; i++) {
264
- this.items.push({
265
- value: disabled[i],
266
- enabled: false
267
- });
268
- }
269
- }
270
-
271
- shift_down (el) {
272
- var index = $(el).data('index');
273
- if (index === this.items.length - 1) {
274
- return;
275
- }
276
- var temp = this.items[index];
277
- this.items[index] = this.items[index + 1];
278
- this.items[index + 1] = temp;
279
- this.move_element_down(index);
280
- }
281
-
282
- shift_up (el) {
283
- var index = $(el).data('index');
284
- if (index === 0) {
285
- return;
286
- }
287
- var temp = this.items[index];
288
- this.items[index] = this.items[index - 1];
289
- this.items[index - 1] = temp;
290
- this.move_element_up(index);
291
- }
292
-
293
- move_element_up (index) {
294
- var $src = $('.picknsort-item:eq(' + index + ')');
295
- var $dest = $('.picknsort-item:eq(' + (index-1) + ')');
296
- $src.insertBefore($dest);
297
-
298
- // Update data-index
299
- $src.find('.picknsort-item-down, .picknsort-item-up').data("index", index-1);
300
- $dest.find('.picknsort-item-down, .picknsort-item-up').data("index", index);
301
- }
302
-
303
- move_element_down (index) {
304
- var $src = $('.picknsort-item:eq(' + index + ')');
305
- var $dest = $('.picknsort-item:eq(' + (index+1) + ')');
306
- $src.insertAfter($dest);
307
-
308
- // Update data-index
309
- $src.find('.picknsort-item-down, .picknsort-item-up').data("index", index+1);
310
- $dest.find('.picknsort-item-down, .picknsort-item-up').data("index", index);
311
- }
312
-
313
- apply () {
314
- var out = [];
315
- for (var i=0, len=this.items.length; i<len; i++) {
316
- out.push(this.items[i].value);
317
- }
318
- var disabled = [];
319
- $('input.picknsort-item-checkbox:not(:checked)').each(function (elindex) {
320
- var itemindex = $('input.picknsort-item-checkbox').index($(this));
321
- // Adjust for deleted elements
322
- var spliceindex = itemindex - (1 * elindex);
323
- var del = out.splice(spliceindex, 1);
324
- disabled.push(del[0]);
325
- });
326
- this.callback(out, disabled);
327
- this.last_output = {
328
- enabled: out,
329
- disabled: disabled
330
- }
331
- this.destroy_modal();
332
- }
333
-
334
- add_css_to_page (dark) {
335
- /*
336
- * You can change your PickNSort theme colors here. Not sure how well it will work...
337
- */
338
- var light_theme = {
339
- windowbg: "#FFF",
340
- itembg: "#F4F4F4",
341
- itemcolor: "#535353"
342
- }
343
- var dark_theme = {
344
- windowbg: "#444",
345
- itembg: "#333",
346
- itemcolor: "#DBDBDB"
347
- }
348
-
349
- var current_theme = (dark) ? dark_theme : light_theme;
350
-
351
- var css_string = `
352
-#picknsort-container {
353
- position: fixed;
354
- z-index: 9999 !important;
355
- top: 0;
356
- bottom: 0;
357
- left: 0;
358
- right: 0;
359
- background: rgba(0,0,0,0.5);
360
-}
361
-#picknsort-window {
362
- max-height: 90vh;
363
- width: 40em;
364
- background: ${current_theme.windowbg};
365
- position: absolute;
366
- top: 5em;
367
- left: calc(50% - 20em);
368
- padding: 2em;
369
- padding-top: 4em;
370
-}
371
-#picknsort-close-button {
372
- position: absolute;
373
- top: 1em;
374
- font-size: 1.5em;
375
- color: #666;
376
- right: 1em;
377
- cursor: pointer;
378
-}
379
-#picknsort-item-list {
380
- max-height: 60vh;
381
- overflow-y: scroll;
382
- margin-bottom: 1em;
383
-}
384
-#picknsort-apply-button, #picknsort-reset-button {
385
- text-align: center;
386
- font-size: 1.5em;
387
- padding: 1em;
388
- background: rgb(106, 232, 165);
389
- font-weight: bold;
390
- color: #FFF;
391
- cursor: pointer;
392
- margin-top: 1em;
393
-}
394
-#picknsort-reset-button {
395
- background: #CCC;
396
-}
397
-.picknsort-item {
398
- padding: 1em;
399
- border-top: solid 1px #CCC;
400
- margin-bottom: 1em;
401
- position: relative;
402
- background: ${current_theme.itembg};
403
- color: ${current_theme.itemcolor}
404
-}
405
-.picknsort-item-checkbox-wrapper {
406
- position: absolute;
407
- top: 0;
408
- left: 0;
409
- bottom: 0;
410
- width: 3em;
411
- text-align: center;
412
-}
413
-.picknsort-item-checkbox {
414
- transform: scale(1.5);
415
- margin-top: 1.3em !important;
416
-}
417
-.picknsort-item-value {
418
- margin-left: 3em;
419
-}
420
-.picknsort-item-nav {
421
- font-size: 2em;
422
- position: absolute;
423
- right: 0;
424
- top: 0;
425
- bottom: 0;
426
- color: #CCC;
427
- cursor: pointer;
428
-}
429
-.picknsort-item-down, .picknsort-item-up {
430
- display: inline-block;
431
- padding: 0em 0.5em;
432
- height: calc(100% - 0.2em);
433
-}
434
- ` // End multiline string
435
-
436
-
437
- $("<style>")
438
- .prop("type", "text/css")
439
- .html(css_string).appendTo("head");
440
- }
441
-}
442
-</script>
443
-<script type="application/javascript">
444
- // Dash JS
445
-
446
- function picknsort_setup () {
447
- if (localStorage.getItem('netdata_ordered_hosts')) {
448
- picknsort.last_output = JSON.parse(localStorage.getItem('netdata_ordered_hosts'));
449
- } else {
450
- picknsort.last_output = {
451
- enabled: dash.netdata_info.mirrored_hosts,
452
- disabled: []
453
- }
454
- }
455
- }
456
-
457
- function load_dashboard_js () {
458
- // Import dashboard.js
459
- $.ajax({
460
- url: dash.base_url + '/dashboard.js',
461
- cache: true,
462
- dataType: "script",
463
- success: function () {
464
- console.log("Loaded dashboard.js");
465
- setTimeout(function () {
466
- $('#alarms').css("visibility", "visible");
467
- }, 400);
468
- }
469
- });
470
- }
471
-
472
- class Dash {
473
- constructor (base_url, link_base_url) {
474
- this.base_url = base_url; // URL of netdata host, with port
475
- this.link_base_url = link_base_url || base_url; // Reverse proxy URL (Optional)
476
- this.current_alarms = {};
477
- this.new_alarms = {};
478
- this.first_build = true;
479
- this.options = DASH_OPTIONS;
480
- }
481
-
482
- reorder_hosts () {
483
- picknsort.popup(dash.update_ordered_hosts, dash.find_new_hosts);
484
- }
485
-
486
- get_enabled_hosts () {
487
- try {
488
- return JSON.parse(localStorage.getItem('netdata_ordered_hosts')).enabled
489
- } catch (e) {
490
- return this.netdata_info.mirrored_hosts.sort();
491
- }
492
- }
493
-
494
- get_ordered_hosts () {
495
- try {
496
- return JSON.parse(localStorage.getItem('netdata_ordered_hosts'));
497
- } catch (e) {
498
- return null;
499
- }
500
- }
501
-
502
- set_ordered_hosts (hosts) {
503
- localStorage.setItem('netdata_ordered_hosts', JSON.stringify(hosts));
504
- location.reload();
505
- }
506
-
507
- update_ordered_hosts (enabled, disabled) {
508
- if (enabled === null && disabled === null) {
509
- return;
510
- }
511
- dash.set_ordered_hosts({
512
- enabled: enabled,
513
- disabled: disabled
514
- });
515
- }
516
-
517
- find_new_hosts () {
518
- var newhosts = dash.netdata_info.mirrored_hosts.slice();
519
- var currenthosts = dash.get_ordered_hosts();
520
-
521
- for (var i=0,len=currenthosts.enabled.length; i<len; i++) {
522
- var found = newhosts.indexOf(currenthosts.enabled[i]);
523
-
524
- if (found > -1) {
525
- newhosts.splice(found, 1);
526
- } else {
527
- currenthosts.enabled.splice(i, 1);
528
- }
529
- }
530
-
531
- for (var i=0,len=currenthosts.disabled.length; i<len; i++) {
532
- var found = newhosts.indexOf(currenthosts.disabled[i]);
533
-
534
- if (found > -1) {
535
- newhosts.splice(found, 1);
536
- } else {
537
- currenthosts.enabled.splice(i, 1);
538
- }
539
- }
540
-
541
- for (var i=0,len=newhosts.length; i<len; i++) {
542
- currenthosts.enabled.push(newhosts[i]);
543
- }
544
-
545
- dash.set_ordered_hosts(currenthosts);
546
- }
547
-
548
- get_host_url (hostname, link) {
549
- var base = ( link ) ? this.link_base_url : this.base_url;
550
- return (hostname) ? base + '/host/' + hostname : base;
551
- }
552
-
553
- get_api_url (hostname) {
554
- return this.get_host_url(hostname) + '/api/v1'
555
- }
556
-
557
-
558
- init (callback) {
559
- var that = this;
560
- $.get(this.get_api_url() + '/info', function (data) {
561
- that.netdata_info = data;
562
- picknsort_setup()
563
- that.build();
564
- callback();
565
- });
566
- }
567
-
568
- digest () {
569
- this.fetch_active_alarms();
570
- this.fix_layout_errors();
571
- }
572
-
573
- build () {
574
- // Fix vertically misaligned stats on load error
575
- $('.dash-graph').css({
576
- height: this.options.graph_height,
577
- width: this.options.graph_width
578
- });
579
- $('.dash-chart').css({
580
- height: this.options.chart_width, // Charts are square
581
- width: this.options.chart_width
582
- });
583
-
584
- // Fix chart alignment
585
- $('.netdata-host-stats-container').css({
586
- width: 'calc(' + this.options.graph_width + ' + (2 * ' + $('.netdata-host-stats-container').css('padding-left') + '))'
587
- });
588
-
589
- var $template = $('.netdata-host-stats-container').first();
590
-
591
- var hosts = this.get_enabled_hosts();
592
-
593
- for (var i=0, len=hosts.length; i<len; i++) {
594
- var hostname = hosts[i];
595
- $('#alarms .alarm-host-list').append('<div class="host-alarms ' + hostname + '"><a onclick="return dash.scroll_to_host_stats(' + "'" + hostname + "'" + ')" href="#' + hostname + '"><h2>' + hostname + '</h2></a></div>');
596
-
597
- $template.clone().removeClass('template').attr('id', hostname).appendTo('#dash');
598
- var $newest = $('.netdata-host-stats-container').last();
599
- this.build_stats($newest, hostname);
600
- }
601
-
602
-
603
- if (this.first_build === true) {
604
- this.remove_template_elements();
605
- this.first_build = false;
606
- }
607
- }
608
-
609
- build_stats ($hoststats, hostname) {
610
- var that = this;
611
-
612
- $hoststats.find('.netdata-host-stats .dash-graph').each(function () {
613
- that.build_graph($(this), hostname);
614
- });
615
-
616
- $hoststats.find('.netdata-host-stats .dash-chart').each(function () {
617
- that.build_chart($(this), hostname);
618
- });
619
-
620
- $hoststats.find('.netdata-host-name').html('<a target="_blank" href="' + that.get_host_url(hostname, true) + '/">' + hostname + '</a>');
621
- }
622
-
623
- build_graph ($wrapper, hostname) {
624
- var that = this;
625
- var $graph = $('<div>', {
626
- // Defaults
627
- 'data-netdata': $wrapper.attr('data-dash-netdata'),
628
- 'data-host': that.get_host_url(hostname),
629
- 'data-before': '0',
630
- 'data-after': '-540',
631
- 'role': 'application',
632
- 'data-width': that.options.graph_width,
633
- 'data-height': that.options.graph_height
634
- });
635
-
636
- $.each($wrapper[0].attributes, function (key, node) {
637
- if ( node.name.match(/^data-(?!dash).*/ ) ) {
638
- $graph.attr(node.name, node.value);
639
- }
640
- });
641
-
642
- $graph.appendTo($wrapper);
643
- }
644
-
645
- build_chart ($wrapper, hostname) {
646
- var that = this;
647
- var $graph = $('<div>', {
648
- // Defaults
649
- 'data-netdata': $wrapper.attr('data-dash-netdata'),
650
- 'data-host': that.get_host_url(hostname),
651
- 'data-before': '0',
652
- 'data-after': '-540',
653
- 'data-points': '540',
654
- 'role': 'application',
655
- 'data-width': that.options.chart_width,
656
- 'data-title': ' ',
657
- 'data-easypiechart-trackcolor': "#373B40",
658
- 'data-chart-library': 'easypiechart'
659
-
660
- })
661
-
662
- $.each($wrapper[0].attributes, function (key, node) {
663
- if ( node.name.match(/^data-(?!dash).*/ ) ) {
664
- $graph.attr(node.name, node.value);
665
- }
666
- });
667
-
668
- $graph.appendTo($wrapper);
669
- }
670
-
671
- scroll_to_host_stats (hostname) {
672
- event.preventDefault();
673
- $('#dash').scrollLeft(document.getElementById(hostname).offsetLeft - $('#' + hostname).width());
674
-
675
- // Prevent regular event from happening
676
- return false;
677
- }
678
-
679
- all_alarms_are_warnings () {
680
- var out = true;
681
- $.each(this.current_alarms, function (host, alarms) {
682
- if (out === false) {
683
- return false; // Maximum efficiency
684
- }
685
- $.each(alarms, function (name, data) {
686
- if (data.status != "WARNING") {
687
- out = false;
688
- return false;
689
- }
690
- });
691
- });
692
- return out;
693
- }
694
-
695
- update_alarm_count () {
696
- var count = $('img.alarm-badge').length;
697
- $('.alarm-count').text($('img.alarm-badge').length);
698
- $('.alarm-count').removeClass('no-alarms warnings-only');
699
- if ( count === 0 ) {
700
- $('.alarm-count').addClass('no-alarms');
701
- return
702
- }
703
- if (this.all_alarms_are_warnings()) {
704
- $('.alarm-count').addClass('warnings-only');
705
- }
706
- }
707
-
708
- fetch_active_alarms () {
709
- var that = this;
710
- console.log("Getting alarms...");
711
- var hosts = this.get_enabled_hosts();
712
- for (var i=0, len=hosts.length; i<len; i++) {
713
- var hostname = hosts[i];
714
-
715
- $.get(this.get_api_url(hostname) + '/alarms', function (data) {
716
- that.new_alarms[ data.hostname ] = data.alarms;
717
- if ( Object.keys(that.new_alarms).length === len ) {
718
- // All responses received
719
- if ( that.check_new_current_alarms() ) {
720
- console.log("No alarm changes detected... Refreshing images.");
721
- that.new_alarms = {};
722
- that.refresh_alarm_images();
723
- return;
724
- }
725
-
726
- that.current_alarms = that.new_alarms;
727
- that.new_alarms = {};
728
- that.draw_alarms();
729
- that.update_alarm_count();
730
- }
731
- });
732
- }
733
- }
734
-
735
- toggle_alarm_collapse () {
736
- $('#alarms').toggleClass('collapsed');
737
- }
738
-
739
- check_new_current_alarms () {
740
- // Create arrays of property names
741
- var a = this.current_alarms;
742
- var b = this.new_alarms;
743
- var aProps = Object.keys(a);
744
- var bProps = Object.keys(b);
745
-
746
- // If number of properties is different,
747
- // objects are not equivalent
748
- if (aProps.length != bProps.length) {
749
- return false;
750
- }
751
-
752
- for (var i = 0; i < aProps.length; i++) {
753
- var propName = aProps[i];
754
- var aa = a[propName];
755
- var aaProps = Object.keys(aa);
756
- var bb = b[propName];
757
- var bbProps = Object.keys(bb);
758
-
759
- if (aaProps.length != bbProps.length) {
760
- return false;
761
- }
762
-
763
- for (var n = 0, len=aaProps.length; i < len; i++) {
764
- if ( bb[aaProps[n]] === undefined ) {
765
- return false;
766
- }
767
- }
768
- }
769
-
770
- // If we made it this far, objects
771
- // are considered equivalent
772
- return true;
773
- }
774
-
775
- refresh_alarm_images () {
776
- // Use Math.random() to "reload" the image
777
- $('.alarm-badge').each(function () {
778
- var old_src = $(this).attr('src').replace(/&rand=.*/g, "");
779
- $(this).attr('src', old_src + "&rand=" + Math.random());
780
- });
781
- }
782
-
783
- draw_alarms () {
784
- var that = this;
785
- console.log("Drawing...", that.current_alarms);
786
- $.each(that.current_alarms, function(hostname, alarms) {
787
- $('#alarms .host-alarms.' + hostname + ' .alarm-badge').remove();
788
- $.each(alarms, function (index, alarm) {
789
- that.draw_alarm(hostname, alarm);
790
- })
791
- });
792
- }
793
-
794
- draw_alarm (hostname, alarm) {
795
- var queryStr = '/badge.svg?alarm=' + alarm.name + '&chart=' + alarm.chart
796
- $('<img />', {
797
- src: this.get_api_url(hostname) + queryStr,
798
- class: 'alarm-badge'
799
- }).appendTo($('#alarms .host-alarms.' + hostname));
800
- }
801
-
802
- remove_template_elements () {
803
- $('.netdata-host-stats-container').first().remove();
804
- }
805
-
806
- fix_layout_errors () {
807
- $('.dash-graph:contains("chart not found")').html('<div class="loading-error">Not found</div>');
808
- $('.dash-chart:contains("chart not found")').html('<div class="loading-error">Not found</div>');
809
- }
810
- }
811
-
812
- if (typeof REVERSE_PROXY_URL === 'undefined') REVERSE_PROXY_URL = null;
813
-
814
- var dash = new Dash(NETDATA_HOST, REVERSE_PROXY_URL);
815
-
816
- var picknsort = new PickNSort(DARK_THEME);
817
-
818
- dash.init(function () {
819
- load_dashboard_js();
820
- });
821
-
822
- setInterval(function () {
823
- dash.digest();
824
- }, ALARM_REFRESH_INTERVAL * 1000);
825
-
826
-</script>
827
-<style type="text/css">
828
- body {
829
- background-color: #272b30;
830
- }
831
-
832
- a, a:hover {
833
- color: #AAA !important;
834
- }
835
-
836
- #dash {
837
- overflow: scroll;
838
- width: 100vw;
839
- white-space: nowrap;
840
- height: 100vh;
841
-
842
- }
843
-
844
- #alarms {
845
- display: block;
846
- z-index: 9999;
847
- position: fixed;
848
- right: 0;
849
- top: 0;
850
- bottom: 0;
851
- background-color: #111;
852
- width: 23em;
853
- padding: 1em;
854
- color: #AAA;
855
- box-shadow: 0 0 3em #060606;
856
- border: solid 1px #2d2d2d;
857
- visibility: hidden;
858
- }
859
-
860
-
861
-
862
- #alarms h1 {
863
- text-align: center;
864
- margin: 0;
865
- margin-bottom: 0.5em;
866
- margin-top: -0.1em;
867
- font-size: 2em;
868
- }
869
-
870
- #alarms h2 {
871
- font-size: 1.5em;
872
- }
873
-
874
- #alarms .alarm-collapse-button {
875
- position: absolute;
876
- top: 0;
877
- left: 0;
878
- width: 0.9em;
879
- height: 0.9em;
880
- font-size: 4em;
881
- line-height: 0.8;
882
- background: #111;
883
- text-align: center;
884
- cursor: default;
885
- }
886
-
887
- #alarms .alarm-collapse-button:hover {
888
- background: #000;
889
- }
890
-
891
- #alarms.collapsed {
892
- width: 4em;
893
- }
894
-
895
- #alarms.collapsed .alarm-collapse-button {
896
- position: fixed;
897
- left: auto;
898
- right: 0;
899
- top: 0;
900
- bottom: 0;
901
- width: 4em;
902
- height: 100vh;
903
- opacity: 0;
904
- z-index: 9999;
905
- }
906
-
907
- #alarms.collapsed h1 {
908
- transform: rotate(-90deg);
909
- position: absolute;
910
- left: -9.1em;
911
- top: 4em;
912
- width: 20em;
913
- }
914
-
915
- #alarms .alarm-host-list {
916
- margin-top: 1em;
917
- height: 100%;
918
- overflow-y: scroll;
919
- scrollbar-width: thin;
920
- }
921
-
922
- #alarms.collapsed .alarm-host-list {
923
- display: none;
924
- }
925
-
926
-
927
-
928
- #alarms .host-alarms {
929
- background: #1d1d1d;
930
- margin-bottom: 1em;
931
- padding: 0.2em 1em;
932
- padding-bottom: 1.5em;
933
- border-top: 1px solid;
934
- position: relative;
935
- }
936
-
937
- .host-alarms a:last-child:after {
938
- position: absolute;
939
- display: block;
940
- content: 'no alarms';
941
- width: 6em;
942
- height: 1em;
943
- right: 0;
944
- top: 2em;
945
- color: #646464;
946
- }
947
-
948
- #alarms .host-alarms img.alarm-badge {
949
- margin: .25em;
950
- height: 1.2em;
951
- }
952
-
953
- #alarms .alarm-count {
954
- width: 1.5em;
955
- height: 1.5em;
956
- text-align: center;
957
- position: absolute;
958
- right: 0.5em;
959
- top: 0.5em;
960
- font-size: 1.5em;
961
- background: #6f1515;
962
- border-radius: 50%;
963
- }
964
-
965
- #alarms .alarm-count:empty {
966
- background: #333;
967
- }
968
-
969
- #alarms .no-alarms {
970
- background: #156f15;
971
- color: rgba(0,0,0,0);
972
- }
973
-
974
- #alarms .warnings-only {
975
- background: #f48041;
976
- color: #EEE;
977
- }
978
-
979
- .settings-button {
980
- position: absolute;
981
- bottom: 0;
982
- right: 0;
983
- font-size: 3em;
984
- width: 1.3em;
985
- height: 1.3em;
986
- z-index: 9999;
987
- text-align: center;
988
- line-height: 1.2;
989
- cursor: default;
990
- }
991
-
992
- .settings-button:hover {
993
- background: #424242;
994
- }
995
-
996
- .netdata-host-name {
997
- font-size: 3em;
998
- color: #FFF;
999
- text-align: center;
1000
- white-space: nowrap;
1001
- background: inherit;
1002
- position: sticky;
1003
- top: 0;
1004
- z-index: 9998;
1005
- box-shadow: 0 0.5em 1em #232323;
1006
- margin-bottom: 0.5em;
1007
- border-bottom: solid 0.1em #AAA;
1008
- }
1009
-
1010
- .netdata-host-stats-container {
1011
- position: relative;
1012
- margin: 0 1em;
1013
- padding: 1em 2em;
1014
- display: inline-block;
1015
- text-align: center;
1016
- color: #CCC;
1017
- background: #232323;
1018
- }
1019
-
1020
- .netdata-host-stats-container:last-of-type {
1021
- margin-right: 27em;
1022
- }
1023
-
1024
- .dash-graph {
1025
- margin-bottom: 1em;
1026
- }
1027
-
1028
- .netdata-legend-resize-handler {
1029
- display: none
1030
- }
1031
-
1032
- .dash-charts {
1033
- white-space: normal;
1034
- margin: 2em 0;
1035
- }
1036
-
1037
- .dash-chart {
1038
- display: inline-block;
1039
- vertical-align: top;
1040
- }
1041
-
1042
- .easyPieChartLabel {
1043
- color: #FFF;
1044
- }
1045
-
1046
- .loading-error {
1047
- padding-top: 2em;
1048
- font-size: 2em;
1049
- }
1050
-
1051
- .netdata-legend-value, .netdata-legend-toolbox, .netdata-legend-toolbox-button, .netdata-legend-resize-handler {
1052
- background: initial;
1053
- }
1054
-</style>
1055
-</html>