feat(panel.html): use client_details.html after clicking on client on sidebar
This commit is contained in:
@@ -13,7 +13,6 @@
|
|||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
const socket = io();
|
const socket = io();
|
||||||
const dataElement = $("#data");
|
|
||||||
|
|
||||||
const showNotify = (message) => {
|
const showNotify = (message) => {
|
||||||
$("#notify").stop().fadeIn();
|
$("#notify").stop().fadeIn();
|
||||||
@@ -23,47 +22,161 @@
|
|||||||
}, 3000);
|
}, 3000);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const loadClientDetails = (clientId) => {
|
||||||
|
fetch(`/client/${clientId}`)
|
||||||
|
.then((response) => response.text())
|
||||||
|
.then((html) => {
|
||||||
|
$("#content").html(html);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error fetching client details:", error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// load client_details for the client specified in the URL hash
|
||||||
|
const hash = window.location.hash;
|
||||||
|
if (hash) {
|
||||||
|
const clientId = hash.substring(1);
|
||||||
|
loadClientDetails(clientId);
|
||||||
|
}
|
||||||
|
|
||||||
$("#notify").hide();
|
$("#notify").hide();
|
||||||
|
|
||||||
socket.on("connect", () => {
|
socket.on("connect", () => {
|
||||||
console.log("Connected to server");
|
console.log("Connected to server");
|
||||||
$("#no-connection-icon").hide();
|
$("#no-connection-message").hide();
|
||||||
showNotify("Connected to server");
|
showNotify("Connected to server");
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("disconnect", () => {
|
socket.on("disconnect", () => {
|
||||||
console.log("Disconnected from server");
|
console.log("Disconnected from server");
|
||||||
$("#no-connection-icon").show();
|
$("#no-connection-message").show();
|
||||||
showNotify("Disconnected from server");
|
showNotify("Disconnected from server");
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("update_data", (data) => {
|
socket.on("update_data", (data) => {
|
||||||
console.log("Received data:", data);
|
|
||||||
document.getElementById("data").innerHTML = JSON.stringify(
|
|
||||||
data,
|
|
||||||
null,
|
|
||||||
2,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update client list
|
|
||||||
const clientList = $("#client-list");
|
const clientList = $("#client-list");
|
||||||
|
const existingItems = {};
|
||||||
|
|
||||||
clientList.empty();
|
// Index current <li> by clientId
|
||||||
Object.entries(data).forEach(([clientId, client]) => {
|
clientList.children("li").each(function () {
|
||||||
const listItem = document.createElement("li");
|
const a = $(this).find("a");
|
||||||
|
if (a.length) {
|
||||||
const iconElement = document.createElement("i");
|
const clientId = a.attr("href").substring(1);
|
||||||
iconElement.classList.add("fi", "fi-sr-play");
|
existingItems[clientId] = $(this);
|
||||||
iconElement.style.color = "var(--ctp-green)";
|
}
|
||||||
listItem.appendChild(iconElement);
|
|
||||||
|
|
||||||
const spanElement = document.createElement("a");
|
|
||||||
spanElement.appendChild(document.createTextNode(clientId));
|
|
||||||
spanElement.href = `#${clientId}`;
|
|
||||||
|
|
||||||
listItem.appendChild(spanElement);
|
|
||||||
clientList.append(listItem);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Track which clientIds are still present
|
||||||
|
const seen = new Set();
|
||||||
|
|
||||||
|
Object.entries(data).forEach(([clientId, client]) => {
|
||||||
|
seen.add(clientId);
|
||||||
|
|
||||||
|
// Build icon
|
||||||
|
const iconElement = document.createElement("i");
|
||||||
|
switch (client.status) {
|
||||||
|
case "online":
|
||||||
|
iconElement.className = "fi fi-sr-play";
|
||||||
|
iconElement.style.color = "var(--ctp-green)";
|
||||||
|
break;
|
||||||
|
case "offline":
|
||||||
|
iconElement.className = "fi fi-sr-stop";
|
||||||
|
iconElement.style.color = "var(--ctp-red)";
|
||||||
|
break;
|
||||||
|
case "pending":
|
||||||
|
iconElement.className = "fi fi-sr-pending";
|
||||||
|
iconElement.style.color = "var(--ctp-yellow)";
|
||||||
|
break;
|
||||||
|
case "stale":
|
||||||
|
iconElement.className = "fi fi-sr-skull";
|
||||||
|
iconElement.style.color = "var(--ctp-orange)";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
iconElement.className = "fi fi-rr-question";
|
||||||
|
iconElement.style.color = "var(--ctp-gray)";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time since last seen
|
||||||
|
const lastSeen = new Date(client.last_seen * 1000);
|
||||||
|
const now = new Date();
|
||||||
|
const timeSinceLastSeen = Math.floor((now - lastSeen) / 1000);
|
||||||
|
const days = Math.floor(timeSinceLastSeen / 86400);
|
||||||
|
const hours = Math.floor((timeSinceLastSeen % 86400) / 3600);
|
||||||
|
const minutes = Math.floor((timeSinceLastSeen % 3600) / 60);
|
||||||
|
const seconds = timeSinceLastSeen % 60;
|
||||||
|
let timeSinceLastSeenText = "";
|
||||||
|
if (days > 0) timeSinceLastSeenText += `${days}d `;
|
||||||
|
if (hours > 0) timeSinceLastSeenText += `${hours}h `;
|
||||||
|
if (minutes > 0) timeSinceLastSeenText += `${minutes}m `;
|
||||||
|
if (seconds > 0) timeSinceLastSeenText += `${seconds}s`;
|
||||||
|
|
||||||
|
timeSinceLastSeenText = timeSinceLastSeenText.trim() || "0s";
|
||||||
|
|
||||||
|
let statusText = `${client.id} (${timeSinceLastSeenText})`;
|
||||||
|
|
||||||
|
// check if <li> exists
|
||||||
|
if (existingItems[clientId]) {
|
||||||
|
// update if needed
|
||||||
|
const li = existingItems[clientId];
|
||||||
|
const a = li.find("a");
|
||||||
|
if (a.text() !== statusText) {
|
||||||
|
a.text(statusText);
|
||||||
|
}
|
||||||
|
|
||||||
|
li.attr(
|
||||||
|
"title",
|
||||||
|
`Status: ${client.status}\nLast Seen: ${lastSeen.toISOString()}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// update icon
|
||||||
|
const icon = li.find("i")[0];
|
||||||
|
if (icon) {
|
||||||
|
icon.className = iconElement.className;
|
||||||
|
icon.style.color = iconElement.style.color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// add new <li>
|
||||||
|
const li = $("<li></li>");
|
||||||
|
li.append(iconElement);
|
||||||
|
const a = $("<a></a>")
|
||||||
|
.text(statusText)
|
||||||
|
.attr("href", `#${clientId}`);
|
||||||
|
|
||||||
|
li.attr(
|
||||||
|
"title",
|
||||||
|
`Status: ${client.status}\nLast Seen: ${lastSeen.toISOString()}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
li.append(a);
|
||||||
|
clientList.append(li);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove <li> for clients no longer present
|
||||||
|
Object.keys(existingItems).forEach((clientId) => {
|
||||||
|
if (!seen.has(clientId)) {
|
||||||
|
existingItems[clientId].remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Re-bind click handlers
|
||||||
|
$("#client-list li > a")
|
||||||
|
.off("click")
|
||||||
|
.on("click", function (e) {
|
||||||
|
const href = $(this).attr("href");
|
||||||
|
if (href.startsWith("#")) {
|
||||||
|
const clientId = href.substring(1);
|
||||||
|
loadClientDetails(clientId);
|
||||||
|
$("#client-list li > a").removeClass("active");
|
||||||
|
$(this).addClass("active");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (window.location.hash) {
|
||||||
|
const clientId = window.location.hash.substring(1);
|
||||||
|
loadClientDetails(clientId);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -72,21 +185,18 @@
|
|||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<header>
|
<header>
|
||||||
<h2><a href="{{ url_for('index.index') }}">judas</a></h2>
|
<h2><a href="{{ url_for('index.index') }}">judas</a></h2>
|
||||||
<p>
|
<p id="no-connection-message">
|
||||||
<span id="no-connection-icon" style="display: none">
|
<i class="fi fi-rr-link-slash"></i>
|
||||||
<i class="fi fi-rr-link-slash"></i>
|
<span> No connection to server </span>
|
||||||
</span>
|
|
||||||
<a class="button" href="{{ url_for('auth.logout') }}">Logout</a>
|
|
||||||
</p>
|
</p>
|
||||||
|
<a class="button" href="{{ url_for('auth.logout') }}">Logout</a>
|
||||||
</header>
|
</header>
|
||||||
<div id="notify"></div>
|
<div id="notify"></div>
|
||||||
<main>
|
<main>
|
||||||
<aside>
|
<aside>
|
||||||
<ul id="client-list"></ul>
|
<ul id="client-list"></ul>
|
||||||
</aside>
|
</aside>
|
||||||
<div id="content">
|
<div id="content"></div>
|
||||||
<pre id="data"></pre>
|
|
||||||
</div>
|
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user