diff --git a/samy.js b/samy.js
index b301f7f..6fa8f98 100644
--- a/samy.js
+++ b/samy.js
@@ -261,8 +261,168 @@ async function fetchSites() {
}
// =======================================================================
-// Run Selected (main trigger)
+// Printer management (Devices tab)
// =======================================================================
+let allPrinters = [];
+
+// POST /getprinters with password from Devices tab
+async function fetchPrinters() {
+ const pwdInput = document.getElementById("PrinterPassword");
+ const pwd = pwdInput?.value;
+ if (!pwd) {
+ alert("Please enter the printer password.");
+ return;
+ }
+
+ const clientContainer = document.getElementById("printerClientContainer");
+ const listContainer = document.getElementById("printerListContainer");
+ const dropdown = document.getElementById("printerClientDropdown");
+ const checkboxContainer = document.getElementById("printerCheckboxContainer");
+
+ if (dropdown) {
+ dropdown.innerHTML = '';
+ }
+ if (checkboxContainer) {
+ checkboxContainer.innerHTML = "";
+ }
+ if (clientContainer) clientContainer.style.display = "none";
+ if (listContainer) listContainer.style.display = "none";
+
+ try {
+ const resp = await fetch("/getprinters", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ password: pwd }),
+ });
+
+ if (!resp.ok) throw new Error("HTTP " + resp.status);
+
+ const data = await resp.json();
+ allPrinters = Array.isArray(data) ? data : [];
+
+ if (!allPrinters.length) {
+ alert("No printers returned for this password.");
+ return;
+ }
+
+ // Build unique sorted ClientCode list
+ const codes = [...new Set(allPrinters.map((p) => p.ClientCode))].sort();
+
+ dropdown.innerHTML = "";
+ const defaultOpt = new Option("Select a client...", "", true, true);
+ defaultOpt.disabled = true;
+ dropdown.appendChild(defaultOpt);
+
+ codes.forEach((code) => {
+ dropdown.appendChild(new Option(code, code));
+ });
+
+ if (clientContainer) clientContainer.style.display = "block";
+ } catch (e) {
+ console.error("fetchPrinters error:", e);
+ if (dropdown) {
+ dropdown.innerHTML =
+ '';
+ }
+ alert("Failed to fetch printers. Check password and try again.");
+ }
+}
+
+function renderPrintersForClient(clientCode) {
+ const container = document.getElementById("printerCheckboxContainer");
+ const listContainer = document.getElementById("printerListContainer");
+ if (!container) return;
+
+ container.innerHTML = "";
+
+ const printers = allPrinters.filter((p) => p.ClientCode === clientCode);
+
+ if (!printers.length) {
+ container.textContent = "No printers found for this client.";
+ if (listContainer) listContainer.style.display = "block";
+ return;
+ }
+
+ printers.forEach((p, idx) => {
+ const id = `printer_${clientCode}_${idx}`;
+ const label = document.createElement("label");
+ label.style.display = "block";
+
+ const cb = document.createElement("input");
+ cb.type = "checkbox";
+ cb.id = id;
+
+ // stash all fields we might need later
+ cb.dataset.clientCode = p.ClientCode;
+ cb.dataset.profileName = p.ProfileName;
+ cb.dataset.displayName = p.DisplayName;
+ cb.dataset.location = p.Location;
+ cb.dataset.address = p.Address;
+ cb.dataset.printServer = p.PrintServer;
+ cb.dataset.shareName = p.ShareName;
+ cb.dataset.driverName = p.DriverName;
+ cb.dataset.driverInfPath = p.DriverInfPath;
+
+ const nameText =
+ p.DisplayName || p.ProfileName || "Unnamed printer";
+ const locText = p.Location || "Unknown location";
+
+ label.appendChild(cb);
+ label.appendChild(document.createTextNode(" "));
+ label.appendChild(
+ document.createTextNode(`${nameText} (${locText})`)
+ );
+
+ container.appendChild(label);
+ });
+
+ if (listContainer) listContainer.style.display = "block";
+}
+
+async function installSelectedPrinters() {
+ const container = document.getElementById("printerCheckboxContainer");
+ if (!container) return;
+
+ const checked = container.querySelectorAll("input[type=checkbox]:checked");
+ if (!checked.length) {
+ alert("Please select at least one printer.");
+ return;
+ }
+
+ const selected = Array.from(checked).map((cb) => ({
+ ClientCode: cb.dataset.clientCode,
+ ProfileName: cb.dataset.profileName,
+ DisplayName: cb.dataset.displayName,
+ Location: cb.dataset.location,
+ Address: cb.dataset.address,
+ PrintServer: cb.dataset.printServer,
+ ShareName: cb.dataset.shareName,
+ DriverName: cb.dataset.driverName,
+ DriverInfPath: cb.dataset.driverInfPath,
+ }));
+
+ try {
+ const resp = await fetch("/installprinters", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ printers: selected }),
+ });
+
+ if (!resp.ok) throw new Error("HTTP " + resp.status);
+
+ const result = await resp.json().catch(() => null);
+
+ alert(
+ `Requested installation for ${selected.length} printer(s).` +
+ (result && result.Message ? "\n" + result.Message : "")
+ );
+ } catch (e) {
+ console.error("installSelectedPrinters error:", e);
+ alert("Failed to trigger printer install.");
+ }
+}
+
+
// =======================================================================
// Run Selected (main trigger)
// =======================================================================
@@ -474,6 +634,18 @@ document.addEventListener("DOMContentLoaded", () => {
}
});
+// printer dropdown
+document.addEventListener("DOMContentLoaded", () => {
+ const clientDropdown = document.getElementById("printerClientDropdown");
+ if (clientDropdown) {
+ clientDropdown.addEventListener("change", (e) => {
+ const code = e.target.value;
+ if (code) renderPrintersForClient(code);
+ });
+ }
+});
+
+
// notify server on window close
window.addEventListener("beforeunload", () => {
fetch("/quit", { method: "GET", keepalive: true });