Provide access to neighbor info without dragging in extra resource (#1711)

unless necessary.
This commit is contained in:
Tim Wilkinson 2024-11-20 23:50:17 -08:00 committed by GitHub
parent 91fe800447
commit 223438861a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 168 additions and 42 deletions

75
files/app/main/inject.ut Executable file
View File

@ -0,0 +1,75 @@
{%
/*
* Part of AREDN® -- Used for creating Amateur Radio Emergency Data Networks
* Copyright (C) 2024 Tim Wilkinson
* See Contributors file for additional contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms:
*
* Additional use restrictions exist on the AREDN® trademark and logo.
* See AREDNLicense.txt for more info.
*
* Attributions to the AREDN® Project must be retained in the source code.
* If importing this code into a new or existing project attribution
* to the AREDN® project must be added to the source code.
*
* You must not misrepresent the origin of the material contained within.
*
* Modified versions must be modified to attribute to the original source
* and be marked in reasonable ways as differentiate it from the original
* version
*/
%}
(function(){
let lk = document.createElement("link");
lk.rel = "stylesheet";
{% if (config.resourcehash) { %}
lk.onerror = () => {
lk = document.createElement("link");
lk.rel = "stylesheet";
{% if (config.resourcehash) { %}
lk.href = "/a/css/admin.{{versions.admincss}}.css";
{% } else { %}
lk.href = "/a/css/admin.css";
{% } %}
document.head.appendChild(lk);
};
lk.href = "http://localnode.local.mesh/a/css/admin.{{versions.admincss}}.css";
{% } else { %}
lk.href = "/a/css/admin.css";
{% } %}
document.head.appendChild(lk);
let hx = document.createElement("script");
hx.type = 'text/javascript';
hx.onload = window.injectCallback;
{% if (config.resourcehash) { %}
hx.onerror = () => {
hx = document.createElement('script');
hx.type = "text/javascript";
hx.onload = window.injectCallback;
{% if (config.resourcehash) { %}
hx.src = "/a/js/htmx.min.{{versions.htmx}}.js";
{% } else { %}
hx.src = "/a/js/htmx.min.js";
{% } %}
document.head.appendChild(hx);
}
hx.src = "http://localnode.local.mesh/a/js/htmx.min.{{versions.htmx}}.js";
{% } else { %}
hx.src = "/a/js/htmx.min.js";
{% } %}
document.head.appendChild(hx);
})();

View File

@ -169,11 +169,13 @@ if (tracker) {
<div class="neighbor">
<div class="o">
<div><a href="{{n.hostname ? `http://${n.hostname}.local.mesh` : n.ip}}" target="_blank">{{n.hostname || n.ip}}</a></div>
{% if (auth.isAdmin) { %}
<select name="{{n.mac}}" hx-put={{request.env.REQUEST_URI}} hx-swap="none">
<option value="always" {{n.user_allow ? "selected" : ""}}>never block</option>
<option value="available" {{n.user_allow || n.blocks.user ? "" : "selected"}}>{{n.blocked ? "blocked" : "unblocked"}}</option>
<option value="user" {{n.blocks.user ? "selected" : ""}}>always block</option>
</select>
{% } %}
</div>
<div class="cols">
<div class="i">

47
files/app/partial/activator.ut Executable file
View File

@ -0,0 +1,47 @@
{%
/*
* Part of AREDN® -- Used for creating Amateur Radio Emergency Data Networks
* Copyright (C) 2024 Tim Wilkinson
* See Contributors file for additional contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Additional Terms:
*
* Additional use restrictions exist on the AREDN® trademark and logo.
* See AREDNLicense.txt for more info.
*
* Attributions to the AREDN® Project must be retained in the source code.
* If importing this code into a new or existing project attribution
* to the AREDN® project must be added to the source code.
*
* You must not misrepresent the origin of the material contained within.
*
* Modified versions must be modified to attribute to the original source
* and be marked in reasonable ways as differentiate it from the original
* version
*/
%}
{% if (!auth.isAdmin) { %}
<script>
(function(){
const l = document.getElementById("{{inner}}");
function x(e) {
l.removeEventListener("click", x);
window.injectCallback = () => { htmx.process(l); htmx.trigger(e.target, "click") }
fetch("/a/inject").then(v => v.text()).then(v => eval(v));
}
l.addEventListener("click", x);
})();
</script>
{% } %}

View File

@ -34,7 +34,7 @@
%}
<div class="ctrl-modal-footer">
<hr/>
{% if (inner !== "nocancel") { %}
{% if (inner !== "nocancel" && auth.isAdmin) { %}
<button id="dialog-cancel" hx-delete="{{request.env.REQUEST_URI}}" onclick="setTimeout(_ => document.getElementById('ctrl-modal').close(), 10)">Cancel</button>
{% } %}
<button id="dialog-done" onclick="setTimeout(_ => document.getElementById('ctrl-modal').close(), 10)">Done</button>

View File

@ -98,6 +98,44 @@
}
return "-";
}
const llist = [];
const nlist = [];
const hlist = lqm.getHidden();
const t = lqm.getTrackers();
const trackers = {};
for (mac in t) {
const tmac = t[mac];
if (tmac.ip) {
trackers[tmac.ip] = tmac;
}
}
const links = olsr.getLinks();
for (let i = 0; i < length(links); i++) {
const link = links[i];
const tracker = trackers[link.remoteIP];
if (link.ifName === "br-dtdlink") {
if (tracker && tracker.distance >= 100) {
push(nlist, { name: tracker.hostname || `|${link.remoteIP}`, tracker: tracker, link: link });
}
else {
push(llist, { name: (tracker && tracker.hostname) || `|${link.remoteIP}`, tracker: tracker, link: link });
}
}
else {
push(nlist, { name: (tracker && tracker.hostname) || `|${link.remoteIP}`, tracker: tracker, link: link });
}
delete trackers[link.remoteIP];
}
for (let remoteIP in trackers)
{
const tracker = trackers[remoteIP];
if (tracker.type == "DtD" && tracker.distance < 100) {
push(llist, { name: tracker.hostname || `|${remoteIP}`, tracker: tracker, link: null });
}
else {
push(nlist, { name: tracker.hostname || `|${remoteIP}`, tracker: tracker, link: null });
}
}
%}
<div class="noctrl" hx-target="#ctrl-modal">
<div class="section-title">Local Nodes</div>
@ -113,44 +151,6 @@
</div>
</div>
{%
const llist = [];
const nlist = [];
const hlist = lqm.getHidden();
const t = lqm.getTrackers();
const trackers = {};
for (mac in t) {
const tmac = t[mac];
if (tmac.ip) {
trackers[tmac.ip] = tmac;
}
}
const links = olsr.getLinks();
for (let i = 0; i < length(links); i++) {
const link = links[i];
const tracker = trackers[link.remoteIP];
if (link.ifName === "br-dtdlink") {
if (tracker && tracker.distance >= 100) {
push(nlist, { name: tracker.hostname || `|${link.remoteIP}`, tracker: tracker, link: link });
}
else {
push(llist, { name: (tracker && tracker.hostname) || `|${link.remoteIP}`, tracker: tracker, link: link });
}
}
else {
push(nlist, { name: (tracker && tracker.hostname) || `|${link.remoteIP}`, tracker: tracker, link: link });
}
delete trackers[link.remoteIP];
}
for (let remoteIP in trackers)
{
const tracker = trackers[remoteIP];
if (tracker.type == "DtD" && tracker.distance < 100) {
push(llist, { name: tracker.hostname || `|${remoteIP}`, tracker: tracker, link: null });
}
else {
push(nlist, { name: tracker.hostname || `|${remoteIP}`, tracker: tracker, link: null });
}
}
if (length(llist) > 0) {
sort(llist, (a, b) => a.name == b.name ? 0 : a.name < b.name ? -1 : 1);
for (let i = 0; i < length(llist); i++) {
@ -159,7 +159,7 @@
const link = entry.link;
const status = calcColor(tracker);
if (tracker) {
print(`<div class="ctrl cols status ${status}" hx-get="status/e/neighbor-device?m=${tracker.mac}" title="Link status: ${status}">`);
print(`<div class="ctrl cols status ${status}" hx-get="neighbor-device?m=${tracker.mac}" title="Link status: ${status}">`);
}
else {
print(`<div class="ctrl cols status unknown" title="Link status: unknown">`);
@ -201,7 +201,7 @@
const link = entry.link;
const status = calcColor(tracker);
if (tracker) {
print(`<div class="ctrl cols status ${status}" hx-get="status/e/neighbor-device?m=${tracker.mac}" title="Link status: ${status}">`);
print(`<div class="ctrl cols status ${status}" hx-get="neighbor-device?m=${tracker.mac}" title="Link status: ${status}">`);
}
else {
print(`<div class="ctrl cols status unknown" title="Link status: unknown">`);

View File

@ -62,6 +62,7 @@
{{_R("local-and-neighbor-devices")}}
</div>
</div>
{{_R("activator", "local-and-neighbor-devices")}}
</div>
<div id="c3">
<div id="radio-and-antenna">

View File

@ -406,10 +406,11 @@ body.authenticated .ctrl:hover
{
flex: 0.75;
}
body.authenticated #local-and-neighbor-devices .status.ctrl:hover
#local-and-neighbor-devices .status.ctrl:hover
{
padding: 7.5px 10px;
margin: -10px -10px;
background-color: var(--ctrl-bg-color-hover);
}
#local-and-neighbor-devices .excellent
{