graphs.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // This is free software, licensed under the Apache License, Version 2.0
  2. 'use strict';
  3. 'require poll';
  4. 'require view';
  5. 'require fs';
  6. 'require ui';
  7. 'require uci';
  8. 'require rpc';
  9. var RefreshIfaces = "";
  10. var RefreshTabs = ['s', 't', '5', 'h', 'd', 'm', 'y'];
  11. var callServiceList = rpc.declare({
  12. object: 'service',
  13. method: 'list',
  14. params: [ 'name' ],
  15. expect: { '': {} }
  16. });
  17. var isReadonlyView = !L.hasViewPermission() || null;
  18. function RefreshGraphs() {
  19. RefreshTabs.forEach(function (id) {
  20. RefreshIfaces.forEach(function (iface) {
  21. fs.exec_direct('/usr/bin/vnstati', [ '-' + id, '-i', iface, '-o', '-' ], 'blob').then(function(res) {
  22. document.getElementById('graph_' + id + '_' + iface).src = URL.createObjectURL(res);
  23. });
  24. });
  25. });
  26. }
  27. function IfacesResetData(ev) {
  28. ui.showModal(_('Delete data for ALL interfaces'), [
  29. E('p', _('The data will be removed from the database permanently. This cannot be undone.')),
  30. E('div', { 'class': 'right' }, [
  31. E('div', {
  32. 'class': 'btn',
  33. 'click': L.hideModal
  34. }, _('Cancel')),
  35. ' ',
  36. E('div', {
  37. 'class': 'btn cbi-button-negative',
  38. 'click': function(ev) {
  39. var if_count = 0;
  40. RefreshIfaces.forEach(function (iface) {
  41. fs.exec_direct('/usr/bin/vnstat', [ '--remove', '-i', iface, '--force' ], 'blob').then(function() {
  42. fs.exec_direct('/usr/bin/vnstat', [ '--add', '-i', iface ], 'blob').then(function() {
  43. if_count++;
  44. if (if_count == RefreshIfaces.length) {
  45. RefreshGraphs();
  46. }
  47. });
  48. });
  49. });
  50. ui.hideModal();
  51. }
  52. }, _('Delete'))
  53. ])
  54. ]);
  55. }
  56. return view.extend({
  57. renderTab: function(ifaces, style, title) {
  58. var tab = E('div', {
  59. 'class': 'cbi-section',
  60. 'data-tab': style,
  61. 'data-tab-title': title
  62. }, [
  63. E('p', {}, E('em', { 'class': 'spinning' }, [ _('Loading graphs…') ]))
  64. ]);
  65. ifaces.forEach(function(iface) {
  66. fs.exec_direct('/usr/bin/vnstati', [ '-'+style, '-i', iface, '-o', '-' ], 'blob').then(function(res) {
  67. var img = tab.querySelector('img[data-iface="%s"]'.format(iface));
  68. img.src = URL.createObjectURL(res);
  69. img.alt = _('Could not load graph, no data available: ') + iface;
  70. img.align = 'middle';
  71. img.style.visibility = 'visible';
  72. img.id = 'graph_' + style + '_' + iface;
  73. tab.firstElementChild.style.display = 'none';
  74. });
  75. tab.appendChild(E('span', {}, E('img', { 'data-iface': iface, 'style': 'visibility:hidden; margin:5px 10px' })));
  76. });
  77. return tab;
  78. },
  79. load: function() {
  80. return Promise.all([
  81. L.resolveDefault(callServiceList('vnstat'), {}),
  82. uci.load('vnstat'),
  83. ]);
  84. },
  85. render: function(data) {
  86. var ifaces = uci.get_first('vnstat', 'vnstat', 'interface') || [];
  87. var isRunning = false;
  88. try {
  89. isRunning = data[0]['vnstat']['instances']['instance1']['running'];
  90. } catch (e) { }
  91. var view = E([], [
  92. E('h2', [_('vnStat Graphs')]),
  93. (isRunning == false) ? E('p', { 'class': 'alert-message warning' }, _('Warning: The service is not running, graphs will not be updated!')):E('p'),
  94. E('div', ifaces.length ? [
  95. this.renderTab(ifaces, 's', _('Summary')),
  96. this.renderTab(ifaces, 't', _('Top')),
  97. this.renderTab(ifaces, '5', _('5 Minute')),
  98. this.renderTab(ifaces, 'h', _('Hourly')),
  99. this.renderTab(ifaces, 'd', _('Daily')),
  100. this.renderTab(ifaces, 'm', _('Monthly')),
  101. this.renderTab(ifaces, 'y', _('Yearly')),
  102. ] : [ E('em', [_('No monitored interfaces have been found. Go to the configuration to enable monitoring for one or more interfaces.')]) ]),
  103. ]);
  104. if (ifaces.length) {
  105. ui.tabs.initTabGroup(view.lastElementChild.childNodes);
  106. view.appendChild(E('div', { 'class': 'right' }, [
  107. E('br'),
  108. E('button', {
  109. 'class': 'cbi-button cbi-button-neutral',
  110. 'click': IfacesResetData,
  111. 'disabled': isReadonlyView
  112. }, [ _('Clear data for all interfaces') ])
  113. ]));
  114. }
  115. // Preserve the interfaces for the poll/refresh function
  116. RefreshIfaces = ifaces;
  117. poll.add(RefreshGraphs, 60);
  118. return view;
  119. },
  120. handleSave: null,
  121. handleSaveApply: null,
  122. handleReset: null
  123. });