summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-mod-network
diff options
context:
space:
mode:
Diffstat (limited to 'modules/luci-mod-network')
-rw-r--r--modules/luci-mod-network/htdocs/luci-static/resources/view/network/iface_status.js42
-rw-r--r--modules/luci-mod-network/htdocs/luci-static/resources/view/network/network.js135
-rw-r--r--modules/luci-mod-network/htdocs/luci-static/resources/view/network/wifi_join.js159
-rw-r--r--modules/luci-mod-network/htdocs/luci-static/resources/view/network/wifi_status.js59
-rw-r--r--modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js93
-rw-r--r--modules/luci-mod-network/luasrc/controller/admin/network.lua2
-rw-r--r--modules/luci-mod-network/luasrc/model/cbi/admin_network/network.lua63
-rw-r--r--modules/luci-mod-network/luasrc/model/cbi/admin_network/wifi.lua14
-rw-r--r--modules/luci-mod-network/luasrc/model/cbi/admin_network/wifi_overview.lua76
-rw-r--r--modules/luci-mod-network/luasrc/view/admin_network/iface_overview.htm53
-rw-r--r--modules/luci-mod-network/luasrc/view/admin_network/iface_overview_status.htm183
-rw-r--r--modules/luci-mod-network/luasrc/view/admin_network/iface_status.htm62
-rw-r--r--modules/luci-mod-network/luasrc/view/admin_network/wifi_join.htm183
-rw-r--r--modules/luci-mod-network/luasrc/view/admin_network/wifi_overview.htm61
-rw-r--r--modules/luci-mod-network/luasrc/view/admin_network/wifi_overview_status.htm127
-rw-r--r--modules/luci-mod-network/luasrc/view/admin_network/wifi_status.htm71
16 files changed, 633 insertions, 750 deletions
diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/iface_status.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/iface_status.js
new file mode 100644
index 0000000000..88f48d189a
--- /dev/null
+++ b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/iface_status.js
@@ -0,0 +1,42 @@
+requestAnimationFrame(function() {
+ document.querySelectorAll('[data-iface-status]').forEach(function(container) {
+ var network = container.getAttribute('data-iface-status'),
+ icon = container.querySelector('img'),
+ info = container.querySelector('span');
+
+ L.poll(5, L.url('admin/network/iface_status', network), null, function(xhr, ifaces) {
+ var ifc = Array.isArray(ifaces) ? ifaces[0] : null;
+ if (!ifc)
+ return;
+
+ L.itemlist(info, [
+ _('Device'), ifc.ifname,
+ _('Uptime'), ifc.is_up ? '%t'.format(ifc.uptime) : null,
+ _('MAC'), ifc.ifname ? ifc.macaddr : null,
+ _('RX'), ifc.ifname ? '%.2mB (%d %s)'.format(ifc.rx_bytes, ifc.rx_packets, _('Pkts.')) : null,
+ _('TX'), ifc.ifname ? '%.2mB (%d %s)'.format(ifc.tx_bytes, ifc.tx_packets, _('Pkts.')) : null,
+ _('IPv4'), ifc.ipaddrs ? ifc.ipaddrs[0] : null,
+ _('IPv4'), ifc.ipaddrs ? ifc.ipaddrs[1] : null,
+ _('IPv4'), ifc.ipaddrs ? ifc.ipaddrs[2] : null,
+ _('IPv4'), ifc.ipaddrs ? ifc.ipaddrs[3] : null,
+ _('IPv4'), ifc.ipaddrs ? ifc.ipaddrs[4] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[0] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[1] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[2] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[3] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[4] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[5] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[6] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[7] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[8] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[9] : null,
+ _('IPv6-PD'), ifc.ip6prefix,
+ null, ifc.ifname ? null : E('em', _('Interface not present or not connected yet.'))
+ ]);
+
+ icon.src = L.resource('icons/%s%s.png').format(ifc.type, ifc.is_up ? '' : '_disabled');
+ });
+
+ L.run();
+ });
+});
diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/network.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/network.js
new file mode 100644
index 0000000000..acca7cf8a5
--- /dev/null
+++ b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/network.js
@@ -0,0 +1,135 @@
+function iface_reconnect(id) {
+ L.halt();
+ L.dom.content(document.getElementById(id + '-ifc-description'), E('em', _('Interface is reconnecting...')));
+ L.post(L.url('admin/network/iface_reconnect', id), L.run);
+}
+
+function iface_delete(ev) {
+ if (!confirm(_('Really delete this interface? The deletion cannot be undone! You might lose access to this device if you are connected via this interface'))) {
+ ev.preventDefault();
+ return false;
+ }
+
+ ev.target.previousElementSibling.value = '1';
+ return true;
+}
+
+var networks = [];
+
+document.querySelectorAll('[data-network]').forEach(function(n) {
+ networks.push(n.getAttribute('data-network'));
+});
+
+function render_iface(ifc) {
+ return E('span', { class: 'cbi-tooltip-container' }, [
+ E('img', { 'class' : 'middle', 'src': L.resource('icons/%s%s.png').format(
+ ifc.is_alias ? 'alias' : ifc.type,
+ ifc.is_up ? '' : '_disabled') }),
+ E('span', { 'class': 'cbi-tooltip ifacebadge large' }, [
+ E('img', { 'src': L.resource('icons/%s%s.png').format(
+ ifc.type, ifc.is_up ? '' : '_disabled') }),
+ L.itemlist(E('span', { 'class': 'left' }), [
+ _('Type'), ifc.typename,
+ _('Device'), ifc.ifname,
+ _('Connected'), ifc.is_up ? _('yes') : _('no'),
+ _('MAC'), ifc.macaddr,
+ _('RX'), '%.2mB (%d %s)'.format(ifc.rx_bytes, ifc.rx_packets, _('Pkts.')),
+ _('TX'), '%.2mB (%d %s)'.format(ifc.tx_bytes, ifc.tx_packets, _('Pkts.'))
+ ])
+ ])
+ ]);
+}
+
+L.poll(5, L.url('admin/network/iface_status', networks.join(',')), null,
+ function(x, ifcs) {
+ if (ifcs) {
+ for (var idx = 0; idx < ifcs.length; idx++) {
+ var ifc = ifcs[idx];
+
+ var s = document.getElementById(ifc.id + '-ifc-devices');
+ if (s) {
+ var c = [ render_iface(ifc) ];
+
+ if (ifc.subdevices && ifc.subdevices.length)
+ {
+ var sifs = [ ' (' ];
+
+ for (var j = 0; j < ifc.subdevices.length; j++)
+ sifs.push(render_iface(ifc.subdevices[j]));
+
+ sifs.push(')');
+
+ c.push(E('span', {}, sifs));
+ }
+
+ c.push(E('br'));
+ c.push(E('small', {}, ifc.is_alias ? _('Alias of "%s"').format(ifc.is_alias) : ifc.name));
+
+ L.dom.content(s, c);
+ }
+
+ var d = document.getElementById(ifc.id + '-ifc-description');
+ if (d && ifc.proto && ifc.ifname) {
+ var desc = null, c = [];
+
+ if (ifc.is_dynamic)
+ desc = _('Virtual dynamic interface');
+ else if (ifc.is_alias)
+ desc = _('Alias Interface');
+
+ if (ifc.desc)
+ desc = desc ? '%s (%s)'.format(desc, ifc.desc) : ifc.desc;
+
+ L.itemlist(d, [
+ _('Protocol'), '%h'.format(desc || '?'),
+ _('Uptime'), ifc.is_up ? '%t'.format(ifc.uptime) : null,
+ _('MAC'), (!ifc.is_dynamic && !ifc.is_alias && ifc.macaddr) ? ifc.macaddr : null,
+ _('RX'), (!ifc.is_dynamic && !ifc.is_alias) ? '%.2mB (%d %s)'.format(ifc.rx_bytes, ifc.rx_packets, _('Pkts.')) : null,
+ _('TX'), (!ifc.is_dynamic && !ifc.is_alias) ? '%.2mB (%d %s)'.format(ifc.tx_bytes, ifc.tx_packets, _('Pkts.')) : null,
+ _('IPv4'), ifc.ipaddrs ? ifc.ipaddrs[0] : null,
+ _('IPv4'), ifc.ipaddrs ? ifc.ipaddrs[1] : null,
+ _('IPv4'), ifc.ipaddrs ? ifc.ipaddrs[2] : null,
+ _('IPv4'), ifc.ipaddrs ? ifc.ipaddrs[3] : null,
+ _('IPv4'), ifc.ipaddrs ? ifc.ipaddrs[4] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[0] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[1] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[2] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[3] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[4] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[5] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[6] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[7] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[8] : null,
+ _('IPv6'), ifc.ip6addrs ? ifc.ip6addrs[9] : null,
+ _('IPv6-PD'), ifc.ip6prefix,
+ _('Error'), ifc.errors ? ifc.errors[0] : null,
+ _('Error'), ifc.errors ? ifc.errors[1] : null,
+ _('Error'), ifc.errors ? ifc.errors[2] : null,
+ _('Error'), ifc.errors ? ifc.errors[3] : null,
+ _('Error'), ifc.errors ? ifc.errors[4] : null,
+ ]);
+ }
+ else if (d && !ifc.proto) {
+ var e = document.getElementById(ifc.id + '-ifc-edit');
+ if (e) e.disabled = true;
+
+ var link = L.url('admin/system/packages') + '?query=luci-proto&display=available';
+ L.dom.content(d, [
+ E('em', _('Unsupported protocol type.')), E('br'),
+ E('a', { href: link }, _('Install protocol extensions...'))
+ ]);
+ }
+ else if (d && !ifc.ifname) {
+ var link = L.url('admin/network/network', ifc.name) + '?tab.network.%s=physical'.format(ifc.name);
+ L.dom.content(d, [
+ E('em', _('Network without interfaces.')), E('br'),
+ E('a', { href: link }, _('Assign interfaces...'))
+ ]);
+ }
+ else if (d) {
+ L.dom.content(d, E('em' ,_('Interface not present or not connected yet.')));
+ }
+ }
+ }
+ }
+);
diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wifi_join.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wifi_join.js
new file mode 100644
index 0000000000..d5bd7b0a6d
--- /dev/null
+++ b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wifi_join.js
@@ -0,0 +1,159 @@
+var poll = null;
+
+function format_signal(bss) {
+ var qval = bss.quality || 0,
+ qmax = bss.quality_max || 100,
+ scale = 100 / qmax * qval,
+ range = 'none';
+
+ if (!bss.bssid || bss.bssid == '00:00:00:00:00:00')
+ range = 'none';
+ else if (scale < 15)
+ range = '0';
+ else if (scale < 35)
+ range = '0-25';
+ else if (scale < 55)
+ range = '25-50';
+ else if (scale < 75)
+ range = '50-75';
+ else
+ range = '75-100';
+
+ return E('span', {
+ class: 'ifacebadge',
+ title: '%s: %d%s / %s: %d/%d'.format(_('Signal'), bss.signal, _('dB'), _('Quality'), qval, qmax)
+ }, [
+ E('img', { src: L.resource('icons/signal-%s.png').format(range) }),
+ ' %d%%'.format(scale)
+ ]);
+}
+
+function format_encryption(bss) {
+ var enc = bss.encryption || { }
+
+ if (enc.wep === true)
+ return 'WEP';
+ else if (enc.wpa > 0)
+ return E('abbr', {
+ title: 'Pairwise: %h / Group: %h'.format(
+ enc.pair_ciphers.join(', '),
+ enc.group_ciphers.join(', '))
+ },
+ '%h - %h'.format(
+ (enc.wpa === 3) ? _('mixed WPA/WPA2') : (enc.wpa === 2 ? 'WPA2' : 'WPA'),
+ enc.auth_suites.join(', ')));
+ else
+ return E('em', enc.enabled ? _('unknown') : _('open'));
+}
+
+function format_actions(dev, type, bss) {
+ var enc = bss.encryption || { },
+ input = [
+ E('input', { type: 'submit', class: 'cbi-button cbi-button-action important', value: _('Join Network') }),
+ E('input', { type: 'hidden', name: 'token', value: L.env.token }),
+ E('input', { type: 'hidden', name: 'device', value: dev }),
+ E('input', { type: 'hidden', name: 'join', value: bss.ssid }),
+ E('input', { type: 'hidden', name: 'mode', value: bss.mode }),
+ E('input', { type: 'hidden', name: 'bssid', value: bss.bssid }),
+ E('input', { type: 'hidden', name: 'channel', value: bss.channel }),
+ E('input', { type: 'hidden', name: 'clbridge', value: type === 'wl' ? 1 : 0 }),
+ E('input', { type: 'hidden', name: 'wep', value: enc.wep ? 1 : 0 })
+ ];
+
+ if (enc.wpa) {
+ input.push(E('input', { type: 'hidden', name: 'wpa_version', value: enc.wpa }));
+
+ enc.auth_suites.forEach(function(s) {
+ input.push(E('input', { type: 'hidden', name: 'wpa_suites', value: s }));
+ });
+
+ enc.group_ciphers.forEach(function(s) {
+ input.push(E('input', { type: 'hidden', name: 'wpa_group', value: s }));
+ });
+
+ enc.pair_ciphers.forEach(function(s) {
+ input.push(E('input', { type: 'hidden', name: 'wpa_pairwise', value: s }));
+ });
+ }
+
+ return E('form', {
+ class: 'inline',
+ method: 'post',
+ action: L.url('admin/network/wireless_join')
+ }, input);
+}
+
+function fade(bss, content) {
+ if (bss.stale)
+ return E('span', { style: 'opacity:0.5' }, content);
+ else
+ return content;
+}
+
+function flush() {
+ L.stop(poll);
+ L.halt();
+
+ scan();
+}
+
+function scan() {
+ var tbl = document.querySelector('[data-wifi-scan]'),
+ dev = tbl.getAttribute('data-wifi-scan'),
+ type = tbl.getAttribute('data-wifi-type');
+
+ cbi_update_table(tbl, [], E('em', { class: 'spinning' }, _('Starting wireless scan...')));
+
+ L.post(L.url('admin/network/wireless_scan_trigger', dev), null, function(s) {
+ if (s.status !== 204) {
+ cbi_update_table(tbl, [], E('em', _('Scan request failed')));
+ return;
+ }
+
+ var count = 0;
+
+ poll = L.poll(3, L.url('admin/network/wireless_scan_results', dev), null, function(s, results) {
+ if (Array.isArray(results)) {
+ var bss = [];
+
+ results.sort(function(a, b) {
+ var diff = (b.quality - a.quality) || (a.channel - b.channel);
+
+ if (diff)
+ return diff;
+
+ if (a.ssid < b.ssid)
+ return -1;
+ else if (a.ssid > b.ssid)
+ return 1;
+
+ if (a.bssid < b.bssid)
+ return -1;
+ else if (a.bssid > b.bssid)
+ return 1;
+ }).forEach(function(res) {
+ bss.push([
+ fade(res, format_signal(res)),
+ fade(res, res.ssid ? '%h'.format(res.ssid) : E('em', {}, _('hidden'))),
+ fade(res, res.channel),
+ fade(res, res.mode),
+ fade(res, res.bssid),
+ fade(res, format_encryption(res)),
+ format_actions(dev, type, res)
+ ]);
+ });
+
+ cbi_update_table(tbl, bss, E('em', { class: 'spinning' }, _('No scan results available yet...')));
+ }
+
+ if (count++ >= 3) {
+ count = 0;
+ L.post(L.url('admin/network/wireless_scan_trigger', dev, 1), null, function() {});
+ }
+ });
+
+ L.run();
+ });
+}
+
+document.addEventListener('DOMContentLoaded', scan);
diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wifi_status.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wifi_status.js
new file mode 100644
index 0000000000..7e14d999bd
--- /dev/null
+++ b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wifi_status.js
@@ -0,0 +1,59 @@
+requestAnimationFrame(function() {
+ document.querySelectorAll('[data-wifi-status]').forEach(function(container) {
+ var ifname = container.getAttribute('data-wifi-status'),
+ small = container.querySelector('small'),
+ info = container.querySelector('span');
+
+ L.poll(5, L.url('admin/network/wireless_status', ifname), null, function(xhr, iws) {
+ var iw = Array.isArray(iws) ? iws[0] : null;
+ if (!iw)
+ return;
+
+ var is_assoc = (iw.bssid && iw.bssid != '00:00:00:00:00:00' && iw.channel && !iw.disabled);
+ var p = iw.quality;
+ var q = iw.disabled ? -1 : p;
+
+ var icon;
+ if (q < 0)
+ icon = L.resource('icons/signal-none.png');
+ else if (q == 0)
+ icon = L.resource('icons/signal-0.png');
+ else if (q < 25)
+ icon = L.resource('icons/signal-0-25.png');
+ else if (q < 50)
+ icon = L.resource('icons/signal-25-50.png');
+ else if (q < 75)
+ icon = L.resource('icons/signal-50-75.png');
+ else
+ icon = L.resource('icons/signal-75-100.png');
+
+ L.dom.content(small, [
+ E('img', {
+ src: icon,
+ title: '%s: %d %s / %s: %d %s'.format(
+ _('Signal'), iw.signal, _('dBm'),
+ _('Noise'), iw.noise, _('dBm'))
+ }),
+ '\u00a0', E('br'), '%d%%\u00a0'.format(p)
+ ]);
+
+ L.itemlist(info, [
+ _('Mode'), iw.mode,
+ _('SSID'), '%h'.format(iw.ssid || '?'),
+ _('BSSID'), is_assoc ? iw.bssid : null,
+ _('Encryption'), is_assoc ? iw.encryption || _('None') : null,
+ _('Channel'), is_assoc ? '%d (%.3f %s)'.format(iw.channel, iw.frequency || 0, _('GHz')) : null,
+ _('Tx-Power'), is_assoc ? '%d %s'.format(iw.txpower, _('dBm')) : null,
+ _('Signal'), is_assoc ? '%d %s'.format(iw.signal, _('dBm')) : null,
+ _('Noise'), is_assoc ? '%d %s'.format(iw.noise, _('dBm')) : null,
+ _('Bitrate'), is_assoc ? '%.1f %s'.format(iw.bitrate || 0, _('Mbit/s')) : null,
+ _('Country'), is_assoc ? iw.country : null
+ ], [ ' | ', E('br'), E('br'), E('br'), E('br'), E('br'), ' | ', E('br'), ' | ' ]);
+
+ if (!is_assoc)
+ L.dom.append(info, E('em', iw.disabled ? _('Wireless is disabled') : _('Wireless is not associated')));
+ });
+
+ L.run();
+ });
+});
diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js
new file mode 100644
index 0000000000..bdeb23d235
--- /dev/null
+++ b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/wireless.js
@@ -0,0 +1,93 @@
+function wifi_delete(ev) {
+ if (!confirm(_('Really delete this wireless network? The deletion cannot be undone! You might lose access to this device if you are connected via this network.'))) {
+ ev.preventDefault();
+ return false;
+ }
+
+ ev.target.previousElementSibling.value = '1';
+ return true;
+}
+
+function wifi_restart(ev) {
+ L.halt();
+
+ findParent(ev.target, '.table').querySelectorAll('[data-disabled="false"]').forEach(function(s) {
+ L.dom.content(s, E('em', _('Wireless is restarting...')));
+ });
+
+ L.post(L.url('admin/network/wireless_reconnect', ev.target.getAttribute('data-radio')), L.run);
+}
+
+var networks = [ ];
+
+document.querySelectorAll('[data-network]').forEach(function(n) {
+ networks.push(n.getAttribute('data-network'));
+});
+
+L.poll(5, L.url('admin/network/wireless_status', networks.join(',')), null,
+ function(x, st) {
+ if (st) {
+ var rowstyle = 1;
+ var radiostate = { };
+
+ st.forEach(function(s) {
+ var r = radiostate[s.device.device] || (radiostate[s.device.device] = {});
+
+ s.is_assoc = (s.bssid && s.bssid != '00:00:00:00:00:00' && s.channel && s.mode != 'Unknown' && !s.disabled);
+
+ r.up = r.up || s.is_assoc;
+ r.channel = r.channel || s.channel;
+ r.bitrate = r.bitrate || s.bitrate;
+ r.frequency = r.frequency || s.frequency;
+ });
+
+ for (var i = 0; i < st.length; i++) {
+ var iw = st[i],
+ sig = document.getElementById(iw.id + '-iw-signal'),
+ info = document.getElementById(iw.id + '-iw-status'),
+ disabled = (info && info.getAttribute('data-disabled') === 'true');
+
+ var p = iw.quality;
+ var q = disabled ? -1 : p;
+
+ var icon;
+ if (q < 0)
+ icon = L.resource('icons/signal-none.png');
+ else if (q == 0)
+ icon = L.resource('icons/signal-0.png');
+ else if (q < 25)
+ icon = L.resource('icons/signal-0-25.png');
+ else if (q < 50)
+ icon = L.resource('icons/signal-25-50.png');
+ else if (q < 75)
+ icon = L.resource('icons/signal-50-75.png');
+ else
+ icon = L.resource('icons/signal-75-100.png');
+
+ L.dom.content(sig, E('span', {
+ class: 'ifacebadge',
+ title: '%s %d %s / %s: %d %s'.format(_('Signal'), iw.signal, _('dBm'), _('Noise'), iw.noise, _('dBm'))
+ }, [ E('img', { src: icon }), ' %d%%'.format(p) ]));
+
+ L.itemlist(info, [
+ _('SSID'), '%h'.format(iw.ssid || '?'),
+ _('Mode'), iw.mode,
+ _('BSSID'), iw.is_assoc ? iw.bssid : null,
+ _('Encryption'), iw.is_assoc ? iw.encryption || _('None') : null,
+ null, iw.is_assoc ? null : E('em', disabled ? _('Wireless is disabled') : _('Wireless is not associated'))
+ ], [ ' | ', E('br') ]);
+ }
+
+ for (var dev in radiostate) {
+ var img = document.getElementById(dev + '-iw-upstate');
+ if (img) img.src = L.resource('icons/wifi' + (radiostate[dev].up ? '' : '_disabled') + '.png');
+
+ var stat = document.getElementById(dev + '-iw-devinfo');
+ L.itemlist(stat, [
+ _('Channel'), '%s (%s %s)'.format(radiostate[dev].channel || '?', radiostate[dev].frequency || '?', _('GHz')),
+ _('Bitrate'), '%s %s'.format(radiostate[dev].bitrate || '?', _('Mbit/s'))
+ ], ' | ');
+ }
+ }
+ }
+);
diff --git a/modules/luci-mod-network/luasrc/controller/admin/network.lua b/modules/luci-mod-network/luasrc/controller/admin/network.lua
index a200f79b51..1da5eac464 100644
--- a/modules/luci-mod-network/luasrc/controller/admin/network.lua
+++ b/modules/luci-mod-network/luasrc/controller/admin/network.lua
@@ -321,7 +321,7 @@ function wifi_scan_trigger(radio, update)
return
end
- luci.http.status(200, "Scan scheduled")
+ luci.http.status(204, "Scan scheduled")
if nixio.fork() == 0 then
io.stderr:close()
diff --git a/modules/luci-mod-network/luasrc/model/cbi/admin_network/network.lua b/modules/luci-mod-network/luasrc/model/cbi/admin_network/network.lua
index 0c0ca5263d..b98086dea6 100644
--- a/modules/luci-mod-network/luasrc/model/cbi/admin_network/network.lua
+++ b/modules/luci-mod-network/luasrc/model/cbi/admin_network/network.lua
@@ -15,59 +15,6 @@ m:chain("dhcp")
m.pageaction = false
-local tpl_networks = tpl.Template(nil, [[
- <div class="cbi-section-node">
- <div class="table">
- <%
- for i, net in ipairs(netlist) do
- local z = net[3]
- local c = z and z:get_color() or "#EEEEEE"
- local t = z and translate("Part of zone %q" % z:name()) or translate("No zone assigned")
- local disabled = (net[4]:get("auto") == "0")
- local dynamic = net[4]:is_dynamic()
- %>
- <div class="tr cbi-rowstyle-<%=i % 2 + 1%>">
- <div class="td col-3 center middle">
- <div class="ifacebox">
- <div class="ifacebox-head" style="background-color:<%=c%>" title="<%=pcdata(t)%>">
- <strong><%=net[1]:upper()%></strong>
- </div>
- <div class="ifacebox-body" id="<%=net[1]%>-ifc-devices" data-network="<%=net[1]%>">
- <img src="<%=resource%>/icons/ethernet_disabled.png" style="width:16px; height:16px" /><br />
- <small>?</small>
- </div>
- </div>
- </div>
- <div class="td col-5 left middle" id="<%=net[1]%>-ifc-description">
- <em><%:Collecting data...%></em>
- </div>
- <div class="td cbi-section-actions">
- <div>
- <input type="button" class="cbi-button cbi-button-neutral" onclick="iface_reconnect('<%=net[1]%>')" title="<%:Reconnect this interface%>" value="<%:Restart%>"<%=ifattr(disabled or dynamic, "disabled", "disabled")%> />
-
- <% if disabled then %>
- <input type="hidden" name="cbid.network.<%=net[1]%>.__disable__" value="1" />
- <input type="submit" name="cbi.apply" class="cbi-button cbi-button-neutral" onclick="this.previousElementSibling.value='0'" title="<%:Reconnect this interface%>" value="<%:Connect%>"<%=ifattr(dynamic, "disabled", "disabled")%> />
- <% else %>
- <input type="hidden" name="cbid.network.<%=net[1]%>.__disable__" value="0" />
- <input type="submit" name="cbi.apply" class="cbi-button cbi-button-neutral" onclick="this.previousElementSibling.value='1'" title="<%:Shutdown this interface%>" value="<%:Stop%>"<%=ifattr(dynamic, "disabled", "disabled")%> />
- <% end %>
-
- <input type="button" class="cbi-button cbi-button-action important" onclick="location.href='<%=url("admin/network/network", net[1])%>'" title="<%:Edit this interface%>" value="<%:Edit%>" id="<%=net[1]%>-ifc-edit"<%=ifattr(dynamic, "disabled", "disabled")%> />
-
- <input type="hidden" name="cbid.network.<%=net[1]%>.__delete__" value="" />
- <input type="submit" name="cbi.apply" class="cbi-button cbi-button-negative" onclick="iface_delete(event)" value="<%:Delete%>"<%=ifattr(dynamic, "disabled", "disabled")%> />
- </div>
- </div>
- </div>
- <% end %>
- </div>
- </div>
- <div class="cbi-section-create">
- <input type="button" class="cbi-button cbi-button-add" value="<%:Add new interface...%>" onclick="location.href='<%=url("admin/network/iface_add")%>'" />
- </div>
-]])
-
local _, net
local ifaces, netlist = { }, { }
@@ -102,6 +49,8 @@ table.sort(netlist,
end)
s = m:section(TypedSection, "interface", translate("Interface Overview"))
+s.template = "admin_network/iface_overview"
+s.netlist = netlist
function s.cfgsections(self)
local _, net, sl = nil, nil, { }
@@ -113,12 +62,6 @@ function s.cfgsections(self)
return sl
end
-function s.render(self)
- tpl_networks:render({
- netlist = netlist
- })
-end
-
o = s:option(Value, "__disable__")
function o.write(self, sid, value)
@@ -138,8 +81,6 @@ function o.write(self, sid, value)
end
-m:section(SimpleSection).template = "admin_network/iface_overview_status"
-
if fs.access("/etc/init.d/dsl_control") then
local ok, boarddata = pcall(json.parse, fs.readfile("/etc/board.json"))
local modemtype = (ok == true)
diff --git a/modules/luci-mod-network/luasrc/model/cbi/admin_network/wifi.lua b/modules/luci-mod-network/luasrc/model/cbi/admin_network/wifi.lua
index fd7e729b00..9ab282c3ab 100644
--- a/modules/luci-mod-network/luasrc/model/cbi/admin_network/wifi.lua
+++ b/modules/luci-mod-network/luasrc/model/cbi/admin_network/wifi.lua
@@ -898,12 +898,14 @@ if hwtype == "mac80211" or hwtype == "prism2" then
ft_psk_generate_local = s:taboption("encryption", Flag, "ft_psk_generate_local",
translate("Generate PMK locally"),
- translate("When using a PSK, the PMK can be generated locally without inter AP communications"))
+ translate("When using a PSK, the PMK can be automatically generated. When enabled, the R0/R1 key options below are not applied. Disable this to use the R0 and R1 key options."))
ft_psk_generate_local:depends({ieee80211r="1"})
+ ft_psk_generate_local.default = ft_psk_generate_local.enabled
+ ft_psk_generate_local.rmempty = false
r0_key_lifetime = s:taboption("encryption", Value, "r0_key_lifetime",
translate("R0 Key Lifetime"), translate("minutes"))
- r0_key_lifetime:depends({ieee80211r="1", ft_psk_generate_local=""})
+ r0_key_lifetime:depends({ieee80211r="1"})
r0_key_lifetime.placeholder = "10000"
r0_key_lifetime.datatype = "uinteger"
r0_key_lifetime.rmempty = true
@@ -911,13 +913,13 @@ if hwtype == "mac80211" or hwtype == "prism2" then
r1_key_holder = s:taboption("encryption", Value, "r1_key_holder",
translate("R1 Key Holder"),
translate("6-octet identifier as a hex string - no colons"))
- r1_key_holder:depends({ieee80211r="1", ft_psk_generate_local=""})
+ r1_key_holder:depends({ieee80211r="1"})
r1_key_holder.placeholder = "00004f577274"
r1_key_holder.datatype = "and(hexstring,rangelength(12,12))"
r1_key_holder.rmempty = true
pmk_r1_push = s:taboption("encryption", Flag, "pmk_r1_push", translate("PMK R1 Push"))
- pmk_r1_push:depends({ieee80211r="1", ft_psk_generate_local=""})
+ pmk_r1_push:depends({ieee80211r="1"})
pmk_r1_push.placeholder = "0"
pmk_r1_push.rmempty = true
@@ -927,7 +929,7 @@ if hwtype == "mac80211" or hwtype == "prism2" then
"<br />This list is used to map R0KH-ID (NAS Identifier) to a destination " ..
"MAC address when requesting PMK-R1 key from the R0KH that the STA " ..
"used during the Initial Mobility Domain Association."))
- r0kh:depends({ieee80211r="1", ft_psk_generate_local=""})
+ r0kh:depends({ieee80211r="1"})
r0kh.rmempty = true
r1kh = s:taboption("encryption", DynamicList, "r1kh", translate("External R1 Key Holder List"),
@@ -936,7 +938,7 @@ if hwtype == "mac80211" or hwtype == "prism2" then
"<br />This list is used to map R1KH-ID to a destination MAC address " ..
"when sending PMK-R1 key from the R0KH. This is also the " ..
"list of authorized R1KHs in the MD that can request PMK-R1 keys."))
- r1kh:depends({ieee80211r="1", ft_psk_generate_local=""})
+ r1kh:depends({ieee80211r="1"})
r1kh.rmempty = true
-- End of 802.11r options
diff --git a/modules/luci-mod-network/luasrc/model/cbi/admin_network/wifi_overview.lua b/modules/luci-mod-network/luasrc/model/cbi/admin_network/wifi_overview.lua
index 3bffb3502c..54720d6889 100644
--- a/modules/luci-mod-network/luasrc/model/cbi/admin_network/wifi_overview.lua
+++ b/modules/luci-mod-network/luasrc/model/cbi/admin_network/wifi_overview.lua
@@ -64,68 +64,6 @@ function guess_wifi_hw(dev)
end
end
-local tpl_radio = tpl.Template(nil, [[
- <div class="cbi-section-node">
- <div class="table">
- <!-- physical device -->
- <div class="tr cbi-rowstyle-2">
- <div class="td col-2 center middle">
- <span class="ifacebadge"><img src="<%=resource%>/icons/wifi_disabled.png" id="<%=dev:name()%>-iw-upstate" /> <%=dev:name()%></span>
- </div>
- <div class="td col-7 left middle">
- <big><strong><%=hw%></strong></big><br />
- <span id="<%=dev:name()%>-iw-devinfo"></span>
- </div>
- <div class="td middle cbi-section-actions">
- <div>
- <input type="button" class="cbi-button cbi-button-neutral" title="<%:Restart radio interface%>" value="<%:Restart%>" data-radio="<%=dev:name()%>" onclick="wifi_restart(event)" />
- <input type="button" class="cbi-button cbi-button-action important" title="<%:Find and join network%>" value="<%:Scan%>" onclick="cbi_submit(this, 'device', '<%=dev:name()%>', '<%=url('admin/network/wireless_join')%>')" />
- <input type="button" class="cbi-button cbi-button-add" title="<%:Provide new network%>" value="<%:Add%>" onclick="cbi_submit(this, 'device', '<%=dev:name()%>', '<%=url('admin/network/wireless_add')%>')" />
- </div>
- </div>
- </div>
- <!-- /physical device -->
-
- <!-- network list -->
- <% if #wnets > 0 then %>
- <% for i, net in ipairs(wnets) do local disabled = (dev:get("disabled") == "1" or net:get("disabled") == "1") %>
- <div class="tr cbi-rowstyle-<%=1 + ((i-1) % 2)%>">
- <div class="td col-2 center middle" id="<%=net:id()%>-iw-signal">
- <span class="ifacebadge" title="<%:Not associated%>"><img src="<%=resource%>/icons/signal-<%= disabled and "none" or "0" %>.png" /> 0%</span>
- </div>
- <div class="td col-7 left middle" id="<%=net:id()%>-iw-status" data-network="<%=net:id()%>" data-disabled="<%= disabled and "true" or "false" %>">
- <em><%= disabled and translate("Wireless is disabled") or translate("Collecting data...") %></em>
- </div>
- <div class="td middle cbi-section-actions">
- <div>
- <% if disabled then %>
- <input name="cbid.wireless.<%=net:name()%>.__disable__" type="hidden" value="1" />
- <input name="cbi.apply" type="submit" class="cbi-button cbi-button-neutral" title="<%:Enable this network%>" value="<%:Enable%>" onclick="this.previousElementSibling.value='0'" />
- <% else %>
- <input name="cbid.wireless.<%=net:name()%>.__disable__" type="hidden" value="0" />
- <input name="cbi.apply" type="submit" class="cbi-button cbi-button-neutral" title="<%:Disable this network%>" value="<%:Disable%>" onclick="this.previousElementSibling.value='1'" />
- <% end %>
-
- <input type="button" class="cbi-button cbi-button-action important" onclick="location.href='<%=net:adminlink()%>'" title="<%:Edit this network%>" value="<%:Edit%>" />
-
- <input name="cbid.wireless.<%=net:name()%>.__delete__" type="hidden" value="" />
- <input name="cbi.apply" type="submit" class="cbi-button cbi-button-negative" title="<%:Delete this network%>" value="<%:Remove%>" onclick="wifi_delete(event)" />
- </div>
- </div>
- </div>
- <% end %>
- <% else %>
- <div class="tr placeholder">
- <div class="td">
- <em><%:No network configured on this device%></em>
- </div>
- </div>
- <% end %>
- <!-- /network list -->
- </div>
- </div>
-]])
-
m = Map("wireless", translate("Wireless Overview"))
m:chain("network")
@@ -147,15 +85,10 @@ end
local _, dev, net
for _, dev in ipairs(ntm:get_wifidevs()) do
s = m:section(TypedSection)
+ s.template = "admin_network/wifi_overview"
s.wnets = dev:get_wifinets()
-
- function s.render(self, sid)
- tpl_radio:render({
- hw = guess_wifi_hw(dev),
- dev = dev,
- wnets = self.wnets
- })
- end
+ s.dev = dev
+ s.hw = guess_wifi_hw(dev)
function s.cfgsections(self)
local _, net, sl = nil, nil, { }
@@ -208,9 +141,6 @@ for _, dev in ipairs(ntm:get_wifidevs()) do
end
end
-s = m:section(NamedSection, "__script__")
-s.template = "admin_network/wifi_overview_status"
-
s = m:section(NamedSection, "__assoclist__")
function s.render(self, sid)
diff --git a/modules/luci-mod-network/luasrc/view/admin_network/iface_overview.htm b/modules/luci-mod-network/luasrc/view/admin_network/iface_overview.htm
new file mode 100644
index 0000000000..9d4afd2b27
--- /dev/null
+++ b/modules/luci-mod-network/luasrc/view/admin_network/iface_overview.htm
@@ -0,0 +1,53 @@
+<div class="cbi-section-node">
+ <div class="table">
+ <%
+ for i, net in ipairs(self.netlist) do
+ local z = net[3]
+ local c = z and z:get_color() or "#EEEEEE"
+ local t = z and translate("Part of zone %q") % z:name() or translate("No zone assigned")
+ local disabled = (net[4]:get("auto") == "0")
+ local dynamic = net[4]:is_dynamic()
+ %>
+ <div class="tr cbi-rowstyle-<%=i % 2 + 1%>">
+ <div class="td col-3 center middle">
+ <div class="ifacebox">
+ <div class="ifacebox-head" style="background-color:<%=c%>" title="<%=pcdata(t)%>">
+ <strong><%=net[1]:upper()%></strong>
+ </div>
+ <div class="ifacebox-body" id="<%=net[1]%>-ifc-devices" data-network="<%=net[1]%>">
+ <img src="<%=resource%>/icons/ethernet_disabled.png" style="width:16px; height:16px" /><br />
+ <small>?</small>
+ </div>
+ </div>
+ </div>
+ <div class="td col-5 left middle" id="<%=net[1]%>-ifc-description">
+ <em><%:Collecting data...%></em>
+ </div>
+ <div class="td cbi-section-actions">
+ <div>
+ <input type="button" class="cbi-button cbi-button-neutral" onclick="iface_reconnect('<%=net[1]%>')" title="<%:Reconnect this interface%>" value="<%:Restart%>"<%=ifattr(disabled or dynamic, "disabled", "disabled")%> />
+
+ <% if disabled then %>
+ <input type="hidden" name="cbid.network.<%=net[1]%>.__disable__" value="1" />
+ <input type="submit" name="cbi.apply" class="cbi-button cbi-button-neutral" onclick="this.previousElementSibling.value='0'" title="<%:Reconnect this interface%>" value="<%:Connect%>"<%=ifattr(dynamic, "disabled", "disabled")%> />
+ <% else %>
+ <input type="hidden" name="cbid.network.<%=net[1]%>.__disable__" value="0" />
+ <input type="submit" name="cbi.apply" class="cbi-button cbi-button-neutral" onclick="this.previousElementSibling.value='1'" title="<%:Shutdown this interface%>" value="<%:Stop%>"<%=ifattr(dynamic, "disabled", "disabled")%> />
+ <% end %>
+
+ <input type="button" class="cbi-button cbi-button-action important" onclick="location.href='<%=url("admin/network/network", net[1])%>'" title="<%:Edit this interface%>" value="<%:Edit%>" id="<%=net[1]%>-ifc-edit"<%=ifattr(dynamic, "disabled", "disabled")%> />
+
+ <input type="hidden" name="cbid.network.<%=net[1]%>.__delete__" value="" />
+ <input type="submit" name="cbi.apply" class="cbi-button cbi-button-negative" onclick="iface_delete(event)" value="<%:Delete%>"<%=ifattr(dynamic, "disabled", "disabled")%> />
+ </div>
+ </div>
+ </div>
+ <% end %>
+ </div>
+</div>
+
+<div class="cbi-section-create">
+ <input type="button" class="cbi-button cbi-button-add" value="<%:Add new interface...%>" onclick="location.href='<%=url("admin/network/iface_add")%>'" />
+</div>
+
+<script type="text/javascript" src="<%=resource%>/view/network/network.js"></script>
diff --git a/modules/luci-mod-network/luasrc/view/admin_network/iface_overview_status.htm b/modules/luci-mod-network/luasrc/view/admin_network/iface_overview_status.htm
deleted file mode 100644
index 7427154a04..0000000000
--- a/modules/luci-mod-network/luasrc/view/admin_network/iface_overview_status.htm
+++ /dev/null
@@ -1,183 +0,0 @@
-<%#
- Copyright 2010-2018 Jo-Philipp Wich <jo@mein.io>
- Licensed to the public under the Apache License 2.0.
--%>
-
-<script type="text/javascript">//<![CDATA[
- function iface_reconnect(id) {
- XHR.halt();
-
- var d = document.getElementById(id + '-ifc-description');
- if (d) d.innerHTML = '<em><%:Interface is reconnecting...%></em>';
-
- (new XHR()).post('<%=url('admin/network/iface_reconnect')%>/' + id,
- { token: '<%=token%>' }, XHR.run);
- }
-
- function iface_delete(ev) {
- if (!confirm(<%=luci.http.write_json(translate('Really delete this interface? The deletion cannot be undone! You might lose access to this device if you are connected via this interface'))%>)) {
- ev.preventDefault();
- return false;
- }
-
- ev.target.previousElementSibling.value = '1';
- return true;
- }
-
- var networks = [];
-
- document.querySelectorAll('[data-network]').forEach(function(n) {
- networks.push(n.getAttribute('data-network'));
- });
-
- function render_iface(ifc) {
- return E('span', { class: 'cbi-tooltip-container' }, [
- E('img', { 'class' : 'middle', 'src': '<%=resource%>/icons/%s%s.png'.format(
- ifc.is_alias ? 'alias' : ifc.type,
- ifc.is_up ? '' : '_disabled') }),
- E('span', { 'class': 'cbi-tooltip ifacebadge large' }, [
- E('img', { 'src': '<%=resource%>/icons/%s%s.png'.format(
- ifc.type, ifc.is_up ? '' : '_disabled') }),
- E('span', { 'class': 'left' }, [
- E('strong', '<%:Type%>: '), ifc.typename, E('br'),
- E('strong', '<%:Device%>: '), ifc.ifname, E('br'),
- E('strong', '<%:Connected%>: '), ifc.is_up ? '<%:yes%>' : '<%:no%>', E('br'),
- ifc.macaddr ? E('strong', '<%:MAC%>: ') : '',
- ifc.macaddr ? ifc.macaddr : '',
- ifc.macaddr ? E('br') : '',
- E('strong', '<%:RX%>: '), '%.2mB (%d <%:Pkts.%>)'.format(ifc.rx_bytes, ifc.rx_packets), E('br'),
- E('strong', '<%:TX%>: '), '%.2mB (%d <%:Pkts.%>)'.format(ifc.tx_bytes, ifc.tx_packets)
- ])
- ])
- ]);
- }
-
- XHR.poll(5, '<%=url('admin/network/iface_status')%>/' + networks.join(','), null,
- function(x, ifcs)
- {
- if (ifcs)
- {
- for (var idx = 0; idx < ifcs.length; idx++)
- {
- var ifc = ifcs[idx];
- var html = '';
-
- var s = document.getElementById(ifc.id + '-ifc-devices');
- if (s)
- {
- while (s.firstChild)
- s.removeChild(s.firstChild);
-
- s.appendChild(render_iface(ifc));
-
- if (ifc.subdevices && ifc.subdevices.length)
- {
- var sifs = [ ' (' ];
-
- for (var j = 0; j < ifc.subdevices.length; j++)
- sifs.push(render_iface(ifc.subdevices[j]));
-
- sifs.push(')');
-
- s.appendChild(E('span', {}, sifs));
- }
-
- s.appendChild(E('br'));
- s.appendChild(E('small', {}, ifc.is_alias ? '<%:Alias of "%s"%>'.format(ifc.is_alias) : ifc.name));
- }
-
- var d = document.getElementById(ifc.id + '-ifc-description');
- if (d && ifc.proto && ifc.ifname)
- {
- var desc = null;
-
- if (ifc.is_dynamic)
- desc = '<%:Virtual dynamic interface%>';
- else if (ifc.is_alias)
- desc = '<%:Alias Interface%>';
-
- if (ifc.desc)
- desc = desc ? '%s (%s)'.format(desc, ifc.desc) : ifc.desc;
-
- html += String.format('<strong><%:Protocol%>:</strong> %h<br />', desc || '?');
-
- if (ifc.is_up)
- {
- html += String.format('<strong><%:Uptime%>:</strong> %t<br />', ifc.uptime);
- }
-
-
- if (!ifc.is_dynamic && !ifc.is_alias)
- {
- if (ifc.macaddr)
- html += String.format('<strong><%:MAC%>:</strong> %s<br />', ifc.macaddr);
-
- html += String.format(
- '<strong><%:RX%>:</strong> %.2mB (%d <%:Pkts.%>)<br />' +
- '<strong><%:TX%>:</strong> %.2mB (%d <%:Pkts.%>)<br />',
- ifc.rx_bytes, ifc.rx_packets,
- ifc.tx_bytes, ifc.tx_packets
- );
- }
-
- if (ifc.ipaddrs && ifc.ipaddrs.length)
- {
- for (var i = 0; i < ifc.ipaddrs.length; i++)
- html += String.format(
- '<strong><%:IPv4%>:</strong> %s<br />',
- ifc.ipaddrs[i]
- );
- }
-
- if (ifc.ip6addrs && ifc.ip6addrs.length)
- {
- for (var i = 0; i < ifc.ip6addrs.length; i++)
- html += String.format(
- '<strong><%:IPv6%>:</strong> %s<br />',
- ifc.ip6addrs[i]
- );
- }
-
- if (ifc.ip6prefix)
- html += String.format('<strong><%:IPv6-PD%>:</strong> %s<br />', ifc.ip6prefix);
-
- if (ifc.errors)
- {
- for (var i = 0; i < ifc.errors.length; i++)
- html += String.format(
- '<em class="error"><strong><%:Error%>:</strong> %h</em><br />',
- ifc.errors[i]
- );
- }
-
- d.innerHTML = html;
- }
- else if (d && !ifc.proto)
- {
- var e = document.getElementById(ifc.id + '-ifc-edit');
- if (e)
- e.disabled = true;
-
- d.innerHTML = String.format(
- '<em><%:Unsupported protocol type.%></em><br />' +
- '<a href="%h"><%:Install protocol extensions...%></a>',
- '<%=url("admin/system/packages")%>?query=luci-proto&display=available'
- );
- }
- else if (d && !ifc.ifname)
- {
- d.innerHTML = String.format(
- '<em><%:Network without interfaces.%></em><br />' +
- '<a href="<%=url("admin/network/network/%s")%>?tab.network.%s=physical"><%:Assign interfaces...%></a>',
- ifc.name, ifc.name
- );
- }
- else if (d)
- {
- d.innerHTML = '<em><%:Interface not present or not connected yet.%></em>';
- }
- }
- }
- }
- );
-//]]></script>
diff --git a/modules/luci-mod-network/luasrc/view/admin_network/iface_status.htm b/modules/luci-mod-network/luasrc/view/admin_network/iface_status.htm
index 34be35dd20..a75b2755cd 100644
--- a/modules/luci-mod-network/luasrc/view/admin_network/iface_status.htm
+++ b/modules/luci-mod-network/luasrc/view/admin_network/iface_status.htm
@@ -1,66 +1,12 @@
<%+cbi/valueheader%>
-<script type="text/javascript">//<![CDATA[
- XHR.poll(5, '<%=url('admin/network/iface_status', self.network)%>', null,
- function(x, ifc)
- {
- if (ifc && (ifc = ifc[0]))
- {
- var s = document.getElementById('<%=self.option%>-ifc-status'),
- img = s.querySelector('img'),
- info = s.querySelector('span'),
- html = '<strong><%:Device%>:</strong> %h<br />'.format(ifc.ifname);
-
- if (ifc.ifname)
- {
- if (ifc.is_up)
- html += String.format('<strong><%:Uptime%>:</strong> %t<br />', ifc.uptime);
-
- if (ifc.macaddr)
- html += String.format('<strong><%:MAC%>:</strong> %s<br />', ifc.macaddr);
-
- html += String.format(
- '<strong><%:RX%></strong>: %.2mB (%d <%:Pkts.%>)<br />' +
- '<strong><%:TX%></strong>: %.2mB (%d <%:Pkts.%>)<br />',
- ifc.rx_bytes, ifc.rx_packets,
- ifc.tx_bytes, ifc.tx_packets
- );
-
- if (ifc.ipaddrs && ifc.ipaddrs.length)
- for (var i = 0; i < ifc.ipaddrs.length; i++)
- html += String.format(
- '<strong><%:IPv4%>:</strong> %s<br />',
- ifc.ipaddrs[i]
- );
-
- if (ifc.ip6addrs && ifc.ip6addrs.length)
- for (var i = 0; i < ifc.ip6addrs.length; i++)
- html += String.format(
- '<strong><%:IPv6%>:</strong> %s<br />',
- ifc.ip6addrs[i]
- );
-
- if (ifc.ip6prefix)
- html += String.format('<strong><%:IPv6-PD%>:</strong> %s<br />', ifc.ip6prefix);
-
- info.innerHTML = html;
- }
- else
- {
- info.innerHTML = '<em><%:Interface not present or not connected yet.%></em>';
- }
-
- img.src = '<%=resource%>/icons/%s%s.png'.format(ifc.type, ifc.is_up ? '' : '_disabled');
- }
- }
- );
-//]]></script>
-
-<span class="ifacebadge large" id="<%=self.option%>-ifc-status">
+<span class="ifacebadge large"<%=attr("data-iface-status", self.network)%>>
<img src="<%=resource%>/icons/ethernet_disabled.png" />
<span>
- <em><%:Collecting data...%></em>
+ <em class="spinning"><%:Collecting data...%></em>
</span>
</span>
+<script type="text/javascript" src="<%=resource%>/view/network/iface_status.js"></script>
+
<%+cbi/valuefooter%>
diff --git a/modules/luci-mod-network/luasrc/view/admin_network/wifi_join.htm b/modules/luci-mod-network/luasrc/view/admin_network/wifi_join.htm
index 987123642f..5a61ba099c 100644
--- a/modules/luci-mod-network/luasrc/view/admin_network/wifi_join.htm
+++ b/modules/luci-mod-network/luasrc/view/admin_network/wifi_join.htm
@@ -19,185 +19,18 @@
<%+header%>
-<script type="text/javascript">//<![CDATA[
- var xhr = new XHR(),
- poll = null;
-
- function format_signal(bss) {
- var qval = bss.quality || 0,
- qmax = bss.quality_max || 100,
- scale = 100 / qmax * qval,
- range = 'none';
-
- if (!bss.bssid || bss.bssid == '00:00:00:00:00:00')
- range = 'none';
- else if (scale < 15)
- range = '0';
- else if (scale < 35)
- range = '0-25';
- else if (scale < 55)
- range = '25-50';
- else if (scale < 75)
- range = '50-75';
- else
- range = '75-100';
-
- return E('span', {
- class: 'ifacebadge',
- title: '<%:Signal%>: %d<%:dB%> / <%:Quality%>: %d/%d'.format(bss.signal, qval, qmax)
- }, [
- E('img', { src: '<%=resource%>/icons/signal-%s.png'.format(range) }),
- ' %d%%'.format(scale)
- ]);
- }
-
- function format_encryption(bss) {
- var enc = bss.encryption || { }
-
- if (enc.wep === true)
- return 'WEP';
- else if (enc.wpa > 0)
- return E('abbr', {
- title: 'Pairwise: %h / Group: %h'.format(
- enc.pair_ciphers.join(', '),
- enc.group_ciphers.join(', '))
- },
- '%h - %h'.format(
- (enc.wpa === 3) ? '<%:mixed WPA/WPA2%>' : (enc.wpa === 2 ? 'WPA2' : 'WPA'),
- enc.auth_suites.join(', ')));
- else if (enc.enabled)
- return '<em><%:unknown%></em>';
- else
- return '<em><%:open%></em>';
- }
-
- function format_actions(bss) {
- var enc = bss.encryption || { },
- input = [
- E('input', { type: 'submit', class: 'cbi-button cbi-button-action important', value: '<%:Join Network%>' }),
- E('input', { type: 'hidden', name: 'token', value: '<%=token%>' }),
- E('input', { type: 'hidden', name: 'device', value: '<%=dev%>' }),
- E('input', { type: 'hidden', name: 'join', value: bss.ssid }),
- E('input', { type: 'hidden', name: 'mode', value: bss.mode }),
- E('input', { type: 'hidden', name: 'bssid', value: bss.bssid }),
- E('input', { type: 'hidden', name: 'channel', value: bss.channel }),
- E('input', { type: 'hidden', name: 'clbridge', value: <%=iw.type == "wl" and 1 or 0%> }),
- E('input', { type: 'hidden', name: 'wep', value: enc.wep ? 1 : 0 })
- ];
-
- if (enc.wpa) {
- input.push(E('input', { type: 'hidden', name: 'wpa_version', value: enc.wpa }));
-
- enc.auth_suites.forEach(function(s) {
- input.push(E('input', { type: 'hidden', name: 'wpa_suites', value: s }));
- });
-
- enc.group_ciphers.forEach(function(s) {
- input.push(E('input', { type: 'hidden', name: 'wpa_group', value: s }));
- });
-
- enc.pair_ciphers.forEach(function(s) {
- input.push(E('input', { type: 'hidden', name: 'wpa_pairwise', value: s }));
- });
- }
-
- return E('form', {
- class: 'inline',
- method: 'post',
- action: '<%=url("admin/network/wireless_join")%>'
- }, input);
- }
-
- function fade(bss, content) {
- if (bss.stale)
- return E('span', { style: 'opacity:0.5' }, content);
- else
- return content;
- }
-
- function flush() {
- XHR.stop(poll);
- XHR.halt();
-
- scan();
- }
-
- function scan() {
- var tbl = document.getElementById('scan_results');
-
- cbi_update_table(tbl, [], '<em><img src="<%=resource%>/icons/loading.gif" class="middle" /> <%:Starting wireless scan...%></em>');
-
- xhr.post('<%=url("admin/network/wireless_scan_trigger", dev)%>', { token: '<%=token%>' },
- function(s) {
- if (s.status !== 200) {
- cbi_update_table(tbl, [], '<em><%:Scan request failed%></em>');
- return;
- }
-
- var count = 0;
-
- poll = XHR.poll(3, '<%=url("admin/network/wireless_scan_results", dev)%>', null,
- function(s, results) {
- if (Array.isArray(results)) {
- var bss = [];
-
- results.sort(function(a, b) {
- var diff = (b.quality - a.quality) || (a.channel - b.channel);
-
- if (diff)
- return diff;
-
- if (a.ssid < b.ssid)
- return -1;
- else if (a.ssid > b.ssid)
- return 1;
-
- if (a.bssid < b.bssid)
- return -1;
- else if (a.bssid > b.bssid)
- return 1;
- }).forEach(function(res) {
- bss.push([
- fade(res, format_signal(res)),
- fade(res, res.ssid ? '%h'.format(res.ssid) : E('em', {}, '<%:hidden%>')),
- fade(res, res.channel),
- fade(res, res.mode),
- fade(res, res.bssid),
- fade(res, format_encryption(res)),
- format_actions(res)
- ]);
- });
-
- cbi_update_table(tbl, bss, '<em><img src="<%=resource%>/icons/loading.gif" class="middle" /> <%:No scan results available yet...%>');
- }
-
- if (count++ >= 3) {
- count = 0;
- xhr.post('<%=url("admin/network/wireless_scan_trigger", dev, "1")%>',
- { token: '<%=token%>' }, function() { });
- }
- });
-
- XHR.run();
- });
- }
-
- document.addEventListener('DOMContentLoaded', scan);
-
-//]]></script>
-
<h2 name="content"><%:Join Network: Wireless Scan%></h2>
<div class="cbi-map">
<div class="cbi-section">
- <div class="table" id="scan_results">
+ <div class="table"<%=attr("data-wifi-scan", dev) .. attr("data-wifi-type", iw.type)%>>
<div class="tr table-titles">
- <div class="th col-1 middle center"><%:Signal%></div>
- <div class="th col-5 middle left"><%:SSID%></div>
- <div class="th col-2 middle center"><%:Channel%></div>
- <div class="th col-2 middle left"><%:Mode%></div>
- <div class="th col-3 middle left"><%:BSSID%></div>
- <div class="th col-2 middle left"><%:Encryption%></div>
+ <div class="th col-2 middle center"><%:Signal%></div>
+ <div class="th col-4 middle left"><%:SSID%></div>
+ <div class="th col-2 middle center hide-xs"><%:Channel%></div>
+ <div class="th col-2 middle left hide-xs"><%:Mode%></div>
+ <div class="th col-3 middle left hide-xs"><%:BSSID%></div>
+ <div class="th col-3 middle left"><%:Encryption%></div>
<div class="th cbi-section-actions">&#160;</div>
</div>
@@ -221,4 +54,6 @@
</form>
</div>
+<script type="text/javascript" src="<%=resource%>/view/network/wifi_join.js"></script>
+
<%+footer%>
diff --git a/modules/luci-mod-network/luasrc/view/admin_network/wifi_overview.htm b/modules/luci-mod-network/luasrc/view/admin_network/wifi_overview.htm
new file mode 100644
index 0000000000..89bb404fd8
--- /dev/null
+++ b/modules/luci-mod-network/luasrc/view/admin_network/wifi_overview.htm
@@ -0,0 +1,61 @@
+<div class="cbi-section-node">
+ <div class="table">
+ <!-- physical device -->
+ <div class="tr cbi-rowstyle-2">
+ <div class="td col-2 center middle">
+ <span class="ifacebadge"><img src="<%=resource%>/icons/wifi_disabled.png" id="<%=self.dev:name()%>-iw-upstate" /> <%=self.dev:name()%></span>
+ </div>
+ <div class="td col-7 left middle">
+ <big><strong><%=self.hw%></strong></big><br />
+ <span id="<%=self.dev:name()%>-iw-devinfo"></span>
+ </div>
+ <div class="td middle cbi-section-actions">
+ <div>
+ <input type="button" class="cbi-button cbi-button-neutral" title="<%:Restart radio interface%>" value="<%:Restart%>" data-radio="<%=self.dev:name()%>" onclick="wifi_restart(event)" />
+ <input type="button" class="cbi-button cbi-button-action important" title="<%:Find and join network%>" value="<%:Scan%>" onclick="cbi_submit(this, 'device', '<%=self.dev:name()%>', '<%=url('admin/network/wireless_join')%>')" />
+ <input type="button" class="cbi-button cbi-button-add" title="<%:Provide new network%>" value="<%:Add%>" onclick="cbi_submit(this, 'device', '<%=self.dev:name()%>', '<%=url('admin/network/wireless_add')%>')" />
+ </div>
+ </div>
+ </div>
+ <!-- /physical device -->
+
+ <!-- network list -->
+ <% if #self.wnets > 0 then %>
+ <% for i, net in ipairs(self.wnets) do local disabled = (self.dev:get("disabled") == "1" or net:get("disabled") == "1") %>
+ <div class="tr cbi-rowstyle-<%=1 + ((i-1) % 2)%>">
+ <div class="td col-2 center middle" id="<%=net:id()%>-iw-signal">
+ <span class="ifacebadge" title="<%:Not associated%>"><img src="<%=resource%>/icons/signal-<%= disabled and "none" or "0" %>.png" /> 0%</span>
+ </div>
+ <div class="td col-7 left middle" id="<%=net:id()%>-iw-status" data-network="<%=net:id()%>" data-disabled="<%= disabled and "true" or "false" %>">
+ <em><%= disabled and translate("Wireless is disabled") or translate("Collecting data...") %></em>
+ </div>
+ <div class="td middle cbi-section-actions">
+ <div>
+ <% if disabled then %>
+ <input name="cbid.wireless.<%=net:name()%>.__disable__" type="hidden" value="1" />
+ <input name="cbi.apply" type="submit" class="cbi-button cbi-button-neutral" title="<%:Enable this network%>" value="<%:Enable%>" onclick="this.previousElementSibling.value='0'" />
+ <% else %>
+ <input name="cbid.wireless.<%=net:name()%>.__disable__" type="hidden" value="0" />
+ <input name="cbi.apply" type="submit" class="cbi-button cbi-button-neutral" title="<%:Disable this network%>" value="<%:Disable%>" onclick="this.previousElementSibling.value='1'" />
+ <% end %>
+
+ <input type="button" class="cbi-button cbi-button-action important" onclick="location.href='<%=net:adminlink()%>'" title="<%:Edit this network%>" value="<%:Edit%>" />
+
+ <input name="cbid.wireless.<%=net:name()%>.__delete__" type="hidden" value="" />
+ <input name="cbi.apply" type="submit" class="cbi-button cbi-button-negative" title="<%:Delete this network%>" value="<%:Remove%>" onclick="wifi_delete(event)" />
+ </div>
+ </div>
+ </div>
+ <% end %>
+ <% else %>
+ <div class="tr placeholder">
+ <div class="td">
+ <em><%:No network configured on this device%></em>
+ </div>
+ </div>
+ <% end %>
+ <!-- /network list -->
+ </div>
+</div>
+
+<script type="text/javascript" src="<%=resource%>/view/network/wireless.js"></script>
diff --git a/modules/luci-mod-network/luasrc/view/admin_network/wifi_overview_status.htm b/modules/luci-mod-network/luasrc/view/admin_network/wifi_overview_status.htm
deleted file mode 100644
index 9730bc2c92..0000000000
--- a/modules/luci-mod-network/luasrc/view/admin_network/wifi_overview_status.htm
+++ /dev/null
@@ -1,127 +0,0 @@
-<%#
- Copyright 2008-2009 Steven Barth <steven@midlink.org>
- Copyright 2008-2018 Jo-Philipp Wich <jo@mein.io>
- Licensed to the public under the Apache License 2.0.
--%>
-
-<script type="text/javascript">//<![CDATA[
- function wifi_delete(ev) {
- if (!confirm(<%=luci.http.write_json(translate('Really delete this wireless network? The deletion cannot be undone! You might lose access to this device if you are connected via this network.'))%>)) {
- ev.preventDefault();
- return false;
- }
-
- ev.target.previousElementSibling.value = '1';
- return true;
- }
-
- function wifi_restart(ev) {
- XHR.halt();
-
- findParent(ev.target, '.table').querySelectorAll('[data-disabled="false"]').forEach(function(s) {
- s.innerHTML = '<em><%:Wireless is restarting...%></em>';
- });
-
- (new XHR()).post('<%=url('admin/network/wireless_reconnect')%>/' + ev.target.getAttribute('data-radio'),
- { token: '<%=token%>' }, XHR.run);
- }
-
- var networks = [ ];
-
- document.querySelectorAll('[data-network]').forEach(function(n) {
- networks.push(n.getAttribute('data-network'));
- });
-
- XHR.poll(5, '<%=url('admin/network/wireless_status')%>/' + networks.join(','), null,
- function(x, st)
- {
- if (st)
- {
- var rowstyle = 1;
- var radiostate = { };
-
- st.forEach(function(s) {
- var r = radiostate[s.device.device] || (radiostate[s.device.device] = {});
-
- s.is_assoc = (s.bssid && s.bssid != '00:00:00:00:00:00' && s.channel && s.mode != 'Unknown' && !s.disabled);
-
- r.up = r.up || s.is_assoc;
- r.channel = r.channel || s.channel;
- r.bitrate = r.bitrate || s.bitrate;
- r.frequency = r.frequency || s.frequency;
- });
-
- for( var i = 0; i < st.length; i++ )
- {
- var iw = st[i],
- sig = document.getElementById(iw.id + '-iw-signal'),
- info = document.getElementById(iw.id + '-iw-status'),
- disabled = (info && info.getAttribute('data-disabled') === 'true');
-
- var p = iw.quality;
- var q = disabled ? -1 : p;
-
- var icon;
- if (q < 0)
- icon = "<%=resource%>/icons/signal-none.png";
- else if (q == 0)
- icon = "<%=resource%>/icons/signal-0.png";
- else if (q < 25)
- icon = "<%=resource%>/icons/signal-0-25.png";
- else if (q < 50)
- icon = "<%=resource%>/icons/signal-25-50.png";
- else if (q < 75)
- icon = "<%=resource%>/icons/signal-50-75.png";
- else
- icon = "<%=resource%>/icons/signal-75-100.png";
-
-
- if (sig)
- sig.innerHTML = String.format(
- '<span class="ifacebadge" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%>"><img src="%s" /> %d%%</span>',
- iw.signal, iw.noise, icon, p
- );
-
- if (info)
- {
- if (iw.is_assoc)
- info.innerHTML = String.format(
- '<strong><%:SSID%>:</strong> %h | ' +
- '<strong><%:Mode%>:</strong> %s<br />' +
- '<strong><%:BSSID%>:</strong> %s | ' +
- '<strong><%:Encryption%>:</strong> %s',
- iw.ssid, iw.mode, iw.bssid,
- iw.encryption ? iw.encryption : '<%:None%>'
- );
- else
- info.innerHTML = String.format(
- '<strong><%:SSID%>:</strong> %h | ' +
- '<strong><%:Mode%>:</strong> %s<br />' +
- '<em>%s</em>',
- iw.ssid || '?', iw.mode,
- disabled ? '<em><%:Wireless is disabled%></em>'
- : '<em><%:Wireless is not associated%></em>'
- );
- }
- }
-
- for (var dev in radiostate)
- {
- var img = document.getElementById(dev + '-iw-upstate');
- if (img)
- img.src = '<%=resource%>/icons/wifi' + (radiostate[dev].up ? '' : '_disabled') + '.png';
-
- var stat = document.getElementById(dev + '-iw-devinfo');
- if (stat)
- stat.innerHTML = String.format(
- '<strong><%:Channel%>:</strong> %s (%s <%:GHz%>) | ' +
- '<strong><%:Bitrate%>:</strong> %s <%:Mbit/s%>',
- radiostate[dev].channel ? radiostate[dev].channel : '?',
- radiostate[dev].frequency ? radiostate[dev].frequency : '?',
- radiostate[dev].bitrate ? radiostate[dev].bitrate : '?'
- );
- }
- }
- }
- );
-//]]></script>
diff --git a/modules/luci-mod-network/luasrc/view/admin_network/wifi_status.htm b/modules/luci-mod-network/luasrc/view/admin_network/wifi_status.htm
index bfad3d0804..93ae2f51fb 100644
--- a/modules/luci-mod-network/luasrc/view/admin_network/wifi_status.htm
+++ b/modules/luci-mod-network/luasrc/view/admin_network/wifi_status.htm
@@ -1,77 +1,14 @@
<%+cbi/valueheader%>
-<script type="text/javascript">//<![CDATA[
- XHR.poll(5, '<%=url('admin/network/wireless_status', self.ifname)%>', null,
- function(x, iw)
- {
- if (iw && (iw = iw[0]))
- {
- var is_assoc = (iw.bssid && iw.bssid != '00:00:00:00:00:00' && iw.channel && !iw.disabled);
- var p = iw.quality;
- var q = iw.disabled ? -1 : p;
-
- var icon;
- if (q < 0)
- icon = "<%=resource%>/icons/signal-none.png";
- else if (q == 0)
- icon = "<%=resource%>/icons/signal-0.png";
- else if (q < 25)
- icon = "<%=resource%>/icons/signal-0-25.png";
- else if (q < 50)
- icon = "<%=resource%>/icons/signal-25-50.png";
- else if (q < 75)
- icon = "<%=resource%>/icons/signal-50-75.png";
- else
- icon = "<%=resource%>/icons/signal-75-100.png";
-
- var s = document.getElementById('<%=self.option%>-iw-status'),
- small = s.querySelector('small'),
- info = s.querySelector('span');
-
- small.innerHTML = info.innerHTML = String.format(
- '<img src="%s" title="<%:Signal%>: %d <%:dBm%> / <%:Noise%>: %d <%:dBm%>" />&#160;<br />%d%%&#160;',
- icon, iw.signal, iw.noise, p
- );
-
- if (is_assoc)
- info.innerHTML = String.format(
- '<strong><%:Mode%>:</strong> %s | ' +
- '<strong><%:SSID%>:</strong> %h<br />' +
- '<strong><%:BSSID%>:</strong> %s<br />' +
- '<strong><%:Encryption%>:</strong> %s<br />' +
- '<strong><%:Channel%>:</strong> %d (%.3f <%:GHz%>)<br />' +
- '<strong><%:Tx-Power%>:</strong> %d <%:dBm%><br />' +
- '<strong><%:Signal%>:</strong> %d <%:dBm%> | ' +
- '<strong><%:Noise%>:</strong> %d <%:dBm%><br />' +
- '<strong><%:Bitrate%>:</strong> %.1f <%:Mbit/s%> | ' +
- '<strong><%:Country%>:</strong> %s',
- iw.mode, iw.ssid, iw.bssid,
- iw.encryption ? iw.encryption : '<%:None%>',
- iw.channel, iw.frequency ? iw.frequency : 0,
- iw.txpower, iw.signal, iw.noise,
- iw.bitrate ? iw.bitrate : 0, iw.country
- );
- else
- info.innerHTML = String.format(
- '<strong><%:SSID%>:</strong> %h | ' +
- '<strong><%:Mode%>:</strong> %s<br />' +
- '<em>%s</em>',
- iw.ssid || '?', iw.mode,
- iw.disabled ? '<em><%:Wireless is disabled%></em>'
- : '<em><%:Wireless is not associated%></em>'
- );
- }
- }
- );
-//]]></script>
-
-<span class="ifacebadge large" id="<%=self.option%>-iw-status">
+<span class="ifacebadge large"<%=attr("data-wifi-status", self.ifname)%>>
<small>
<img src="<%=resource%>/icons/signal-none.png" title="<%:Not associated%>" />&#160;
</small>
<span>
- <em><%:Collecting data...%></em>
+ <em class="spinning"><%:Collecting data...%></em>
</span>
</span>
+<script type="text/javascript" src="<%=resource%>/view/network/wifi_status.js"></script>
+
<%+cbi/valuefooter%>