@cryptotaxi247 / netdata-1 / commits / cd089089f

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()">&rsaquo;</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()">&#9881;&#xFE0E;</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)'>&#8595;</div>")
226 - .append("<div class='picknsort-item-up' data-index='" + index + "' onclick='picknsort.shift_up(this)'>&#8593;</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>