luci-mod-status: correctness fixes
authorPaul Donald <redacted>
Tue, 26 May 2026 14:26:30 +0000 (17:26 +0300)
committerPaul Donald <redacted>
Wed, 27 May 2026 12:49:46 +0000 (15:49 +0300)
Signed-off-by: Paul Donald <redacted>
modules/luci-mod-status/htdocs/luci-static/resources/view/status/channel_analysis.js
modules/luci-mod-status/htdocs/luci-static/resources/view/status/dmesg.js
modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/30_network.js
modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/40_dhcp.js
modules/luci-mod-status/htdocs/luci-static/resources/view/status/include/60_wifi.js
modules/luci-mod-status/htdocs/luci-static/resources/view/status/routes.js
modules/luci-mod-status/htdocs/luci-static/resources/view/status/routesj.js

index c4a85e0be78a0c211b3bd83357c426f12878c15a..30dc22fc9c56c86ec6226fc01d3fff2c86b08225 100644 (file)
@@ -237,6 +237,7 @@ return view.extend({
 
                                        local_wifi.signal = -10;
                                        local_wifi.ssid = 'Local Interface';
+                                       q = Math.min((local_wifi.signal + 110) / 70 * 100, 100);
 
                                        this.add_wifi_to_graph(chan_analysis, local_wifi, scanCache, center_channels, chan_width);
                                        rows.push([
@@ -258,8 +259,8 @@ return view.extend({
                                        results.push(scanCache[k].data);
 
                        results.sort(function(a, b) {
-                               if (a.channel - b.channel)
-                                       return 1;
+                               if (a.channel !== b.channel)
+                                       return a.channel - b.channel;
 
                                if (a.ssid < b.ssid)
                                        return -1;
@@ -270,6 +271,8 @@ return view.extend({
                                        return -1;
                                else if (a.bssid > b.bssid)
                                        return 1;
+
+                               return 0;
                        });
 
                        for (let res of results) {
index d1b72d47a415a007d883cf96cd8e6fbe8d309b82..315ddacd357812715cf40dc75ae7ed8c9a415d40 100644 (file)
@@ -39,6 +39,7 @@ return view.extend({
                return fs.exec_direct('/bin/dmesg', [ '-r' ]).then(logdata => {
                        let loglines = [];
                        let lastSeverity = null;
+                       let lastTime = null;
 
                        logdata.trim().split(/\n/).forEach(line => {
                                const priorityMatch = line.match(/^<(\w+)>/);
@@ -49,6 +50,8 @@ return view.extend({
                                const cleanLine = line.replace(/^<\w+>/, '');
                                const timeMatch = cleanLine.match(/^\[\s*(\d+(?:\.\d+)?)\]/);
                                const time = timeMatch ? parseFloat(timeMatch[1]) : null;
+                               if (time != null)
+                                       lastTime = time;
 
                                if (!isCont) {
                                        lastSeverity = parseInt(tag, 10); // update severity
@@ -57,7 +60,7 @@ return view.extend({
                                loglines.push({
                                        severity: isCont ? lastSeverity : parseInt(tag, 10),
                                        isCont,
-                                       time,
+                                       time: time != null ? time : lastTime,
                                        text: cleanLine
                                });
                        });
@@ -84,12 +87,10 @@ return view.extend({
 
                        // Filter by severity
                        loglines = loglines.filter(entry => {
-                               if (!entry.isCont) {
-                                       if (!this.invertMinSeverity)
-                                               return (entry.severity >= this.minSeverity);
-                                       else
-                                               return (entry.severity < this.minSeverity);
-                               }
+                               if (this.invertMinSeverity)
+                                       return entry.severity < this.minSeverity;
+                               else
+                                       return entry.severity >= this.minSeverity;
                        });
 
                        // Filter by text
index 723b73d43d413a01fc031f3f236bd49aec2fce58..4d002de8d8767e321dc4f89f921dafc73425ced4 100644 (file)
@@ -69,7 +69,7 @@ function renderbox(ifc, ipv6, dhcpv6_stats) {
                        E('div', {}, renderBadge(
                                L.resource('icons/%s.svg').format(dev ? dev.getType() : 'ethernet_disabled'), null,
                                _('Device'), dev ? dev.getI18n() : '-',
-                               _('MAC address'), dev.getMAC())
+                               _('MAC address'), dev ? dev.getMAC() : '')
                        )
                ])
        ]);
index 4d1161d209726d54b0b218eab31ad7cfebbb6ad5..6bcab8485efe9de8064780029ad9f8fcc40a935e 100644 (file)
@@ -88,6 +88,9 @@ return baseclass.extend({
                        return E('em', _('No active leases found'));
                const machints = host_hints.getMACHints(false);
                const isReadonlyView = !L.hasViewPermission();
+               this.isMACStatic = Object.create(null);
+               this.isDUIDStatic = Object.create(null);
+               this.isDUIDIAIDStatic = Object.create(null);
 
                for (const host of uci.sections('dhcp', 'host')) {
 
index 96a9eece87d908607d537dc975665ce65b133589..8406a1a59d7d0b17ac4e8bd3297b11c837cc0905 100644 (file)
@@ -205,7 +205,7 @@ return baseclass.extend({
 
                        for (let i = 0; i < radios_networks_hints.length; i++) {
                                tasks.push(L.resolveDefault(radios_networks_hints[i].getAssocList(), []).then(L.bind((net, list) => {
-                                       net.assoclist = list.sort((a, b) => { return a.mac > b.mac });
+                                       net.assoclist = list.sort((a, b) => a.mac.localeCompare(b.mac));
                                }, this, radios_networks_hints[i])));
 
                                if (hasWPS && uci.get('wireless', radios_networks_hints[i].sid, 'wps_pushbutton') == '1') {
@@ -233,7 +233,7 @@ return baseclass.extend({
 
                const table = E('div', { 'class': 'network-status-table' });
 
-               for (let i = 0; i < radios.sort((a, b) => { a.getName() > b.getName() }).length; i++)
+               for (let i = 0; i < radios.sort((a, b) => a.getName().localeCompare(b.getName())).length; i++)
                        table.appendChild(this.renderbox(radios[i],
                                networks.filter(net => { return net.getWifiDeviceName() == radios[i].getName() })));
 
index e1e4d532fc0ffe3513cec134c1f9fd68e7f38637..5315d9e2b2559f8aaafb14d4d7f518e5875485ac 100644 (file)
@@ -66,6 +66,7 @@ return view.extend({
                                        const cmp_addr = address || target;
                                        if (!cmp_addr) continue;
 
+                                       if (typeof cmp_mask !== 'number') continue;
                                        if (applyMask(cmp_addr, cmp_mask, v6) !== applyMask(addr, cmp_mask, v6) || mask < cmp_mask)
                                                continue;
 
@@ -85,7 +86,7 @@ return view.extend({
                const res = [];
 
                for (const line of nbs.trim().split(/\n/)) {
-                       const [, addr = null, f = [], state = null] = line.match(/^([0-9a-f:.]+) (.+) (\S+) *$/);
+                       const [, addr = null, f = [], state = null] = (line.match(/^([0-9a-f:.]+) (.+) (\S+) *$/) || []);
                        const flags = f?.trim?.().split?.(/\s+/);
                        let vendor;
 
@@ -120,7 +121,7 @@ return view.extend({
                const res = [];
 
                for (const line of routes.trim().split(/\n/)) {
-                       const [, type = 'unicast', d, f = [] ] = line.match(/^(?:([a-z_]+|\d+) )?(default|[0-9a-f:./]+) (.+)$/);
+                       const [, type = 'unicast', d, f = [] ] = (line.match(/^(?:([a-z_]+|\d+) )?(default|[0-9a-f:./]+) (.+)$/) || []);
                        const dest = d == 'default' ? (v6 ? '::/0' : '0.0.0.0/0') : d;
                        const flags = f?.trim?.().split?.(/\s+/);
 
index 5ca5b3a51abfaf0edcac4aa30839eed42f0033f0..751eb2e186e00d053cc0494f57c665e090c5bf5f 100644 (file)
@@ -67,6 +67,7 @@ return view.extend({
                                        const cmp_addr = address || target;
                                        if (!cmp_addr) continue;
 
+                                       if (typeof cmp_mask !== 'number') continue;
                                        if (applyMask(cmp_addr, cmp_mask, v6) !== applyMask(addr, cmp_mask, v6) || mask < cmp_mask)
                                                continue;
 
@@ -94,10 +95,10 @@ return view.extend({
 
                for (const n of this.parseJSON(nbs)) {
                        let vendor;
-                       if (n.dst.match(/^fe[89a-f][0-9a-f]:/))
+                       if (n.dst?.match(/^fe[89a-f][0-9a-f]:/))
                                continue;
 
-                       if (n.state.find(f => {return f == 'FAILED'}))
+                       if ((n.state || []).some(f => f === 'FAILED'))
                                continue;
 
                        for (let mac in macs) {
git clone https://git.99rst.org/PROJECT