luci-mod-network: convert diagnostic page to LuCI look and feel
[project/luci.git] / modules / luci-mod-network / htdocs / luci-static / resources / view / network / diagnostics.js
1 'use strict';
2 'require view';
3 'require dom';
4 'require fs';
5 'require ui';
6 'require uci';
7 'require network';
8
9 return view.extend({
10 handleCommand: function(exec, args) {
11 var buttons = document.querySelectorAll('.diag-action > .cbi-button');
12
13 for (var i = 0; i < buttons.length; i++)
14 buttons[i].setAttribute('disabled', 'true');
15
16 return fs.exec(exec, args).then(function(res) {
17 var out = document.querySelector('textarea');
18
19 dom.content(out, [ res.stdout || '', res.stderr || '' ]);
20 }).catch(function(err) {
21 ui.addNotification(null, E('p', [ err ]))
22 }).finally(function() {
23 for (var i = 0; i < buttons.length; i++)
24 buttons[i].removeAttribute('disabled');
25 });
26 },
27
28 handlePing: function(ev, cmd) {
29 var exec = cmd || 'ping',
30 addr = ev.currentTarget.parentNode.previousSibling.value,
31 args = (exec == 'ping') ? [ '-4', '-c', '5', '-W', '1', addr ] : [ '-6', '-c', '5', addr ];
32
33 return this.handleCommand(exec, args);
34 },
35
36 handleTraceroute: function(ev, cmd) {
37 var exec = cmd || 'traceroute',
38 addr = ev.currentTarget.parentNode.previousSibling.value,
39 args = (exec == 'traceroute') ? [ '-4', '-q', '1', '-w', '1', '-n', '-m', String(L.env.rpctimeout || 20), addr ] : [ '-q', '1', '-w', '2', '-n', addr ];
40
41 return this.handleCommand(exec, args);
42 },
43
44 handleNslookup: function(ev, cmd) {
45 var addr = ev.currentTarget.parentNode.previousSibling.value;
46
47 return this.handleCommand('nslookup', [ addr ]);
48 },
49
50 handleArpScan: function(ev, cmd) {
51 var addr = ev.currentTarget.parentNode.previousSibling.value;
52
53 return this.handleCommand('arp-scan', [ '-l', '-I', addr ]);
54 },
55
56 load: function() {
57 return Promise.all([
58 L.resolveDefault(fs.stat('/bin/ping6'), {}),
59 L.resolveDefault(fs.stat('/usr/bin/ping6'), {}),
60 L.resolveDefault(fs.stat('/bin/traceroute6'), {}),
61 L.resolveDefault(fs.stat('/usr/bin/traceroute6'), {}),
62 L.resolveDefault(fs.stat('/usr/bin/arp-scan'), {}),
63 network.getDevices(),
64 uci.load('luci')
65 ]);
66 },
67
68 render: function(res) {
69 var has_ping6 = res[0].path || res[1].path,
70 has_traceroute6 = res[2].path || res[3].path,
71 has_arpscan = res[4].path,
72 devices = res[5],
73 dns_host = uci.get('luci', 'diag', 'dns') || 'openwrt.org',
74 ping_host = uci.get('luci', 'diag', 'ping') || 'openwrt.org',
75 route_host = uci.get('luci', 'diag', 'route') || 'openwrt.org';
76
77 var table = E('table', { 'class': 'table' }, [
78 E('tr', { 'class': 'tr' }, [
79 E('td', { 'class': 'td left' }, [
80 E('input', {
81 'style': 'margin:5px 0',
82 'type': 'text',
83 'value': ping_host
84 }),
85 E('span', { 'class': 'diag-action' }, [
86 has_ping6 ? new ui.ComboButton('ping', {
87 'ping': '%s %s'.format(_('IPv4'), _('Ping')),
88 'ping6': '%s %s'.format(_('IPv6'), _('Ping')),
89 }, {
90 'click': ui.createHandlerFn(this, 'handlePing'),
91 'classes': {
92 'ping': 'btn cbi-button cbi-button-action',
93 'ping6': 'btn cbi-button cbi-button-action'
94 }
95 }).render() : E('button', {
96 'class': 'cbi-button cbi-button-action',
97 'click': ui.createHandlerFn(this, 'handlePing')
98 }, [ _('Ping') ])
99 ])
100 ]),
101
102 E('td', { 'class': 'td left' }, [
103 E('input', {
104 'style': 'margin:5px 0',
105 'type': 'text',
106 'value': route_host
107 }),
108 E('span', { 'class': 'diag-action' }, [
109 has_traceroute6 ? new ui.ComboButton('traceroute', {
110 'traceroute': '%s %s'.format(_('IPv4'), _('Traceroute')),
111 'traceroute6': '%s %s'.format(_('IPv6'), _('Traceroute')),
112 }, {
113 'click': ui.createHandlerFn(this, 'handleTraceroute'),
114 'classes': {
115 'traceroute': 'btn cbi-button cbi-button-action',
116 'traceroute6': 'btn cbi-button cbi-button-action'
117 }
118 }).render() : E('button', {
119 'class': 'cbi-button cbi-button-action',
120 'click': ui.createHandlerFn(this, 'handleTraceroute')
121 }, [ _('Traceroute') ])
122 ])
123 ]),
124
125 E('td', { 'class': 'td left' }, [
126 E('input', {
127 'style': 'margin:5px 0',
128 'type': 'text',
129 'value': dns_host
130 }),
131 E('span', { 'class': 'diag-action' }, [
132 E('button', {
133 'class': 'cbi-button cbi-button-action',
134 'click': ui.createHandlerFn(this, 'handleNslookup')
135 }, [ _('Nslookup') ])
136 ])
137 ]),
138
139 has_arpscan ? E('td', { 'class': 'td left' }, [
140 E('select', {
141 'style': 'margin:5px 0'
142 }, devices.map(function(device) {
143 if (!device.isUp())
144 return E([]);
145
146 return E('option', { 'value': device.getName() }, [ device.getI18n() ]);
147 })),
148 E('span', { 'class': 'diag-action' }, [
149 E('button', {
150 'class': 'cbi-button cbi-button-action',
151 'click': ui.createHandlerFn(this, 'handleArpScan')
152 }, [ _('Arp-scan') ])
153 ])
154 ]) : E([]),
155 ])
156 ]);
157
158 var view = E('div', { 'class': 'cbi-map'}, [
159 E('h2', {}, [ _('Diagnostics') ]),
160 E('div', { 'class': 'cbi-map-descr'}, _('Execution of various network commands to check the connection and name resolution to other systems.')),
161 table,
162 E('div', {'class': 'cbi-section'}, [
163 E('div', { 'id' : 'command-output'},
164 E('textarea', {
165 'id': 'widget.command-output',
166 'style': 'width: 100%',
167 'readonly': true,
168 'wrap': 'off',
169 'rows': '20'
170 })
171 )
172 ])
173 ]);
174
175 return view;
176 },
177
178 handleSaveApply: null,
179 handleSave: null,
180 handleReset: null
181 });