dashboard-react.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. /* eslint-disable */
  2. /**
  3. * after react-dashboard refractor, this file can be renamed to 'dashboard.js'
  4. * and it will:
  5. * - setup global objects, so any assignments like 'NETDATA.options.current.destroy_on_hide = true'
  6. * will not break. we need to add it in places where 'dashboard.js' is
  7. * - create react root DOM node
  8. * - load react app
  9. *
  10. * Later, for performance improvement, the bundle can be added to dashboard-rect.js,
  11. * but we need to run the react-app part after DOM is created and ready
  12. */
  13. // ----------------------------------------------------------------------------
  14. // global namespace
  15. // Should stay var!
  16. var NETDATA = window.NETDATA || {};
  17. window.NETDATA = NETDATA // when imported as npm module
  18. /// A heuristic for detecting slow devices.
  19. let isSlowDeviceResult;
  20. const isSlowDevice = function () {
  21. if (!isSlowDeviceResult) {
  22. return isSlowDeviceResult;
  23. }
  24. try {
  25. let ua = navigator.userAgent.toLowerCase();
  26. let iOS = /ipad|iphone|ipod/.test(ua) && !window.MSStream;
  27. let android = /android/.test(ua) && !window.MSStream;
  28. isSlowDeviceResult = (iOS || android);
  29. } catch (e) {
  30. isSlowDeviceResult = false;
  31. }
  32. return isSlowDeviceResult;
  33. };
  34. if (typeof window.netdataSnapshotData === 'undefined') {
  35. window.netdataSnapshotData = null;
  36. }
  37. if (typeof window.netdataShowHelp === 'undefined') {
  38. window.netdataShowHelp = true;
  39. }
  40. if (typeof window.netdataShowAlarms === 'undefined') {
  41. window.netdataShowAlarms = false;
  42. }
  43. if (typeof window.netdataRegistryAfterMs !== 'number' || window.netdataRegistryAfterMs < 0) {
  44. window.netdataRegistryAfterMs = 0; // 1500;
  45. }
  46. if (typeof window.netdataRegistry === 'undefined') {
  47. // backward compatibility
  48. window.netdataRegistry = (typeof netdataNoRegistry !== 'undefined' && netdataNoRegistry === false);
  49. }
  50. if (window.netdataRegistry === false && typeof netdataRegistryCallback === 'function') {
  51. window.netdataRegistry = true;
  52. }
  53. // ----------------------------------------------------------------------------------------------------------------
  54. // the defaults for all charts
  55. // if the user does not specify any of these, the following will be used
  56. NETDATA.chartDefaults = {
  57. width: '100%', // the chart width - can be null
  58. height: '100%', // the chart height - can be null
  59. min_width: null, // the chart minimum width - can be null
  60. library: 'dygraph', // the graphing library to use
  61. method: 'average', // the grouping method
  62. before: 0, // panning
  63. after: -600, // panning
  64. pixels_per_point: 1, // the detail of the chart
  65. fill_luminance: 0.8 // luminance of colors in solid areas
  66. };
  67. // ----------------------------------------------------------------------------------------------------------------
  68. // global options
  69. NETDATA.options = {
  70. pauseCallback: null, // a callback when we are really paused
  71. pause: false, // when enabled we don't auto-refresh the charts
  72. targets: [], // an array of all the state objects that are
  73. // currently active (independently of their
  74. // viewport visibility)
  75. updated_dom: true, // when true, the DOM has been updated with
  76. // new elements we have to check.
  77. auto_refresher_fast_weight: 0, // this is the current time in ms, spent
  78. // rendering charts continuously.
  79. // used with .current.fast_render_timeframe
  80. page_is_visible: true, // when true, this page is visible
  81. auto_refresher_stop_until: 0, // timestamp in ms - used internally, to stop the
  82. // auto-refresher for some time (when a chart is
  83. // performing pan or zoom, we need to stop refreshing
  84. // all other charts, to have the maximum speed for
  85. // rendering the chart that is panned or zoomed).
  86. // Used with .current.global_pan_sync_time
  87. on_scroll_refresher_stop_until: 0, // timestamp in ms - used to stop evaluating
  88. // charts for some time, after a page scroll
  89. last_page_resize: Date.now(), // the timestamp of the last resize request
  90. last_page_scroll: 0, // the timestamp the last time the page was scrolled
  91. browser_timezone: (Intl && Intl.DateTimeFormat)
  92. ? Intl.DateTimeFormat().resolvedOptions().timeZone // timezone detected by javascript
  93. : "cannot-detect-it",
  94. server_timezone: 'unknown', // timezone reported by the server
  95. force_data_points: 0, // force the number of points to be returned for charts
  96. fake_chart_rendering: false, // when set to true, the dashboard will download data but will not render the charts
  97. passive_events: null, // true if the browser supports passive events
  98. // the current profile
  99. // we may have many...
  100. current: {
  101. units: 'auto', // can be 'auto' or 'original'
  102. temperature: 'celsius', // can be 'celsius' or 'fahrenheit'
  103. seconds_as_time: true, // show seconds as DDd:HH:MM:SS ?
  104. timezone: 'default', // the timezone to use, or 'default'
  105. user_set_server_timezone: 'default', // as set by the user on the dashboard
  106. legend_toolbox: true, // show the legend toolbox on charts
  107. resize_charts: true, // show the resize handler on charts
  108. pixels_per_point: isSlowDevice() ? 5 : 1, // the minimum pixels per point for all charts
  109. // increase this to speed javascript up
  110. // each chart library has its own limit too
  111. // the max of this and the chart library is used
  112. // the final is calculated every time, so a change
  113. // here will have immediate effect on the next chart
  114. // update
  115. idle_between_charts: 100, // ms - how much time to wait between chart updates
  116. fast_render_timeframe: 200, // ms - render continuously until this time of continuous
  117. // rendering has been reached
  118. // this setting is used to make it render e.g. 10
  119. // charts at once, sleep idle_between_charts time
  120. // and continue for another 10 charts.
  121. idle_between_loops: 500, // ms - if all charts have been updated, wait this
  122. // time before starting again.
  123. idle_parallel_loops: 100, // ms - the time between parallel refresher updates
  124. idle_lost_focus: 500, // ms - when the window does not have focus, check
  125. // if focus has been regained, every this time
  126. global_pan_sync_time: 300, // ms - when you pan or zoom a chart, the background
  127. // auto-refreshing of charts is paused for this amount
  128. // of time
  129. sync_selection_delay: 400, // ms - when you pan or zoom a chart, wait this amount
  130. // of time before setting up synchronized selections
  131. // on hover.
  132. sync_selection: true, // enable or disable selection sync
  133. pan_and_zoom_delay: 50, // when panning or zooming, how ofter to update the chart
  134. sync_pan_and_zoom: true, // enable or disable pan and zoom sync
  135. pan_and_zoom_data_padding: true, // fetch more data for the master chart when panning or zooming
  136. update_only_visible: true, // enable or disable visibility management / used for printing
  137. parallel_refresher: !isSlowDevice(), // enable parallel refresh of charts
  138. concurrent_refreshes: true, // when parallel_refresher is enabled, sync also the charts
  139. destroy_on_hide: isSlowDevice(), // destroy charts when they are not visible
  140. // when enabled the charts will show some help
  141. // when there's no bootstrap, we can't show it
  142. show_help: netdataShowHelp && !window.netdataNoBootstrap,
  143. show_help_delay_show_ms: 500,
  144. show_help_delay_hide_ms: 0,
  145. eliminate_zero_dimensions: true, // do not show dimensions with just zeros
  146. stop_updates_when_focus_is_lost: true, // boolean - shall we stop auto-refreshes when document does not have user focus
  147. stop_updates_while_resizing: 1000, // ms - time to stop auto-refreshes while resizing the charts
  148. double_click_speed: 500, // ms - time between clicks / taps to detect double click/tap
  149. smooth_plot: !isSlowDevice(), // enable smooth plot, where possible
  150. color_fill_opacity_line: 1.0,
  151. color_fill_opacity_area: 0.2,
  152. color_fill_opacity_fake_stacked: 1,
  153. color_fill_opacity_stacked: 0.8,
  154. pan_and_zoom_factor: 0.25, // the increment when panning and zooming with the toolbox
  155. pan_and_zoom_factor_multiplier_control: 2.0,
  156. pan_and_zoom_factor_multiplier_shift: 3.0,
  157. pan_and_zoom_factor_multiplier_alt: 4.0,
  158. abort_ajax_on_scroll: false, // kill pending ajax page scroll
  159. async_on_scroll: false, // sync/async onscroll handler
  160. onscroll_worker_duration_threshold: 30, // time in ms, for async scroll handler
  161. retries_on_data_failures: 3, // how many retries to make if we can't fetch chart data from the server
  162. setOptionCallback: function () {
  163. }
  164. },
  165. debug: {
  166. show_boxes: false,
  167. main_loop: false,
  168. focus: false,
  169. visibility: false,
  170. chart_data_url: false,
  171. chart_errors: true, // remember to set it to false before merging
  172. chart_timing: false,
  173. chart_calls: false,
  174. libraries: false,
  175. dygraph: false,
  176. globalSelectionSync: false,
  177. globalPanAndZoom: false
  178. }
  179. };
  180. NETDATA.statistics = {
  181. refreshes_total: 0,
  182. refreshes_active: 0,
  183. refreshes_active_max: 0
  184. };
  185. NETDATA.themes = {
  186. white: {
  187. bootstrap_css: "css/bootstrap-3.3.7.css",
  188. dashboard_css: "css/dashboard.css?v20180210-1",
  189. background: "#FFFFFF",
  190. foreground: "#000000",
  191. grid: "#F0F0F0",
  192. axis: "#F0F0F0",
  193. highlight: "#F5F5F5",
  194. colors: ["#3366CC", "#DC3912", "#109618", "#FF9900", "#990099", "#DD4477",
  195. "#3B3EAC", "#66AA00", "#0099C6", "#B82E2E", "#AAAA11", "#5574A6",
  196. "#994499", "#22AA99", "#6633CC", "#E67300", "#316395", "#8B0707",
  197. "#329262", "#3B3EAC"],
  198. easypiechart_track: "#f0f0f0",
  199. easypiechart_scale: "#dfe0e0",
  200. gauge_pointer: "#C0C0C0",
  201. gauge_stroke: "#F0F0F0",
  202. gauge_gradient: false,
  203. gauge_stop_color: "#FC8D5E",
  204. gauge_start_color: "#B0E952",
  205. d3pie: {
  206. title: "#333333",
  207. subtitle: "#666666",
  208. footer: "#888888",
  209. other: "#aaaaaa",
  210. mainlabel: "#333333",
  211. percentage: "#dddddd",
  212. value: "#aaaa22",
  213. tooltip_bg: "#000000",
  214. tooltip_fg: "#efefef",
  215. segment_stroke: "#ffffff",
  216. gradient_color: "#000000",
  217. },
  218. },
  219. slate: {
  220. bootstrap_css: "css/bootstrap-slate-flat-3.3.7.css?v20161229-1",
  221. dashboard_css: "css/dashboard.slate.css?v20180210-1",
  222. background: "#272b30",
  223. foreground: "#C8C8C8",
  224. grid: "#283236",
  225. axis: "#283236",
  226. highlight: "#383838",
  227. colors: ["#66AA00", "#FE3912", "#3366CC", "#D66300", "#0099C6", "#DDDD00",
  228. "#5054e6", "#EE9911", "#BB44CC", "#e45757", "#ef0aef", "#CC7700",
  229. "#22AA99", "#109618", "#905bfd", "#f54882", "#4381bf", "#ff3737",
  230. "#329262", "#3B3EFF"],
  231. easypiechart_track: "#373b40",
  232. easypiechart_scale: "#373b40",
  233. gauge_pointer: "#474b50",
  234. gauge_stroke: "#373b40",
  235. gauge_gradient: false,
  236. gauge_stop_color: "#FC8D5E",
  237. gauge_start_color: "#B0E952",
  238. d3pie: {
  239. title: "#C8C8C8",
  240. subtitle: "#283236",
  241. footer: "#283236",
  242. other: "#283236",
  243. mainlabel: "#C8C8C8",
  244. percentage: "#dddddd",
  245. value: "#cccc44",
  246. tooltip_bg: "#272b30",
  247. tooltip_fg: "#C8C8C8",
  248. segment_stroke: "#283236",
  249. gradient_color: "#000000",
  250. },
  251. },
  252. }
  253. // Codacy declarations
  254. /* global netdataTheme */
  255. NETDATA.updateTheme = function () {
  256. if (typeof window.netdataTheme !== 'undefined'
  257. && typeof NETDATA.themes[netdataTheme] !== 'undefined'
  258. ) {
  259. NETDATA.themes.current = NETDATA.themes[window.netdataTheme];
  260. } else {
  261. NETDATA.themes.current = NETDATA.themes.white;
  262. }
  263. NETDATA.colors = NETDATA.themes.current.colors;
  264. }
  265. NETDATA.updateTheme()
  266. // these are the colors Google Charts are using
  267. // we have them here to attempt emulate their look and feel on the other chart libraries
  268. // http://there4.io/2012/05/02/google-chart-color-list/
  269. //NETDATA.colors = [ '#3366CC', '#DC3912', '#FF9900', '#109618', '#990099', '#3B3EAC', '#0099C6',
  270. // '#DD4477', '#66AA00', '#B82E2E', '#316395', '#994499', '#22AA99', '#AAAA11',
  271. // '#6633CC', '#E67300', '#8B0707', '#329262', '#5574A6', '#3B3EAC' ];
  272. // an alternative set
  273. // http://www.mulinblog.com/a-color-palette-optimized-for-data-visualization/
  274. // (blue) (red) (orange) (green) (pink) (brown) (purple) (yellow) (gray)
  275. //NETDATA.colors = [ '#5DA5DA', '#F15854', '#FAA43A', '#60BD68', '#F17CB0', '#B2912F', '#B276B2', '#DECF3F', '#4D4D4D' ];
  276. // dygraph
  277. // local storage options
  278. NETDATA.localStorage = {
  279. default: {},
  280. current: {},
  281. callback: {} // only used for resetting back to defaults
  282. };
  283. // todo temporary stuff which was originally in dashboard.js
  284. // but needs to be refractored
  285. NETDATA.name2id = function (s) {
  286. return s
  287. .replace(/ /g, '_')
  288. .replace(/:/g, '_')
  289. .replace(/\(/g, '_')
  290. .replace(/\)/g, '_')
  291. .replace(/\./g, '_')
  292. .replace(/\//g, '_');
  293. };
  294. NETDATA.globalChartUnderlay = {
  295. clear: () => {},
  296. init: () => {},
  297. }
  298. NETDATA.globalPanAndZoom = {
  299. callback: () => {},
  300. }
  301. NETDATA.unpause = () => {}
  302. // ----------------------------------------------------------------------------------------------------------------
  303. // XSS checks
  304. NETDATA.xss = {
  305. enabled: (typeof netdataCheckXSS === 'undefined') ? false : netdataCheckXSS,
  306. enabled_for_data: (typeof netdataCheckXSS === 'undefined') ? false : netdataCheckXSS,
  307. string: function (s) {
  308. return s.toString()
  309. .replace(/</g, '&lt;')
  310. .replace(/>/g, '&gt;')
  311. .replace(/"/g, '&quot;')
  312. .replace(/'/g, '&#39;');
  313. },
  314. object: function (name, obj, ignore_regex) {
  315. if (typeof ignore_regex !== 'undefined' && ignore_regex.test(name)) {
  316. // console.log('XSS: ignoring "' + name + '"');
  317. return obj;
  318. }
  319. switch (typeof(obj)) {
  320. case 'string':
  321. const ret = this.string(obj);
  322. if (ret !== obj) {
  323. console.log('XSS protection changed string ' + name + ' from "' + obj + '" to "' + ret + '"');
  324. }
  325. return ret;
  326. case 'object':
  327. if (obj === null) {
  328. return obj;
  329. }
  330. if (Array.isArray(obj)) {
  331. // console.log('checking array "' + name + '"');
  332. let len = obj.length;
  333. while (len--) {
  334. obj[len] = this.object(name + '[' + len + ']', obj[len], ignore_regex);
  335. }
  336. } else {
  337. // console.log('checking object "' + name + '"');
  338. for (var i in obj) {
  339. if (obj.hasOwnProperty(i) === false) {
  340. continue;
  341. }
  342. if (this.string(i) !== i) {
  343. console.log('XSS protection removed invalid object member "' + name + '.' + i + '"');
  344. delete obj[i];
  345. } else {
  346. obj[i] = this.object(name + '.' + i, obj[i], ignore_regex);
  347. }
  348. }
  349. }
  350. return obj;
  351. default:
  352. return obj;
  353. }
  354. },
  355. checkOptional: function (name, obj, ignore_regex) {
  356. if (this.enabled) {
  357. //console.log('XSS: checking optional "' + name + '"...');
  358. return this.object(name, obj, ignore_regex);
  359. }
  360. return obj;
  361. },
  362. checkAlways: function (name, obj, ignore_regex) {
  363. //console.log('XSS: checking always "' + name + '"...');
  364. return this.object(name, obj, ignore_regex);
  365. },
  366. checkData: function (name, obj, ignore_regex) {
  367. if (this.enabled_for_data) {
  368. //console.log('XSS: checking data "' + name + '"...');
  369. return this.object(name, obj, ignore_regex);
  370. }
  371. return obj;
  372. }
  373. };
  374. const fixHost = (host) => {
  375. while (host.slice(-1) === '/') {
  376. host = host.substring(0, host.length - 1);
  377. }
  378. return host;
  379. }
  380. NETDATA.chartRegistry = {
  381. charts: {},
  382. globalReset: function () {
  383. this.charts = {};
  384. },
  385. add: function (host, id, data) {
  386. if (typeof this.charts[host] === 'undefined') {
  387. this.charts[host] = {};
  388. }
  389. //console.log('added ' + host + '/' + id);
  390. this.charts[host][id] = data;
  391. },
  392. get: function (host, id) {
  393. if (typeof this.charts[host] === 'undefined') {
  394. return null;
  395. }
  396. if (typeof this.charts[host][id] === 'undefined') {
  397. return null;
  398. }
  399. //console.log('cached ' + host + '/' + id);
  400. return this.charts[host][id];
  401. },
  402. downloadAll: function (host, callback) {
  403. host = fixHost(host);
  404. let self = this;
  405. function got_data(h, data, callback) {
  406. if (data !== null) {
  407. self.charts[h] = data.charts;
  408. window.charts = data.charts
  409. // update the server timezone in our options
  410. if (typeof data.timezone === 'string') {
  411. NETDATA.options.server_timezone = data.timezone;
  412. }
  413. } else {
  414. NETDATA.error(406, h + '/api/v1/charts');
  415. }
  416. if (typeof callback === 'function') {
  417. callback(data);
  418. }
  419. }
  420. if (window.netdataSnapshotData !== null) {
  421. got_data(host, window.netdataSnapshotData.charts, callback);
  422. } else {
  423. $.ajax({
  424. url: host + '/api/v1/charts',
  425. async: true,
  426. cache: false,
  427. xhrFields: {withCredentials: true} // required for the cookie
  428. })
  429. .done(function (data) {
  430. data = NETDATA.xss.checkOptional('/api/v1/charts', data);
  431. got_data(host, data, callback);
  432. })
  433. .fail(function () {
  434. NETDATA.error(405, host + '/api/v1/charts');
  435. if (typeof callback === 'function') {
  436. callback(null);
  437. }
  438. });
  439. }
  440. }
  441. };
  442. NETDATA.fixHost = function (host) {
  443. while (host.slice(-1) === '/') {
  444. host = host.substring(0, host.length - 1);
  445. }
  446. return host;
  447. };
  448. NETDATA.registryHello = function (host, callback) {
  449. host = NETDATA.fixHost(host);
  450. // send HELLO to a netdata server:
  451. // 1. verifies the server is reachable
  452. // 2. responds with the registry URL, the machine GUID of this netdata server and its hostname
  453. $.ajax({
  454. url: host + '/api/v1/registry?action=hello',
  455. async: true,
  456. cache: false,
  457. headers: {
  458. 'Cache-Control': 'no-cache, no-store',
  459. 'Pragma': 'no-cache'
  460. },
  461. xhrFields: {withCredentials: true} // required for the cookie
  462. })
  463. .done(function (data) {
  464. data = NETDATA.xss.checkOptional('/api/v1/registry?action=hello', data);
  465. if (typeof data.status !== 'string' || data.status !== 'ok') {
  466. // NETDATA.error(408, host + ' response: ' + JSON.stringify(data));
  467. data = null;
  468. }
  469. if (typeof callback === 'function') {
  470. return callback(data);
  471. }
  472. })
  473. .fail(function () {
  474. // NETDATA.error(407, host);
  475. if (typeof callback === 'function') {
  476. return callback(null);
  477. }
  478. });
  479. }
  480. NETDATA.registrySearch = function (machine_guid, getFromRegistry, serverDefault, callback) {
  481. // SEARCH for the URLs of a machine:
  482. $.ajax({
  483. url: getFromRegistry("registryServer") + '/api/v1/registry?action=search&machine='
  484. + getFromRegistry("machineGuid") + '&name=' + encodeURIComponent(getFromRegistry("hostname"))
  485. + '&url=' + encodeURIComponent(serverDefault) + '&for=' + machine_guid,
  486. async: true,
  487. cache: false,
  488. headers: {
  489. 'Cache-Control': 'no-cache, no-store',
  490. 'Pragma': 'no-cache'
  491. },
  492. xhrFields: {withCredentials: true} // required for the cookie
  493. })
  494. .done(function (data) {
  495. data = NETDATA.xss.checkAlways('/api/v1/registry?action=search', data);
  496. if (typeof data.status !== 'string' || data.status !== 'ok') {
  497. // NETDATA.error(417, getFromRegistry("registryServer") + ' responded with: ' + JSON.stringify(data));
  498. console.warn(getFromRegistry("registryServer") + ' responded with: ' + JSON.stringify(data));
  499. data = null;
  500. }
  501. if (typeof callback === 'function') {
  502. return callback(data);
  503. }
  504. })
  505. .fail(function () {
  506. // NETDATA.error(418, getFromRegistry("registryServer"));
  507. console.warn("registry search call failed", getFromRegistry("registryServer"))
  508. if (typeof callback === 'function') {
  509. return callback(null);
  510. }
  511. });
  512. }
  513. NETDATA.registryDelete = function (getFromRegistry, serverDefault, delete_url, callback) {
  514. // send DELETE to a netdata registry:
  515. $.ajax({
  516. url: getFromRegistry("registryServer") + '/api/v1/registry?action=delete&machine='
  517. + getFromRegistry("machineGuid") + '&name=' + encodeURIComponent(getFromRegistry("hostname"))
  518. + '&url=' + encodeURIComponent(serverDefault) + '&delete_url=' + encodeURIComponent(delete_url),
  519. // + '&url=' + encodeURIComponent("http://n5.katsuna.com:19999/") + '&delete_url=' + encodeURIComponent(delete_url),
  520. async: true,
  521. cache: false,
  522. headers: {
  523. 'Cache-Control': 'no-cache, no-store',
  524. 'Pragma': 'no-cache'
  525. },
  526. xhrFields: {withCredentials: true} // required for the cookie
  527. })
  528. .done(function (data) {
  529. // data = NETDATA.xss.checkAlways('/api/v1/registry?action=delete', data);
  530. if (typeof data.status !== 'string' || data.status !== 'ok') {
  531. // NETDATA.error(411, NETDATA.registry.server + ' responded with: ' + JSON.stringify(data));
  532. console.warn(411, getFromRegistry("registryServer") + ' responded with: ' + JSON.stringify(data));
  533. data = null;
  534. }
  535. if (typeof callback === 'function') {
  536. return callback(data);
  537. }
  538. })
  539. .fail(function () {
  540. // NETDATA.error(412, NETDATA.registry.server);
  541. console.warn(412, getFromRegistry("registryServer"));
  542. if (typeof callback === 'function') {
  543. return callback(null);
  544. }
  545. });
  546. }
  547. // NETDATA.currentScript = document.currentScript