Added wake indicator. moved to new wake API endpoint. commented out some things. we dont need none of ts.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
export const qs = new URLSearchParams(location.search);
|
||||
|
||||
// not real cuh
|
||||
export const $ = (id) => document.getElementById(id);
|
||||
export const elName = $("name");
|
||||
export const elCheck = $("check");
|
||||
|
||||
+11
-6
@@ -8,7 +8,12 @@ export function renderLeases(leases) {
|
||||
}
|
||||
const tbl = document.createElement("table");
|
||||
tbl.className = "table";
|
||||
tbl.innerHTML = `<tr><th></th><th>IP</th><th>MAC</th><th>Name</th><th>Expires</th></tr>`;
|
||||
|
||||
(
|
||||
tbl.tHead || tbl.createTHead()
|
||||
).innerHTML = `<tr><th></th><th>IP</th><th>MAC</th><th>Name</th><th>Expires</th></tr>`;
|
||||
|
||||
const tbd = tbl.tBodies.item(0) || tbl.createTBody();
|
||||
const nowSec = Math.floor(Date.now() / 1000);
|
||||
for (const l of leases) {
|
||||
const tr = document.createElement("tr");
|
||||
@@ -34,17 +39,17 @@ export function renderLeases(leases) {
|
||||
const name = l.name || "";
|
||||
tr.innerHTML = `
|
||||
<td><span class="${dotClass}" title="${title}"></span></td>
|
||||
${[ip, mac, name]
|
||||
${Object.entries({ ip, mac, name })
|
||||
.map(
|
||||
(f) =>
|
||||
([name, value]) =>
|
||||
`<td>${
|
||||
f &&
|
||||
`<a href="#" class="pick" data-value="${f}" title="filter by ip">${f}</a>`
|
||||
value &&
|
||||
`<a href="#" class="pick" data-value="${value}" title="filter by ${name}">${value}</a>`
|
||||
}</td>`
|
||||
)
|
||||
.join("\n")}
|
||||
<td><span class="tiny">${whenText}</span></td>`;
|
||||
tbl.appendChild(tr);
|
||||
tbd.appendChild(tr);
|
||||
}
|
||||
elLeases.innerHTML = "";
|
||||
elLeases.appendChild(tbl);
|
||||
|
||||
+37
-17
@@ -1,5 +1,6 @@
|
||||
import { elHtml, elLog, setPill, qs } from "./dom.js";
|
||||
import { elHtml, elLog, setPill, qs, pill } from "./dom.js";
|
||||
import { rankState } from "./utils.js";
|
||||
import { merge_wake_data, translate_wake_message } from "./wake.js";
|
||||
|
||||
const status_map = {
|
||||
ip: "ip",
|
||||
@@ -11,7 +12,7 @@ const status_map = {
|
||||
const filter_array = ["ip", "dev", "nud", "mac"];
|
||||
|
||||
function buildStatusUrl(name) {
|
||||
const hasExtraFilters = f_array.some((k) => qs.getAll(k).length);
|
||||
const hasExtraFilters = filter_array.some((k) => qs.getAll(k).length);
|
||||
if (name && !hasExtraFilters) {
|
||||
return new URL(`/api/smart/${encodeURIComponent(name)}`, location.origin);
|
||||
}
|
||||
@@ -27,21 +28,33 @@ function buildStatusUrl(name) {
|
||||
export function renderStatus(data) {
|
||||
const tbl = document.createElement("table");
|
||||
tbl.className = "table";
|
||||
tbl.innerHTML = `<tr><th>IP</th><th>MAC</th><th>State</th><th>IF</th></tr>`;
|
||||
tbl.innerHTML = `<thead><tr>${
|
||||
data.has_wake ? "<th>Wake status</th>" : ""
|
||||
}<th>IP</th><th>MAC</th><th>State</th><th>IF</th></tr></thead>`;
|
||||
|
||||
for (const row of data.table || []) {
|
||||
// sum hax
|
||||
const tbd = tbl.tBodies.item(0) || tbl.createTBody();
|
||||
for (const row of data.table) {
|
||||
if (data.has_wake && !row.wake_status)
|
||||
throw TypeError("specified has wake but no wake stats");
|
||||
const tr = document.createElement("tr");
|
||||
tr.innerHTML = Object.entries(status_map)
|
||||
.map(
|
||||
(field, description) =>
|
||||
`<td>${
|
||||
row[field]
|
||||
? `<a href="#" class="pick" data-value="${row[field]}" title="filter by ${description}">${row[field]}</a>`
|
||||
: ""
|
||||
}</td>`
|
||||
)
|
||||
.join();
|
||||
tbl.appendChild(tr);
|
||||
tr.innerHTML = `${
|
||||
row.wake_status
|
||||
? `<td><span class="dot ${
|
||||
row.wake_status == "succeed" ? "ok" : "bad"
|
||||
}" title="${translate_wake_message(row.wake_status)}"></span></td>`
|
||||
: ""
|
||||
}${Object.entries(status_map)
|
||||
.map(([field, description]) => {
|
||||
const value = row[field];
|
||||
return `<td>${
|
||||
value
|
||||
? `<a href="#" class="pick" data-value="${value}" title="filter by ${description}">${value}</a>`
|
||||
: ""
|
||||
}</td>`;
|
||||
})
|
||||
.join("")}`;
|
||||
tbd.appendChild(tr);
|
||||
}
|
||||
|
||||
elHtml.innerHTML = "";
|
||||
@@ -69,12 +82,13 @@ export function renderStatus(data) {
|
||||
if (r >= 5) setPill("ok", "online");
|
||||
else if (r >= 2) setPill("warn", "maybe");
|
||||
else setPill("bad", "offline");
|
||||
if (data.filters.nud?.length > 0) pill.textContent += " (filtered)";
|
||||
} else {
|
||||
setPill("warn", "unknown");
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchStatus(name) {
|
||||
export async function fetchStatus(name, render = true, data_wake) {
|
||||
setPill("warn", "checking…");
|
||||
const u = buildStatusUrl(name);
|
||||
elLog.textContent = "GET " + u.pathname + u.search;
|
||||
@@ -93,7 +107,13 @@ export async function fetchStatus(name) {
|
||||
return;
|
||||
}
|
||||
const data = await r.json();
|
||||
renderStatus(data);
|
||||
|
||||
if (data_wake) {
|
||||
data.table = merge_wake_data(data.table, data_wake);
|
||||
data.has_wake = true;
|
||||
}
|
||||
if (render) renderStatus(data);
|
||||
return data;
|
||||
} catch (e) {
|
||||
elLog.textContent = "status error: " + e;
|
||||
setPill("bad", "error");
|
||||
|
||||
+96
-7
@@ -1,18 +1,107 @@
|
||||
import { elLog, setPill } from "./dom.js";
|
||||
import { fetchStatus } from "./status.js";
|
||||
import { elHtml, elLog, setPill } from "./dom.js";
|
||||
import { fetchStatus, renderStatus } from "./status.js";
|
||||
|
||||
export async function sendWake(name) {
|
||||
const data = await fetchStatus(name, false);
|
||||
if (!data) return; // can not proceed; theres nothing.
|
||||
const wake_targets = data.table.map(({ ip, mac }) => {
|
||||
return { ip, mac };
|
||||
});
|
||||
setPill("warn", "waking…");
|
||||
elLog.textContent = "POST /wake?name=" + name;
|
||||
elLog.textContent = "POST /api/wake";
|
||||
try {
|
||||
const r = await fetch(`/wake?name=${encodeURIComponent(name)}`, {
|
||||
const r = await fetch(`/api/wake`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(wake_targets),
|
||||
});
|
||||
const t = await r.text();
|
||||
elLog.textContent = t || "ok";
|
||||
setTimeout(() => fetchStatus(name), 800);
|
||||
if (!r.ok) {
|
||||
let msg = String(r.status);
|
||||
try {
|
||||
const err = await r.clone().json();
|
||||
msg = err.error || JSON.stringify(err);
|
||||
} catch {
|
||||
msg = await r.text();
|
||||
}
|
||||
elLog.textContent = `wake error: ${msg}`;
|
||||
setPill("bad", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
const j = await r.json();
|
||||
|
||||
if (!j.success) {
|
||||
elLog.textContent = `wake error: ${j.error}`;
|
||||
setPill("bad", "error");
|
||||
return;
|
||||
}
|
||||
|
||||
const result = j.result;
|
||||
data.table = merge_wake_data(data.table, result);
|
||||
data.has_wake = true;
|
||||
|
||||
renderStatus(data);
|
||||
|
||||
setTimeout(() => fetchStatus(name, undefined, result), 2000); // long ass timeout
|
||||
} catch (e) {
|
||||
elLog.textContent = "wake error: " + e;
|
||||
setPill("bad", "error");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Array} table
|
||||
* @param {Array} wake
|
||||
*/
|
||||
export function merge_wake_data(table, wake) {
|
||||
if (!wake) return table;
|
||||
if (wake.length != table.length)
|
||||
throw TypeError(
|
||||
"wake status table and status table not of the same length"
|
||||
);
|
||||
const return_array = [];
|
||||
let linear_failed = false;
|
||||
for (const [index, entry] of table.entries()) {
|
||||
if (wake[index].ip != entry.ip || wake[index].mac != entry.mac) {
|
||||
linear_failed = true;
|
||||
break;
|
||||
} // use alternative method
|
||||
|
||||
return_array.push({ wake_status: wake[index].status, ...entry });
|
||||
}
|
||||
|
||||
// never happening AHH
|
||||
if (linear_failed) {
|
||||
return_array = [];
|
||||
const wake_map = new Map();
|
||||
wake.forEach(({ ip, mac, status }) => {
|
||||
wake_map.set(JSON.stringify({ ip, mac }), status);
|
||||
});
|
||||
return_array = table.map((entry) => {
|
||||
const { ip, mac } = entry;
|
||||
return {
|
||||
wake_status: wake_map.get(JSON.stringify({ ip, mac })),
|
||||
...entry,
|
||||
};
|
||||
});
|
||||
}
|
||||
//
|
||||
return return_array;
|
||||
}
|
||||
|
||||
|
||||
export function translate_wake_message(wake_msg) {
|
||||
switch (wake_msg) {
|
||||
case "incomplete":
|
||||
return "Incomplete address (both ip and MAC required)"
|
||||
case "succeed":
|
||||
return "Wake request sent successfully"
|
||||
case "nonexistent_address":
|
||||
return "Errored pinging this address (nonexistent address)"
|
||||
case "wrong_size":
|
||||
return "Wake request malformed"
|
||||
default:
|
||||
return "Unknown"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user