fixed remove from dashboard + added nickname
This commit is contained in:
@@ -65,6 +65,19 @@ function detectClientPlatform(clientId) {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
function getClientCard(clientId) {
|
||||
if (!clientId) return null;
|
||||
const selectorId =
|
||||
typeof CSS !== "undefined" && typeof CSS.escape === "function"
|
||||
? CSS.escape(clientId)
|
||||
: clientId;
|
||||
return document.querySelector(`article[data-id="${selectorId}"]`);
|
||||
}
|
||||
|
||||
function isClientOnline(clientId) {
|
||||
return getClientCard(clientId)?.dataset.online === "true";
|
||||
}
|
||||
|
||||
function applyMenuSupportRules(clientId) {
|
||||
const platform = detectClientPlatform(clientId);
|
||||
const isWindows = platform === "windows";
|
||||
@@ -240,7 +253,7 @@ function initializeRenderer() {
|
||||
pageLabel,
|
||||
openMenu: (id, x, y) => {
|
||||
applyMenuSupportRules(id);
|
||||
openMenu(id, x, y, setContext);
|
||||
openMenu(id, x, y, setContext, { isOnline: isClientOnline(id) });
|
||||
loadPluginsForClient(id);
|
||||
},
|
||||
openModal,
|
||||
@@ -510,6 +523,27 @@ window.removeClientFromDashboard = async (clientId) => {
|
||||
}
|
||||
};
|
||||
|
||||
window.setClientNickname = async (clientId, nickname) => {
|
||||
if (!clientId) return false;
|
||||
try {
|
||||
const res = await fetch(`/api/clients/${clientId}/nickname`, {
|
||||
method: "PATCH",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ nickname: nickname || "" }),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const data = await res.json().catch(() => ({}));
|
||||
alert(data.error || "Failed to update client nickname");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
alert("Failed to update client nickname");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
window.banClient = async (clientId) => {
|
||||
if (!clientId) return;
|
||||
if (!confirm(`Ban IP for ${clientId} and block future connections?`)) return;
|
||||
@@ -686,6 +720,31 @@ menu.addEventListener("click", async (e) => {
|
||||
}
|
||||
closeMenu(clearContext);
|
||||
return;
|
||||
} else if (action === "set-nickname") {
|
||||
const card = getClientCard(contextCard);
|
||||
const currentNickname = (card?.dataset.nickname || "").trim();
|
||||
const input = prompt(
|
||||
`Set nickname for ${contextCard}\n\nLeave blank to clear nickname.`,
|
||||
currentNickname,
|
||||
);
|
||||
if (input === null) {
|
||||
closeMenu(clearContext);
|
||||
return;
|
||||
}
|
||||
|
||||
const trimmed = input.trim();
|
||||
const updated = await window.setClientNickname(contextCard, trimmed || null);
|
||||
if (updated) {
|
||||
setTimeout(() => loadWithOptions({ force: true }), 200);
|
||||
}
|
||||
closeMenu(clearContext);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isClientOnline(contextCard)) {
|
||||
alert("Client is offline. This command can only be used while the client is online.");
|
||||
closeMenu(clearContext);
|
||||
return;
|
||||
}
|
||||
|
||||
const ok = await sendCommand(contextCard, action);
|
||||
|
||||
@@ -132,8 +132,6 @@ export function createRenderer({
|
||||
card.addEventListener("contextmenu", (e) => {
|
||||
e.preventDefault();
|
||||
if (isViewer) return;
|
||||
const isOnline = card.dataset.online === "true";
|
||||
if (!isOnline) return;
|
||||
const clientId = card.dataset.id;
|
||||
if (!clientId) return;
|
||||
const { clientX, clientY } = e;
|
||||
@@ -167,12 +165,15 @@ export function createRenderer({
|
||||
|
||||
card.dataset.online = String(!!client.online);
|
||||
card.dataset.os = String(client.os || "").toLowerCase();
|
||||
card.dataset.nickname = String(client.nickname || "");
|
||||
const os = osBadge(client.os || "unknown");
|
||||
const arch = archBadge(client.arch || "");
|
||||
const ver = versionBadge(client.version || "");
|
||||
const mons = monitorsBadge(client.monitors);
|
||||
const deviceId = shortId(client.id);
|
||||
const hwid = shortId(client.hwid || "");
|
||||
const nickname = String(client.nickname || "").trim();
|
||||
const displayName = nickname || client.host || deviceId;
|
||||
card.className = `card rounded-xl border border-slate-800 bg-slate-900/70 p-4 shadow-lg ${client.online ? "" : "card-offline"} tone-${os.tone}`;
|
||||
const cardThumb = client.thumbnail
|
||||
? (() => {
|
||||
@@ -202,7 +203,8 @@ export function createRenderer({
|
||||
<div class="flex-1 min-w-[240px] flex flex-col gap-2">
|
||||
<div class="flex items-center gap-3 flex-wrap text-lg font-semibold">
|
||||
<span class="text-2xl">${countryToFlag(client.country)}</span>
|
||||
<span>${escapeHtml(client.host || deviceId)}</span>
|
||||
<span>${escapeHtml(displayName)}</span>
|
||||
${nickname && client.host ? `<span class="pill pill-ghost text-xs"><i class="fa-solid fa-laptop"></i> ${escapeHtml(client.host)}</span>` : ""}
|
||||
<span class="text-slate-300 text-lg font-semibold flex items-center gap-1"><i class="fa-solid fa-user"></i> ${escapeHtml(client.user || "unknown")}</span>
|
||||
<span class="pill ${client.online ? "pill-online" : "pill-offline"}">
|
||||
<i class="fa-solid fa-circle"></i>
|
||||
@@ -223,7 +225,7 @@ export function createRenderer({
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<span class="text-emerald-300 font-mono text-sm inline-flex items-center gap-2"><i class="fa-solid fa-satellite-dish"></i> ${formatPing(client.pingMs)}</span>
|
||||
${isViewer ? "" : `<button ${client.online ? "" : "disabled"} class="command-btn inline-flex items-center gap-2 px-3 py-2 rounded-lg border border-slate-800 bg-slate-800/70 hover:bg-slate-700 disabled:opacity-50" data-id="${escapeHtml(client.id)}"><i class="fa-solid fa-bars"></i> Commands</button>`}
|
||||
${isViewer ? "" : `<button class="command-btn inline-flex items-center gap-2 px-3 py-2 rounded-lg border border-slate-800 bg-slate-800/70 hover:bg-slate-700" data-id="${escapeHtml(client.id)}"><i class="fa-solid fa-bars"></i> Commands</button>`}
|
||||
${isViewer ? "" : `<button class="ban-btn inline-flex items-center gap-2 px-3 py-2 rounded-lg border border-red-800 bg-red-900/60 hover:bg-red-800 text-red-100" data-id="${escapeHtml(client.id)}"><i class="fa-solid fa-ban"></i> Ban</button>`}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -19,7 +19,8 @@ menu.innerHTML = `
|
||||
<button class="w-full text-left px-3 py-2.5 mb-1 rounded-lg border border-slate-800 bg-slate-800/60 hover:bg-slate-700 flex items-center gap-2" data-action="reconnect"><i class="fa-solid fa-rotate"></i> Reconnect</button>
|
||||
<button class="w-full text-left px-3 py-2.5 mb-1 rounded-lg border border-red-800 bg-red-900/40 hover:bg-red-800/60 text-red-100 flex items-center gap-2" data-action="disconnect"><i class="fa-solid fa-plug-circle-xmark"></i> Disconnect</button>
|
||||
<button class="w-full text-left px-3 py-2.5 rounded-lg border border-red-900 bg-red-950/60 hover:bg-red-900/80 text-red-200 flex items-center gap-2" data-action="uninstall"><i class="fa-solid fa-trash"></i> Uninstall</button>
|
||||
<button class="w-full mt-1 text-left px-3 py-2.5 rounded-lg border border-rose-900 bg-rose-950/70 hover:bg-rose-900/90 text-rose-200 flex items-center gap-2" data-action="remove-dashboard"><i class="fa-solid fa-user-xmark"></i> Remove From Dashboard</button>
|
||||
<button class="w-full mt-1 text-left px-3 py-2.5 rounded-lg border border-slate-700 bg-slate-800/60 hover:bg-slate-700 text-slate-100 flex items-center gap-2" data-action="set-nickname"><i class="fa-solid fa-signature"></i> Set Nickname</button>
|
||||
<button class="hidden w-full mt-1 text-left px-3 py-2.5 rounded-lg border border-rose-900 bg-rose-950/70 hover:bg-rose-900/90 text-rose-200 flex items-center gap-2" data-action="remove-dashboard"><i class="fa-solid fa-user-xmark"></i> Remove From Dashboard</button>
|
||||
<div id="plugin-section" class="hidden">
|
||||
<div class="border-t border-slate-700 my-2"></div>
|
||||
<div class="text-[11px] uppercase tracking-wider text-slate-400 px-1 mb-1">Plugins</div>
|
||||
@@ -35,8 +36,15 @@ modal.innerHTML = `<div class="max-w-5xl max-h-[90vh] p-4"><img class="max-h-[85
|
||||
document.body.appendChild(modal);
|
||||
const modalImg = modal.querySelector("#modal-img");
|
||||
|
||||
export function openMenu(clientId, x, y, setContext) {
|
||||
export function openMenu(clientId, x, y, setContext, options = {}) {
|
||||
if (setContext) setContext(clientId);
|
||||
|
||||
const removeBtn = menu.querySelector('[data-action="remove-dashboard"]');
|
||||
if (removeBtn) {
|
||||
const isOnline = options.isOnline === true;
|
||||
removeBtn.classList.toggle("hidden", isOnline);
|
||||
}
|
||||
|
||||
menu.classList.remove("hidden");
|
||||
|
||||
const menuWidth = 192;
|
||||
|
||||
Reference in New Issue
Block a user