Update samy.js
This commit is contained in:
142
samy.js
142
samy.js
@@ -82,10 +82,13 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Default tab from PS (onboard/offboard/tweaks/SVSApps)
|
// Default tab from PS (onboard/offboard/devices)
|
||||||
const defaultTabId = `${defaultPage}Tab`;
|
const defaultTabId = `${defaultPage}Tab`;
|
||||||
const defaultBtn = document.querySelector(`.tab-button[data-tab='${defaultTabId}']`);
|
const defaultBtn = document.querySelector(
|
||||||
|
`.tab-button[data-tab='${defaultTabId}']`
|
||||||
|
);
|
||||||
const defaultTab = document.getElementById(defaultTabId);
|
const defaultTab = document.getElementById(defaultTabId);
|
||||||
|
|
||||||
if (defaultBtn) defaultBtn.classList.add("active");
|
if (defaultBtn) defaultBtn.classList.add("active");
|
||||||
if (defaultTab) defaultTab.classList.add("active");
|
if (defaultTab) defaultTab.classList.add("active");
|
||||||
});
|
});
|
||||||
@@ -105,6 +108,7 @@ function toggleColumn(col) {
|
|||||||
cb.checked = master.checked;
|
cb.checked = master.checked;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// fire change handlers
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
children.forEach((cb) => {
|
children.forEach((cb) => {
|
||||||
cb.dispatchEvent(new Event("change"));
|
cb.dispatchEvent(new Event("change"));
|
||||||
@@ -117,19 +121,21 @@ function updateSelectAll(col) {
|
|||||||
`selectAll${col[0].toUpperCase() + col.slice(1)}Checkbox`
|
`selectAll${col[0].toUpperCase() + col.slice(1)}Checkbox`
|
||||||
);
|
);
|
||||||
const children = document.querySelectorAll(
|
const children = document.querySelectorAll(
|
||||||
`#onboardTab input[type=checkbox][data-column=${col}]`
|
`#onboardTab input[type=checkbox][data-column="${col}"]`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!master) return;
|
||||||
master.checked = Array.from(children).every((cb) => cb.checked);
|
master.checked = Array.from(children).every((cb) => cb.checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
["left", "right"].forEach((col) => {
|
["left", "right"].forEach((col) => {
|
||||||
document
|
document
|
||||||
.querySelectorAll(`#onboardTab input[type=checkbox][data-column=${col}]`)
|
.querySelectorAll(`#onboardTab input[type=checkbox][data-column="${col}"]`)
|
||||||
.forEach((cb) =>
|
.forEach((cb) =>
|
||||||
cb.addEventListener("change", () => updateSelectAll(col))
|
cb.addEventListener("change", () => updateSelectAll(col))
|
||||||
);
|
);
|
||||||
|
updateSelectAll(col);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -182,6 +188,7 @@ function toggleDattoRMMOptions() {
|
|||||||
const master = document.getElementById("installDattoRMM");
|
const master = document.getElementById("installDattoRMM");
|
||||||
const container = document.getElementById("installDattoRMMOptionsContainer");
|
const container = document.getElementById("installDattoRMMOptionsContainer");
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
const checked = master?.checked;
|
const checked = master?.checked;
|
||||||
container.style.display = checked ? "block" : "none";
|
container.style.display = checked ? "block" : "none";
|
||||||
container
|
container
|
||||||
@@ -200,9 +207,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
|
|
||||||
if (passwordField && goButton) {
|
if (passwordField && goButton) {
|
||||||
passwordField.addEventListener("keydown", (e) => {
|
passwordField.addEventListener("keydown", (e) => {
|
||||||
if (e.key === "Enter") {
|
if (e.key === "Enter") goButton.click();
|
||||||
goButton.click();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,9 +216,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
|
|
||||||
if (siteDropdown && runButton) {
|
if (siteDropdown && runButton) {
|
||||||
siteDropdown.addEventListener("keydown", (e) => {
|
siteDropdown.addEventListener("keydown", (e) => {
|
||||||
if (e.key === "Enter" && siteDropdown.value) {
|
if (e.key === "Enter" && siteDropdown.value) runButton.click();
|
||||||
runButton.click();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -223,11 +226,11 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
// =======================================================================
|
// =======================================================================
|
||||||
async function fetchSites() {
|
async function fetchSites() {
|
||||||
const pwdInput = document.getElementById("Password");
|
const pwdInput = document.getElementById("Password");
|
||||||
const pwd = (pwdInput?.value ?? "").trim(); // allow blank, normalize whitespace
|
const pwd = (pwdInput?.value ?? "").trim(); // allow blank
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const dropdown = document.getElementById("dattoDropdown");
|
const dropdown = document.getElementById("dattoDropdown");
|
||||||
|
if (!dropdown) return;
|
||||||
|
|
||||||
dropdown.innerHTML = '<option disabled selected>Loading sites...</option>';
|
dropdown.innerHTML = '<option disabled selected>Loading sites...</option>';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -237,19 +240,19 @@ async function fetchSites() {
|
|||||||
body: JSON.stringify({ password: pwd }),
|
body: JSON.stringify({ password: pwd }),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!resp.ok) throw "HTTP " + resp.status;
|
if (!resp.ok) throw new Error("HTTP " + resp.status);
|
||||||
|
|
||||||
const sites = await resp.json();
|
const sites = await resp.json();
|
||||||
|
|
||||||
if (!Array.isArray(sites) || sites.length === 0) {
|
if (!Array.isArray(sites) || sites.length === 0) {
|
||||||
dropdown.innerHTML =
|
dropdown.innerHTML = '<option disabled selected>No sites returned</option>';
|
||||||
'<option disabled selected>No sites returned</option>';
|
alert(
|
||||||
alert("No Datto sites returned. Verify credentials/allowlist, or try again in a moment.");
|
"No Datto sites returned. Verify credentials/allowlist, or try again in a moment."
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dropdown.innerHTML = "";
|
dropdown.innerHTML = "";
|
||||||
|
|
||||||
sites.forEach((site) => {
|
sites.forEach((site) => {
|
||||||
const option = document.createElement("option");
|
const option = document.createElement("option");
|
||||||
option.value = site.UID;
|
option.value = site.UID;
|
||||||
@@ -257,13 +260,14 @@ async function fetchSites() {
|
|||||||
dropdown.appendChild(option);
|
dropdown.appendChild(option);
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("dattoRmmContainer").style.display = "block";
|
const rmmContainer = document.getElementById("dattoRmmContainer");
|
||||||
|
if (rmmContainer) rmmContainer.style.display = "block";
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
dropdown.innerHTML =
|
dropdown.innerHTML = '<option disabled selected>Error loading sites</option>';
|
||||||
'<option disabled selected>Error loading sites</option>';
|
alert(
|
||||||
alert("Failed to fetch sites. Check password or confirm your public IP is allowlisted.");
|
"Failed to fetch sites. Check password or confirm your public IP is allowlisted."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,7 +279,6 @@ let allPrinters = [];
|
|||||||
// POST /getprinters with password from Devices tab
|
// POST /getprinters with password from Devices tab
|
||||||
async function fetchPrinters() {
|
async function fetchPrinters() {
|
||||||
const pwdInput = document.getElementById("PrinterPassword");
|
const pwdInput = document.getElementById("PrinterPassword");
|
||||||
|
|
||||||
const pwd = (pwdInput?.value ?? ""); // allow blank
|
const pwd = (pwdInput?.value ?? ""); // allow blank
|
||||||
|
|
||||||
const clientContainer = document.getElementById("printerClientContainer");
|
const clientContainer = document.getElementById("printerClientContainer");
|
||||||
@@ -283,12 +286,8 @@ async function fetchPrinters() {
|
|||||||
const dropdown = document.getElementById("printerClientDropdown");
|
const dropdown = document.getElementById("printerClientDropdown");
|
||||||
const checkboxContainer = document.getElementById("printerCheckboxContainer");
|
const checkboxContainer = document.getElementById("printerCheckboxContainer");
|
||||||
|
|
||||||
if (dropdown) {
|
if (dropdown) dropdown.innerHTML = '<option disabled selected>Loading clients...</option>';
|
||||||
dropdown.innerHTML = '<option disabled selected>Loading clients...</option>';
|
if (checkboxContainer) checkboxContainer.innerHTML = "";
|
||||||
}
|
|
||||||
if (checkboxContainer) {
|
|
||||||
checkboxContainer.innerHTML = "";
|
|
||||||
}
|
|
||||||
if (clientContainer) clientContainer.style.display = "none";
|
if (clientContainer) clientContainer.style.display = "none";
|
||||||
if (listContainer) listContainer.style.display = "none";
|
if (listContainer) listContainer.style.display = "none";
|
||||||
|
|
||||||
@@ -309,27 +308,22 @@ async function fetchPrinters() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build unique sorted ClientCode list
|
|
||||||
const codes = [...new Set(allPrinters.map((p) => p.ClientCode))].sort();
|
const codes = [...new Set(allPrinters.map((p) => p.ClientCode))].sort();
|
||||||
|
|
||||||
dropdown.innerHTML = "";
|
if (dropdown) {
|
||||||
const defaultOpt = new Option("Select a client...", "", true, true);
|
dropdown.innerHTML = "";
|
||||||
defaultOpt.disabled = true;
|
const defaultOpt = new Option("Select a client...", "", true, true);
|
||||||
dropdown.appendChild(defaultOpt);
|
defaultOpt.disabled = true;
|
||||||
|
dropdown.appendChild(defaultOpt);
|
||||||
|
|
||||||
codes.forEach((code) => {
|
codes.forEach((code) => dropdown.appendChild(new Option(code, code)));
|
||||||
dropdown.appendChild(new Option(code, code));
|
}
|
||||||
});
|
|
||||||
|
|
||||||
if (clientContainer) clientContainer.style.display = "block";
|
if (clientContainer) clientContainer.style.display = "block";
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("fetchPrinters error:", e);
|
console.error("fetchPrinters error:", e);
|
||||||
if (dropdown) {
|
if (dropdown) dropdown.innerHTML = '<option disabled selected>Error loading clients</option>';
|
||||||
dropdown.innerHTML =
|
|
||||||
'<option disabled selected>Error loading clients</option>';
|
|
||||||
}
|
|
||||||
alert("Failed to fetch printers. Check password or confirm your public IP is allowlisted.");
|
alert("Failed to fetch printers. Check password or confirm your public IP is allowlisted.");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,12 +348,10 @@ function renderPrintersForClient(clientCode) {
|
|||||||
label.style.display = "block";
|
label.style.display = "block";
|
||||||
label.style.marginBottom = "4px";
|
label.style.marginBottom = "4px";
|
||||||
|
|
||||||
//Install-Checkbox
|
|
||||||
const cb = document.createElement("input");
|
const cb = document.createElement("input");
|
||||||
cb.type = "checkbox";
|
cb.type = "checkbox";
|
||||||
cb.id = id;
|
cb.id = id;
|
||||||
|
|
||||||
// stash all fields we might need later
|
|
||||||
cb.dataset.clientCode = p.ClientCode;
|
cb.dataset.clientCode = p.ClientCode;
|
||||||
cb.dataset.profileName = p.ProfileName;
|
cb.dataset.profileName = p.ProfileName;
|
||||||
cb.dataset.displayName = p.DisplayName;
|
cb.dataset.displayName = p.DisplayName;
|
||||||
@@ -373,14 +365,10 @@ function renderPrintersForClient(clientCode) {
|
|||||||
const nameText = p.DisplayName || p.ProfileName || "Unnamed printer";
|
const nameText = p.DisplayName || p.ProfileName || "Unnamed printer";
|
||||||
const locText = p.Location || "Unknown location";
|
const locText = p.Location || "Unknown location";
|
||||||
|
|
||||||
// Line 1: install checkbox + printer label
|
|
||||||
label.appendChild(cb);
|
label.appendChild(cb);
|
||||||
label.appendChild(document.createTextNode(" "));
|
label.appendChild(document.createTextNode(" "));
|
||||||
label.appendChild(
|
label.appendChild(document.createTextNode(`${nameText} (${locText})`));
|
||||||
document.createTextNode(`${nameText} (${locText})`)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Line 2: radio for "Make default"
|
|
||||||
const defaultWrapper = document.createElement("div");
|
const defaultWrapper = document.createElement("div");
|
||||||
defaultWrapper.style.marginLeft = "24px";
|
defaultWrapper.style.marginLeft = "24px";
|
||||||
defaultWrapper.style.fontSize = "0.85em";
|
defaultWrapper.style.fontSize = "0.85em";
|
||||||
@@ -389,7 +377,7 @@ function renderPrintersForClient(clientCode) {
|
|||||||
const radio = document.createElement("input");
|
const radio = document.createElement("input");
|
||||||
radio.type = "radio";
|
radio.type = "radio";
|
||||||
radio.name = "defaultPrinter";
|
radio.name = "defaultPrinter";
|
||||||
radio.value = id; // associate default choice with this checkbox/printer
|
radio.value = id;
|
||||||
|
|
||||||
const radioLabel = document.createElement("span");
|
const radioLabel = document.createElement("span");
|
||||||
radioLabel.textContent = " Make default";
|
radioLabel.textContent = " Make default";
|
||||||
@@ -416,7 +404,6 @@ async function installSelectedPrinters() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// See which radio is checked for "Make default"
|
|
||||||
const defaultRadio = container.querySelector(
|
const defaultRadio = container.querySelector(
|
||||||
'input[type=radio][name="defaultPrinter"]:checked'
|
'input[type=radio][name="defaultPrinter"]:checked'
|
||||||
);
|
);
|
||||||
@@ -432,7 +419,6 @@ async function installSelectedPrinters() {
|
|||||||
ShareName: cb.dataset.shareName,
|
ShareName: cb.dataset.shareName,
|
||||||
DriverName: cb.dataset.driverName,
|
DriverName: cb.dataset.driverName,
|
||||||
DriverInfPath: cb.dataset.driverInfPath,
|
DriverInfPath: cb.dataset.driverInfPath,
|
||||||
// Only the printer whose checkbox id matches the selected radio gets SetAsDefault=true
|
|
||||||
SetAsDefault: defaultId !== null && cb.id === defaultId,
|
SetAsDefault: defaultId !== null && cb.id === defaultId,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -446,20 +432,16 @@ async function installSelectedPrinters() {
|
|||||||
if (!resp.ok) throw new Error("HTTP " + resp.status);
|
if (!resp.ok) throw new Error("HTTP " + resp.status);
|
||||||
|
|
||||||
const result = await resp.json().catch(() => null);
|
const result = await resp.json().catch(() => null);
|
||||||
|
|
||||||
console.log("Printer install result:", result);
|
console.log("Printer install result:", result);
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("installSelectedPrinters error:", e);
|
console.error("installSelectedPrinters error:", e);
|
||||||
alert("Failed to trigger printer install.");
|
alert("Failed to trigger printer install.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// =======================================================================
|
// =======================================================================
|
||||||
// Run Selected (main trigger)
|
// Run Selected (main trigger)
|
||||||
// =======================================================================
|
// =======================================================================
|
||||||
|
|
||||||
async function triggerInstall() {
|
async function triggerInstall() {
|
||||||
const runBtn = document.querySelector(".run-button");
|
const runBtn = document.querySelector(".run-button");
|
||||||
if (!runBtn) return;
|
if (!runBtn) return;
|
||||||
@@ -470,13 +452,13 @@ async function triggerInstall() {
|
|||||||
if (statusBox) statusBox.innerHTML = "";
|
if (statusBox) statusBox.innerHTML = "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Grab special-case elements ONCE
|
// Special-case elements ONCE
|
||||||
const dattoCB = document.getElementById("installDattoRMM");
|
const dattoCB = document.getElementById("installDattoRMM");
|
||||||
const svsCB = document.getElementById("installSVSMSPModule");
|
const svsCB = document.getElementById("installSVSMSPModule");
|
||||||
const renameCB = document.getElementById("renameComputer");
|
const renameCB = document.getElementById("renameComputer");
|
||||||
const newNameInput = document.getElementById("txtNewComputerName");
|
const newNameInput = document.getElementById("txtNewComputerName");
|
||||||
|
|
||||||
// Standard tasks are all tasks EXCEPT special-case ones
|
// Standard tasks = all tasks except special-case ones
|
||||||
const checkedTasks = tasks.filter((t) => {
|
const checkedTasks = tasks.filter((t) => {
|
||||||
if (["installDattoRMM", "installSVSMSPModule", "renameComputer"].includes(t.id)) return false;
|
if (["installDattoRMM", "installSVSMSPModule", "renameComputer"].includes(t.id)) return false;
|
||||||
const cb = document.getElementById(t.id);
|
const cb = document.getElementById(t.id);
|
||||||
@@ -489,7 +471,6 @@ async function triggerInstall() {
|
|||||||
if (svsCB && svsCB.checked) specialTasks++;
|
if (svsCB && svsCB.checked) specialTasks++;
|
||||||
|
|
||||||
const extraTasks = (renameCB && renameCB.checked) ? 1 : 0;
|
const extraTasks = (renameCB && renameCB.checked) ? 1 : 0;
|
||||||
|
|
||||||
const total = checkedTasks.length + specialTasks + extraTasks;
|
const total = checkedTasks.length + specialTasks + extraTasks;
|
||||||
|
|
||||||
if (total === 0) {
|
if (total === 0) {
|
||||||
@@ -554,15 +535,45 @@ async function triggerInstall() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4) Rename computer (LAST)
|
// 4) Rename computer LAST
|
||||||
if (renameCB && renameCB.checked && newNameInput) {
|
if (renameCB && renameCB.checked && newNameInput) {
|
||||||
const newName = newNameInput.value.trim();
|
const newName = newNameInput.value.trim();
|
||||||
|
|
||||||
const nameIsValid =
|
const nameIsValid =
|
||||||
newName.length > 0 &&
|
newName.length > 0 &&
|
||||||
newName.length <= 15 &&
|
newName.length <= 15 &&
|
||||||
/^[A-Za-z]()
|
/^[A-Za-z0-9-]+$/.test(newName);
|
||||||
|
|
||||||
|
if (!nameIsValid) {
|
||||||
|
alert("Invalid computer name. Must be 1-15 characters and only letters, numbers, and hyphens.");
|
||||||
|
logProgress("Rename computer", false);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
await fetch("/renameComputer", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ newName }),
|
||||||
|
});
|
||||||
|
logProgress("Rename computer", true);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Error calling /renameComputer:", e);
|
||||||
|
logProgress("Rename computer", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("triggerInstall fatal error:", e);
|
||||||
|
} finally {
|
||||||
|
runBtn.disabled = false;
|
||||||
|
|
||||||
|
// Best-effort notification to the server
|
||||||
|
try {
|
||||||
|
await fetch("/tasksCompleted", { method: "POST" });
|
||||||
|
} catch (err) {
|
||||||
|
console.warn("Could not notify server about completion:", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// =======================================================================
|
// =======================================================================
|
||||||
// Shutdown handler (Exit button & window close)
|
// Shutdown handler (Exit button & window close)
|
||||||
@@ -574,9 +585,7 @@ function endSession() {
|
|||||||
// Sub-options auto-toggle, tagline rotation, and beforeunload hook
|
// Sub-options auto-toggle, tagline rotation, and beforeunload hook
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
// Sub-option containers
|
// Sub-option containers
|
||||||
const tasksWithSubOptions = document.querySelectorAll(
|
const tasksWithSubOptions = document.querySelectorAll('[id$="OptionsContainer"]');
|
||||||
'[id$="OptionsContainer"]'
|
|
||||||
);
|
|
||||||
|
|
||||||
tasksWithSubOptions.forEach((container) => {
|
tasksWithSubOptions.forEach((container) => {
|
||||||
const taskId = container.id.replace("OptionsContainer", "");
|
const taskId = container.id.replace("OptionsContainer", "");
|
||||||
@@ -602,7 +611,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
updateVisibility();
|
updateVisibility();
|
||||||
});
|
});
|
||||||
|
|
||||||
// NEW: Rename computer checkbox -> show/hide text box
|
// Rename computer checkbox -> show/hide text box
|
||||||
const renameCheckbox = document.getElementById("renameComputer");
|
const renameCheckbox = document.getElementById("renameComputer");
|
||||||
const renameBlock = document.getElementById("renameComputerBlock");
|
const renameBlock = document.getElementById("renameComputerBlock");
|
||||||
|
|
||||||
@@ -654,7 +663,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// notify server on window close
|
// notify server on window close
|
||||||
window.addEventListener("beforeunload", () => {
|
window.addEventListener("beforeunload", () => {
|
||||||
fetch("/quit", { method: "GET", keepalive: true });
|
fetch("/quit", { method: "GET", keepalive: true });
|
||||||
|
|||||||
Reference in New Issue
Block a user