diff --git a/luci-base/Makefile b/luci-base/Makefile
index 264bfe9f4..fc8a31d2a 100644
--- a/luci-base/Makefile
+++ b/luci-base/Makefile
@@ -14,12 +14,13 @@ LUCI_BASENAME:=base
LUCI_TITLE:=LuCI core libraries
LUCI_DEPENDS:=+lua +luci-lib-nixio +luci-lib-ip +rpcd +libubus-lua +luci-lib-jsonc +liblucihttp-lua
-PKG_SOURCE:=LuaSrcDiet-0.12.1.tar.bz2
-PKG_SOURCE_URL:=https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/luasrcdiet
-PKG_HASH:=ed7680f2896269ae8633756e7edcf09050812f78c8f49e280e63c30d14f35aea
-PKG_LICENSE:=Apache-2.0
-HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/LuaSrcDiet-0.12.1
+PKG_SOURCE:=v1.0.0.tar.gz
+PKG_SOURCE_URL:=https://github.com/jirutka/luasrcdiet/archive/
+PKG_HASH:=48162e63e77d009f5848f18a5cabffbdfc867d0e5e73c6d407f6af5d6880151b
+PKG_LICENSE:=MIT
+
+HOST_BUILD_DIR:=$(BUILD_DIR_HOST)/luasrcdiet-1.0.0
include $(INCLUDE_DIR)/host-build.mk
@@ -36,13 +37,13 @@ endef
define Host/Compile
$(MAKE) -C src/ clean po2lmo
- $(MAKE) -C $(HOST_BUILD_DIR) bin/LuaSrcDiet.lua
+ $(MAKE) -C $(HOST_BUILD_DIR) bin/luasrcdiet
endef
define Host/Install
$(INSTALL_DIR) $(1)/bin
$(INSTALL_BIN) src/po2lmo $(1)/bin/po2lmo
- $(INSTALL_BIN) $(HOST_BUILD_DIR)/bin/LuaSrcDiet.lua $(1)/bin/LuaSrcDiet
+ $(INSTALL_BIN) $(HOST_BUILD_DIR)/bin/luasrcdiet $(1)/bin/luasrcdiet
endef
$(eval $(call HostBuild))
diff --git a/luci-base/htdocs/luci-static/resources/cbi.js b/luci-base/htdocs/luci-static/resources/cbi.js
index a7f999d87..6a487366f 100644
--- a/luci-base/htdocs/luci-static/resources/cbi.js
+++ b/luci-base/htdocs/luci-static/resources/cbi.js
@@ -620,7 +620,11 @@ function cbi_init() {
}
document.querySelectorAll('.cbi-dropdown').forEach(function(s) {
- cbi_dropdown_init(s);
+ cbi_dropdown_init(s);
+ });
+
+ document.querySelectorAll('.cbi-tooltip:not(:empty)').forEach(function(s) {
+ s.parentNode.classList.add('cbi-tooltip-container');
});
cbi_d_update();
@@ -1232,14 +1236,13 @@ function cbi_validate_field(cbid, optional, type)
function cbi_row_swap(elem, up, store)
{
- var tr = elem.parentNode;
-
- while (tr && !tr.classList.contains('cbi-section-table-row'))
- tr = tr.parentNode;
+ var tr = findParent(elem.parentNode, '.cbi-section-table-row');
if (!tr)
return false;
+ tr.classList.remove('flash');
+
if (up) {
var prev = tr.previousElementSibling;
@@ -1277,6 +1280,9 @@ function cbi_row_swap(elem, up, store)
if (input)
input.value = ids.join(' ');
+ window.scrollTo(0, tr.offsetTop);
+ window.setTimeout(function() { tr.classList.add('flash'); }, 1);
+
return false;
}
@@ -1522,6 +1528,19 @@ function toElem(s)
return elem || null;
}
+function findParent(node, selector)
+{
+ while (node)
+ if (node.msMatchesSelector && node.msMatchesSelector(selector))
+ return node;
+ else if (node.matches && node.matches(selector))
+ return node;
+ else
+ node = node.parentNode;
+
+ return null;
+}
+
function E()
{
var html = arguments[0],
@@ -1541,7 +1560,7 @@ function E()
if (attr)
for (var key in attr)
- if (attr.hasOwnProperty(key))
+ if (attr.hasOwnProperty(key) && attr[key] !== null && attr[key] !== undefined)
elem.setAttribute(key, attr[key]);
if (typeof(data) === 'function')
@@ -1818,18 +1837,6 @@ CBIDropdown = {
document.querySelectorAll('.cbi-dropdown[open]').forEach(function(s) {
s.dispatchEvent(new CustomEvent('cbi-dropdown-close', {}));
});
- },
-
- findParent: function(node, selector) {
- while (node)
- if (node.msMatchesSelector && node.msMatchesSelector(selector))
- return node;
- else if (node.matches && node.matches(selector))
- return node;
- else
- node = node.parentNode;
-
- return null;
}
};
@@ -1908,7 +1915,7 @@ function cbi_dropdown_init(sb) {
sbox.openDropdown(this);
}
else {
- var li = sbox.findParent(ev.target, 'li');
+ var li = findParent(ev.target, 'li');
if (li && li.parentNode.classList.contains('dropdown'))
sbox.toggleItem(this, li);
}
@@ -1933,7 +1940,7 @@ function cbi_dropdown_init(sb) {
}
else
{
- var active = sbox.findParent(document.activeElement, 'li');
+ var active = findParent(document.activeElement, 'li');
switch (ev.keyCode) {
case 27:
@@ -1986,7 +1993,7 @@ function cbi_dropdown_init(sb) {
if (!this.hasAttribute('open'))
return;
- var li = sbox.findParent(ev.target, 'li');
+ var li = findParent(ev.target, 'li');
if (li) {
if (li.parentNode.classList.contains('dropdown'))
sbox.setFocus(this, li);
@@ -2023,18 +2030,18 @@ function cbi_dropdown_init(sb) {
});
create.addEventListener('focus', function(ev) {
- var cbox = sbox.findParent(this, 'li').querySelector('input[type="checkbox"]');
+ var cbox = findParent(this, 'li').querySelector('input[type="checkbox"]');
if (cbox) cbox.checked = true;
sb.setAttribute('locked-in', '');
});
create.addEventListener('blur', function(ev) {
- var cbox = sbox.findParent(this, 'li').querySelector('input[type="checkbox"]');
+ var cbox = findParent(this, 'li').querySelector('input[type="checkbox"]');
if (cbox) cbox.checked = false;
sb.removeAttribute('locked-in');
});
- var li = sbox.findParent(create, 'li');
+ var li = findParent(create, 'li');
li.setAttribute('unselectable', '');
li.addEventListener('click', function(ev) {
@@ -2044,3 +2051,77 @@ function cbi_dropdown_init(sb) {
}
cbi_dropdown_init.prototype = CBIDropdown;
+
+function cbi_update_table(table, data, placeholder) {
+ target = isElem(table) ? table : document.querySelector(table);
+
+ if (!isElem(target))
+ return;
+
+ target.querySelectorAll('.tr.table-titles, .cbi-section-table-titles').forEach(function(thead) {
+ var titles = [];
+
+ thead.querySelectorAll('.th').forEach(function(th) {
+ titles.push(th);
+ });
+
+ if (Array.isArray(data)) {
+ var n = 0, rows = target.querySelectorAll('.tr');
+
+ data.forEach(function(row) {
+ var trow = E('div', { 'class': 'tr' });
+
+ for (var i = 0; i < titles.length; i++) {
+ var text = titles[i].innerText;
+ var td = trow.appendChild(E('div', {
+ 'class': titles[i].className,
+ 'data-title': text ? text.trim() : null
+ }, row[i] || ''));
+
+ td.classList.remove('th');
+ td.classList.add('td');
+ }
+
+ trow.classList.add('cbi-rowstyle-%d'.format((n++ % 2) ? 2 : 1));
+
+ if (rows[n])
+ target.replaceChild(trow, rows[n]);
+ else
+ target.appendChild(trow);
+ });
+
+ while (rows[++n])
+ target.removeChild(rows[n]);
+
+ if (placeholder && target.firstElementChild === target.lastElementChild) {
+ var trow = target.appendChild(E('div', { 'class': 'tr placeholder' }));
+ var td = trow.appendChild(E('div', { 'class': titles[0].className }, placeholder));
+
+ td.classList.remove('th');
+ td.classList.add('td');
+ }
+ }
+ else {
+ thead.parentNode.style.display = 'none';
+
+ thead.parentNode.querySelectorAll('.tr, .cbi-section-table-row').forEach(function(trow) {
+ if (trow !== thead) {
+ var n = 0;
+ trow.querySelectorAll('.th, .td').forEach(function(td) {
+ if (n < titles.length) {
+ var text = (titles[n++].innerText || '').trim();
+ if (text !== '')
+ td.setAttribute('data-title', text);
+ }
+ });
+ }
+ });
+
+ thead.parentNode.style.display = '';
+ }
+ });
+}
+
+document.addEventListener('DOMContentLoaded', function() {
+ document.querySelectorAll('.table').forEach(cbi_update_table);
+});
diff --git a/luci-base/htdocs/luci-static/resources/xhr.js b/luci-base/htdocs/luci-static/resources/xhr.js
index de4476cdd..f1537a448 100644
--- a/luci-base/htdocs/luci-static/resources/xhr.js
+++ b/luci-base/htdocs/luci-static/resources/xhr.js
@@ -204,7 +204,6 @@ XHR.poll = function(interval, url, data, callback, post)
};
XHR._q.push(e);
- XHR.run();
return e;
}
@@ -260,3 +259,5 @@ XHR.running = function()
{
return !!(XHR._r && XHR._i);
}
+
+document.addEventListener('DOMContentLoaded', XHR.run);
diff --git a/luci-base/luasrc/dispatcher.lua b/luci-base/luasrc/dispatcher.lua
index 6850d7e3a..6d5a8f4d3 100644
--- a/luci-base/luasrc/dispatcher.lua
+++ b/luci-base/luasrc/dispatcher.lua
@@ -703,15 +703,22 @@ function _create_node(path)
local last = table.remove(path)
local parent = _create_node(path)
- c = {nodes={}, auto=true}
- -- the node is "in request" if the request path matches
- -- at least up to the length of the node path
- if parent.inreq and context.path[#path+1] == last then
- c.inreq = true
+ c = {nodes={}, auto=true, inreq=true}
+
+ local _, n
+ for _, n in ipairs(path) do
+ if context.path[_] ~= n then
+ c.inreq = false
+ break
+ end
end
+
+ c.inreq = c.inreq and (context.path[#path + 1] == last)
+
parent.nodes[last] = c
context.treecache[name] = c
end
+
return c
end
diff --git a/luci-base/luasrc/tools/status.lua b/luci-base/luasrc/tools/status.lua
index 06a9ad415..635995310 100644
--- a/luci-base/luasrc/tools/status.lua
+++ b/luci-base/luasrc/tools/status.lua
@@ -6,9 +6,25 @@ module("luci.tools.status", package.seeall)
local uci = require "luci.model.uci".cursor()
local ipc = require "luci.ip"
+local function duid_to_mac(duid)
+ local b1, b2, b3, b4, b5, b6
+
+ -- DUID-LLT / Ethernet
+ if type(duid) == "string" and #duid == 28 then
+ b1, b2, b3, b4, b5, b6 = duid:match("^00010001(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)%x%x%x%x%x%x%x%x$")
+
+ -- DUID-LL / Ethernet
+ elseif type(duid) == "string" and #duid == 20 then
+ b1, b2, b3, b4, b5, b6 = duid:match("^00030001(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)$")
+ end
+
+ return b1 and ipc.checkmac(table.concat({ b1, b2, b3, b4, b5, b6 }, ":"))
+end
+
local function dhcp_leases_common(family)
local rv = { }
local nfs = require "nixio.fs"
+ local sys = require "luci.sys"
local leasefile = "/tmp/dhcp.leases"
uci:foreach("dhcp", "dnsmasq",
@@ -87,6 +103,22 @@ local function dhcp_leases_common(family)
fd:close()
end
+ if family == 6 then
+ local _, lease
+ local hosts = sys.net.host_hints()
+ for _, lease in ipairs(rv) do
+ local mac = duid_to_mac(lease.duid)
+ local host = mac and hosts[mac]
+ if host then
+ if not lease.name then
+ lease.host_hint = host.name or host.ipv4 or host.ipv6
+ elseif host.name and lease.hostname ~= host.name then
+ lease.host_hint = host.name
+ end
+ end
+ end
+ end
+
return rv
end
@@ -113,6 +145,11 @@ function wifi_networks()
local net
for _, net in ipairs(dev:get_wifinets()) do
+ local a, an = nil, 0
+ for _, a in pairs(net:assoclist() or {}) do
+ an = an + 1
+ end
+
rd.networks[#rd.networks+1] = {
name = net:shortname(),
link = net:adminlink(),
@@ -128,10 +165,10 @@ function wifi_networks()
noise = net:noise(),
bitrate = net:bitrate(),
ifname = net:ifname(),
- assoclist = net:assoclist(),
country = net:country(),
txpower = net:txpower(),
txpoweroff = net:txpower_offset(),
+ num_assoc = an,
disabled = (dev:get("disabled") == "1" or
net:get("disabled") == "1")
}
@@ -165,7 +202,6 @@ function wifi_network(id)
noise = net:noise(),
bitrate = net:bitrate(),
ifname = net:ifname(),
- assoclist = net:assoclist(),
country = net:country(),
txpower = net:txpower(),
txpoweroff = net:txpower_offset(),
@@ -182,6 +218,52 @@ function wifi_network(id)
return { }
end
+function wifi_assoclist()
+ local sys = require "luci.sys"
+ local ntm = require "luci.model.network".init()
+ local hosts = sys.net.host_hints()
+
+ local assoc = {}
+ local _, dev, net, bss
+
+ for _, dev in ipairs(ntm:get_wifidevs()) do
+ local radioname = dev:get_i18n()
+
+ for _, net in ipairs(dev:get_wifinets()) do
+ local netname = net:shortname()
+ local netlink = net:adminlink()
+ local ifname = net:ifname()
+
+ for _, bss in pairs(net:assoclist() or {}) do
+ local host = hosts[_]
+
+ bss.bssid = _
+ bss.ifname = ifname
+ bss.radio = radioname
+ bss.name = netname
+ bss.link = netlink
+
+ bss.host_name = (host) and (host.name or host.ipv4 or host.ipv6)
+ bss.host_hint = (host and host.name and (host.ipv4 or host.ipv6)) and (host.ipv4 or host.ipv6)
+
+ assoc[#assoc+1] = bss
+ end
+ end
+ end
+
+ table.sort(assoc, function(a, b)
+ if a.radio ~= b.radio then
+ return a.radio < b.radio
+ elseif a.ifname ~= b.ifname then
+ return a.ifname < b.ifname
+ else
+ return a.bssid < b.bssid
+ end
+ end)
+
+ return assoc
+end
+
function switch_status(devs)
local dev
local switches = { }
diff --git a/luci-base/luasrc/view/cbi/apply_widget.htm b/luci-base/luasrc/view/cbi/apply_widget.htm
index 702512f49..e3090da65 100644
--- a/luci-base/luasrc/view/cbi/apply_widget.htm
+++ b/luci-base/luasrc/view/cbi/apply_widget.htm
@@ -47,7 +47,7 @@
}
-
+
-
-
-
-
-

-
?
-
-
- <%:Collecting data...%>
-
-
-
+
+
+
+ <%:Collecting data...%>
+
+
<%+cbi/valuefooter%>
diff --git a/luci-mod-admin-full/luasrc/view/admin_network/lease_status.htm b/luci-mod-admin-full/luasrc/view/admin_network/lease_status.htm
index 9005279a4..8fbbdc947 100644
--- a/luci-mod-admin-full/luasrc/view/admin_network/lease_status.htm
+++ b/luci-mod-admin-full/luasrc/view/admin_network/lease_status.htm
@@ -1,27 +1,11 @@
-