From bb284008cc421dc563f4b1d0c5d1de4b0159f4d5 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Thu, 28 Apr 2022 15:01:39 +0200 Subject: [PATCH 01/16] Fix re render table --- ereuse_devicehub/static/js/main_inventory.js | 22 +++++++++----------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index c230363d..6e0c9d12 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -299,15 +299,13 @@ async function processSelectedDevices() { const tmpDiv = document.createElement("div") tmpDiv.innerHTML = newRequest - const oldTable = Array.from(document.querySelectorAll("table.table > tbody > tr .deviceSelect")).map(x => x.attributes["data-device-dhid"].value) const newTable = Array.from(tmpDiv.querySelectorAll("table.table > tbody > tr .deviceSelect")).map(x => x.attributes["data-device-dhid"].value) - for (let i = 0; i < oldTable.length; i++) { - if (!newTable.includes(oldTable[i])) { - // variable from device_list.html --> See: ereuse_devicehub\templates\inventory\device_list.html (Ln: 411) - table.rows().remove(i) + table.rows().dt.activeRows.forEach(row => { + if (!newTable.includes(row.querySelector("input").attributes["data-device-dhid"].value)) { + row.remove() } - } + }) } } @@ -352,12 +350,12 @@ async function processSelectedDevices() { const listHTML = $("#LotsSelector") - // Get selected devices - const selectedDevicesIDs = $.map($(".deviceSelect").filter(":checked"), (x) => parseInt($(x).attr("data"))); - if (selectedDevicesIDs.length <= 0) { - listHTML.html("
  • No devices selected
  • "); - return; - } + // Get selected devices + const selectedDevicesIDs = $.map($(".deviceSelect").filter(":checked"), (x) => parseInt($(x).attr("data"))); + if (selectedDevicesIDs.length <= 0) { + listHTML.html("
  • No devices selected
  • "); + return; + } // Initialize Actions list, and set checkbox triggers const actions = new Actions(); From 770ab8ea8d598845ca94a946a83767cb2b5532bc Mon Sep 17 00:00:00 2001 From: RubenPX Date: Thu, 28 Apr 2022 15:29:57 +0200 Subject: [PATCH 02/16] improvement sending variables data through methods --- ereuse_devicehub/static/js/main_inventory.js | 57 +++++++++++--------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index 6e0c9d12..187aff80 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -194,12 +194,13 @@ async function processSelectedDevices() { /** * Manage the actions that will be performed when applying the changes - * @param {*} ev event (Should be a checkbox type) - * @param {string} lotID lot id - * @param {number} deviceID device id + * @param {EventSource} ev event (Should be a checkbox type) + * @param {Lot} lot lot id + * @param {Device[]} deviceList device id */ - manage(event, lotID, deviceListID) { + manage(event, lot, deviceList) { event.preventDefault(); + const lotID = lot.id; const srcElement = event.srcElement.parentElement.children[0] const {indeterminate} = srcElement; const checked = !srcElement.checked; @@ -216,18 +217,18 @@ async function processSelectedDevices() { this.list = this.list.filter(list => list.lotID != lotID); } } else { - this.list.push({ type: "Add", lotID, devices: deviceListID, isFromIndeterminate: indeterminate }); + this.list.push({ type: "Add", lot, devices: deviceList, isFromIndeterminate: indeterminate }); } } else if (found != undefined && found.type == "Add") { - if (found.isFromIndeterminate == true) { - found.type = "Remove"; - this.list[foundIndex] = found; - } else { - this.list = this.list.filter(list => list.lotID != lotID); - } + if (found.isFromIndeterminate == true) { + found.type = "Remove"; + this.list[foundIndex] = found; } else { - this.list.push({ type: "Remove", lotID, devices: deviceListID, isFromIndeterminate: indeterminate }); + this.list = this.list.filter(list => list.lotID != lotID); } + } else { + this.list.push({ type: "Remove", lot, devices: deviceList, isFromIndeterminate: indeterminate }); + } if (this.list.length > 0) { document.getElementById("ApplyDeviceLots").classList.remove("disabled"); @@ -268,14 +269,14 @@ async function processSelectedDevices() { this.list.forEach(async action => { if (action.type == "Add") { try { - await Api.devices_add(action.lotID, action.devices); + await Api.devices_add(action.lot.id, action.devices.map(dev => dev.data)); this.notifyUser("Devices sucefully aded to selected lot/s", "", false); } catch (error) { this.notifyUser("Failed to add devices to selected lot/s", error.responseJSON.message, true); } } else if (action.type == "Remove") { try { - await Api.devices_remove(action.lotID, action.devices); + await Api.devices_remove(action.lot.id, action.devices.map(dev => dev.data)); this.notifyUser("Devices sucefully removed from selected lot/s", "", false); } catch (error) { this.notifyUser("Fail to remove devices from selected lot/s", error.responseJSON.message, true); @@ -343,19 +344,25 @@ async function processSelectedDevices() { break; } - doc.children[0].addEventListener("mouseup", (ev) => actions.manage(ev, id, selectedDevicesIDs)); - doc.children[1].addEventListener("mouseup", (ev) => actions.manage(ev, id, selectedDevicesIDs)); + doc.children[0].addEventListener("mouseup", (ev) => actions.manage(ev, lot, selectedDevices)); + doc.children[1].addEventListener("mouseup", (ev) => actions.manage(ev, lot, selectedDevices)); elementTarget.append(doc); } const listHTML = $("#LotsSelector") - // Get selected devices - const selectedDevicesIDs = $.map($(".deviceSelect").filter(":checked"), (x) => parseInt($(x).attr("data"))); - if (selectedDevicesIDs.length <= 0) { - listHTML.html("
  • No devices selected
  • "); - return; - } + // Get selected devices + const selectedDevices = table.rows().dt.activeRows.filter(item => item.querySelector("input").checked).map(item => { + const child = item.childNodes[0].children[0] + const info = {} + Object.values(child.attributes).forEach(attrib => { info[attrib.nodeName] = attrib.nodeValue }) + return info + }) + + if (selectedDevices.length <= 0) { + listHTML.html("
  • No devices selected
  • "); + return; + } // Initialize Actions list, and set checkbox triggers const actions = new Actions(); @@ -367,7 +374,7 @@ async function processSelectedDevices() { try { listHTML.html("
  • ") - const devices = await Api.get_devices(selectedDevicesIDs); + const devices = await Api.get_devices(selectedDevices.map(dev => dev.data)); let lots = await Api.get_lots(); lots = lots.map(lot => { @@ -375,11 +382,11 @@ async function processSelectedDevices() { .filter(device => device.lots.filter(devicelot => devicelot.id == lot.id).length > 0) .map(device => parseInt(device.id)); - switch (lot.devices.length) { + switch (lot.devices.length) { case 0: lot.state = "false"; break; - case selectedDevicesIDs.length: + case selectedDevices.length: lot.state = "true"; break; default: From 8d8ce634023e71d463f87527097c3ec8a2cdd7cb Mon Sep 17 00:00:00 2001 From: RubenPX Date: Thu, 28 Apr 2022 15:32:35 +0200 Subject: [PATCH 03/16] Optimize manage list --- ereuse_devicehub/static/js/main_inventory.js | 26 ++++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index 187aff80..6cb71534 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -198,37 +198,25 @@ async function processSelectedDevices() { * @param {Lot} lot lot id * @param {Device[]} deviceList device id */ - manage(event, lot, deviceList) { + manage(event, lot, deviceListID) { event.preventDefault(); const lotID = lot.id; const srcElement = event.srcElement.parentElement.children[0] - const {indeterminate} = srcElement; const checked = !srcElement.checked; - const found = this.list.filter(list => list.lotID == lotID)[0]; - const foundIndex = found != undefined ? this.list.findLastIndex(x => x.lotID == found.lotID) : -1; + const found = this.list.filter(list => list.lot.id == lotID)[0]; if (checked) { - if (found != undefined && found.type == "Remove") { - if (found.isFromIndeterminate == true) { - found.type = "Add"; - this.list[foundIndex] = found; - } else { - this.list = this.list.filter(list => list.lotID != lotID); - } + if (found && found.type == "Remove") { + found.type = "Add"; } else { - this.list.push({ type: "Add", lot, devices: deviceList, isFromIndeterminate: indeterminate }); + this.list.push({ type: "Add", lot, devices: deviceListID}); } - } else if (found != undefined && found.type == "Add") { - if (found.isFromIndeterminate == true) { + } else if (found && found.type == "Add") { found.type = "Remove"; - this.list[foundIndex] = found; } else { - this.list = this.list.filter(list => list.lotID != lotID); + this.list.push({ type: "Remove", lot, devices: deviceListID}); } - } else { - this.list.push({ type: "Remove", lot, devices: deviceList, isFromIndeterminate: indeterminate }); - } if (this.list.length > 0) { document.getElementById("ApplyDeviceLots").classList.remove("disabled"); From c824110b001f817ed51d1beb07c348ccc7d295c2 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Thu, 28 Apr 2022 18:29:18 +0200 Subject: [PATCH 04/16] Send device model through the methods --- ereuse_devicehub/static/js/main_inventory.js | 48 +++++++++----------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index 6cb71534..3859c731 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -196,9 +196,9 @@ async function processSelectedDevices() { * Manage the actions that will be performed when applying the changes * @param {EventSource} ev event (Should be a checkbox type) * @param {Lot} lot lot id - * @param {Device[]} deviceList device id + * @param {Device[]} selectedDevices device id */ - manage(event, lot, deviceListID) { + manage(event, lot, selectedDevices) { event.preventDefault(); const lotID = lot.id; const srcElement = event.srcElement.parentElement.children[0] @@ -210,13 +210,13 @@ async function processSelectedDevices() { if (found && found.type == "Remove") { found.type = "Add"; } else { - this.list.push({ type: "Add", lot, devices: deviceListID}); + this.list.push({ type: "Add", lot, devices: selectedDevices }); } } else if (found && found.type == "Add") { - found.type = "Remove"; - } else { - this.list.push({ type: "Remove", lot, devices: deviceListID}); - } + found.type = "Remove"; + } else { + this.list.push({ type: "Remove", lot, devices: selectedDevices }); + } if (this.list.length > 0) { document.getElementById("ApplyDeviceLots").classList.remove("disabled"); @@ -257,14 +257,14 @@ async function processSelectedDevices() { this.list.forEach(async action => { if (action.type == "Add") { try { - await Api.devices_add(action.lot.id, action.devices.map(dev => dev.data)); + await Api.devices_add(action.lot.id, action.devices.map(dev => dev.id)); this.notifyUser("Devices sucefully aded to selected lot/s", "", false); } catch (error) { this.notifyUser("Failed to add devices to selected lot/s", error.responseJSON.message, true); } } else if (action.type == "Remove") { try { - await Api.devices_remove(action.lot.id, action.devices.map(dev => dev.data)); + await Api.devices_remove(action.lot.id, action.devices.map(dev => dev.id)); this.notifyUser("Devices sucefully removed from selected lot/s", "", false); } catch (error) { this.notifyUser("Fail to remove devices from selected lot/s", error.responseJSON.message, true); @@ -302,14 +302,14 @@ async function processSelectedDevices() { /** * Generates a list item with a correspondient checkbox state - * @param {String} lotID - * @param {String} lotName - * @param {Array} selectedDevicesIDs - * @param {HTMLElement} target + * @param {Object} lot Lot model server + * @param {Device[]} selectedDevices list selected devices + * @param {HTMLElement} elementTarget + * @param {Action[]} actions */ - function templateLot(lot, elementTarget, actions) { + function templateLot(lot, selectedDevices, elementTarget, actions) { elementTarget.innerHTML = "" - const {id, name, state} = lot; + const { id, name, state } = lot; const htmlTemplate = ` `; @@ -340,14 +340,9 @@ async function processSelectedDevices() { const listHTML = $("#LotsSelector") // Get selected devices - const selectedDevices = table.rows().dt.activeRows.filter(item => item.querySelector("input").checked).map(item => { - const child = item.childNodes[0].children[0] - const info = {} - Object.values(child.attributes).forEach(attrib => { info[attrib.nodeName] = attrib.nodeValue }) - return info - }) + const selectedDevicesID = table.rows().dt.activeRows.filter(item => item.querySelector("input").checked).map(item => item.querySelector("input").attributes.data.value) - if (selectedDevices.length <= 0) { + if (selectedDevicesID.length <= 0) { listHTML.html("
  • No devices selected
  • "); return; } @@ -362,11 +357,11 @@ async function processSelectedDevices() { try { listHTML.html("
  • ") - const devices = await Api.get_devices(selectedDevices.map(dev => dev.data)); + const selectedDevices = await Api.get_devices(selectedDevicesID); let lots = await Api.get_lots(); lots = lots.map(lot => { - lot.devices = devices + lot.devices = selectedDevices .filter(device => device.lots.filter(devicelot => devicelot.id == lot.id).length > 0) .map(device => parseInt(device.id)); @@ -374,7 +369,7 @@ async function processSelectedDevices() { case 0: lot.state = "false"; break; - case selectedDevices.length: + case selectedDevicesID.length: lot.state = "true"; break; default: @@ -385,7 +380,6 @@ async function processSelectedDevices() { return lot; }) - let lotsList = []; lotsList.push(lots.filter(lot => lot.state == "true").sort((a,b) => a.name.localeCompare(b.name))); lotsList.push(lots.filter(lot => lot.state == "indetermined").sort((a,b) => a.name.localeCompare(b.name))); @@ -393,7 +387,7 @@ async function processSelectedDevices() { lotsList = lotsList.flat(); // flat array listHTML.html(""); - lotsList.forEach(lot => templateLot(lot, listHTML, actions)); + lotsList.forEach(lot => templateLot(lot, selectedDevices, listHTML, actions)); } catch (error) { console.log(error); listHTML.html("
  • Error feching devices and lots
    (see console for more details)
  • "); From 962f7cb94cc20da6fca4aea62174fb4455ec41bd Mon Sep 17 00:00:00 2001 From: RubenPX Date: Thu, 28 Apr 2022 18:29:39 +0200 Subject: [PATCH 05/16] lint --- ereuse_devicehub/static/js/main_inventory.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index 3859c731..380bb962 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -163,7 +163,7 @@ function get_device_list() { if (computer[typ]) { typ = computer[typ]; }; - return `${typ } ${ manuf } ${ dhid}`; + return `${typ} ${manuf} ${dhid}`; }); description = $.map(list_devices, (x) => x).join(", "); @@ -173,7 +173,7 @@ function get_device_list() { function export_file(type_file) { const devices = $(".deviceSelect").filter(":checked"); const devices_id = $.map(devices, (x) => $(x).attr("data-device-dhid")).join(","); - if (devices_id){ + if (devices_id) { const url = `/inventory/export/${type_file}/?ids=${devices_id}`; window.location.href = url; } else { @@ -233,7 +233,7 @@ async function processSelectedDevices() { */ notifyUser(title, toastText, isError) { const toast = document.createElement("div"); - toast.classList = `alert alert-dismissible fade show ${ isError ? "alert-danger" : "alert-success"}`; + toast.classList = `alert alert-dismissible fade show ${isError ? "alert-danger" : "alert-success"}`; toast.attributes["data-autohide"] = !isError; toast.attributes.role = "alert"; toast.style = "margin-left: auto; width: fit-content;"; @@ -381,9 +381,9 @@ async function processSelectedDevices() { }) let lotsList = []; - lotsList.push(lots.filter(lot => lot.state == "true").sort((a,b) => a.name.localeCompare(b.name))); - lotsList.push(lots.filter(lot => lot.state == "indetermined").sort((a,b) => a.name.localeCompare(b.name))); - lotsList.push(lots.filter(lot => lot.state == "false").sort((a,b) => a.name.localeCompare(b.name))); + lotsList.push(lots.filter(lot => lot.state == "true").sort((a, b) => a.name.localeCompare(b.name))); + lotsList.push(lots.filter(lot => lot.state == "indetermined").sort((a, b) => a.name.localeCompare(b.name))); + lotsList.push(lots.filter(lot => lot.state == "false").sort((a, b) => a.name.localeCompare(b.name))); lotsList = lotsList.flat(); // flat array listHTML.html(""); From f26b441fef491955ed08f232bd406bd180ba5d52 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Fri, 29 Apr 2022 11:36:55 +0200 Subject: [PATCH 06/16] create TableController to access more easy to table info --- .eslintrc.json | 3 +- ereuse_devicehub/static/js/main_inventory.js | 34 +++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 0d9213bb..56f4296d 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -27,7 +27,8 @@ "strict": "off", "class-methods-use-this": "off", "eqeqeq": "warn", - "radix": "warn" + "radix": "warn", + "max-classes-per-file": ["error", 2] }, "globals": { "API_URLS": true, diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index 380bb962..1bddad27 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -17,6 +17,38 @@ $(document).ready(() => { // $('#selectLot').selectpicker(); }) +class TableController { + static #tableRows = table.rows().dt.activeRows; + + /** + * @returns This will return all input attributes from selected devices + */ + static getSelectedDevices() { + return this.#ProcessTR(this.#tableRows.filter(element => element.querySelector("input").checked)) + } + + /** + * @returns This will return all input attributes from all devices in list + */ + static getAllDevices() { + return this.#ProcessTR(this.#tableRows) + } + + /** + * + * @param {HTMLElement} DOMElements + * @returns Procesed input atributes to an Object class + */ + static #ProcessTR(DOMElements) { + return DOMElements.map(element => { + const info = {} + info.checked = element.querySelector("input").checked + Object.values(element.querySelector("input").attributes).forEach(attrib => {info[attrib.nodeName] = attrib.nodeValue}) + return info + }) + } +} + function deviceSelect() { const devices_count = $(".deviceSelect").filter(":checked").length; get_device_list(); @@ -340,7 +372,7 @@ async function processSelectedDevices() { const listHTML = $("#LotsSelector") // Get selected devices - const selectedDevicesID = table.rows().dt.activeRows.filter(item => item.querySelector("input").checked).map(item => item.querySelector("input").attributes.data.value) + const selectedDevicesID = TableController.getSelectedDevices().map(item => item.data) if (selectedDevicesID.length <= 0) { listHTML.html("
  • No devices selected
  • "); From 0fd12ee37cd754c523a13c6bfe3c2f65c445af45 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Fri, 29 Apr 2022 12:36:42 +0200 Subject: [PATCH 07/16] Use TableController to check all devices list --- ereuse_devicehub/static/js/main_inventory.js | 38 +++++++++++--------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index 1bddad27..ccb34a05 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -24,14 +24,17 @@ class TableController { * @returns This will return all input attributes from selected devices */ static getSelectedDevices() { - return this.#ProcessTR(this.#tableRows.filter(element => element.querySelector("input").checked)) + return this.#tableRows + .filter(element => element.querySelector("input").checked) + .map(element => element.querySelector("input")) } /** * @returns This will return all input attributes from all devices in list */ static getAllDevices() { - return this.#ProcessTR(this.#tableRows) + return this.#tableRows + .map(element => element.querySelector("input")) } /** @@ -39,18 +42,18 @@ class TableController { * @param {HTMLElement} DOMElements * @returns Procesed input atributes to an Object class */ - static #ProcessTR(DOMElements) { + static ProcessTR(DOMElements) { return DOMElements.map(element => { const info = {} - info.checked = element.querySelector("input").checked - Object.values(element.querySelector("input").attributes).forEach(attrib => {info[attrib.nodeName] = attrib.nodeValue}) + info.checked = element.checked + Object.values(element.attributes).forEach(attrib => {info[attrib.nodeName.replace(/-/g, "_")] = attrib.nodeValue}) return info }) } } function deviceSelect() { - const devices_count = $(".deviceSelect").filter(":checked").length; + const devices_count = TableController.getSelectedDevices().length; get_device_list(); if (devices_count == 0) { $("#addingLotModal .pol").show(); @@ -92,7 +95,7 @@ function deviceSelect() { } function removeLot() { - const devices = $(".deviceSelect"); + const devices = TableController.getAllDevices(); if (devices.length > 0) { $("#btnRemoveLots .text-danger").show(); } else { @@ -102,8 +105,8 @@ function removeLot() { } function removeTag() { - const devices = $(".deviceSelect").filter(":checked"); - const devices_id = $.map(devices, (x) => $(x).attr("data")); + const devices = TableController.getSelectedDevices(); + const devices_id = devices.map(dev => dev.data); if (devices_id.length == 1) { const url = `/inventory/tag/devices/${devices_id[0]}/del/`; window.location.href = url; @@ -113,8 +116,8 @@ function removeTag() { } function addTag() { - const devices = $(".deviceSelect").filter(":checked"); - const devices_id = $.map(devices, (x) => $(x).attr("data")); + const devices = TableController.getSelectedDevices(); + const devices_id = devices.map(dev => dev.data); if (devices_id.length == 1) { $("#addingTagModal .pol").hide(); $("#addingTagModal .btn-primary").show(); @@ -169,7 +172,7 @@ function newDataWipe(action) { } function get_device_list() { - const devices = $(".deviceSelect").filter(":checked"); + const devices = TableController.getSelectedDevices(); /* Insert the correct count of devices in actions form */ const devices_count = devices.length; @@ -188,10 +191,11 @@ function get_device_list() { "Desktop": "", "Laptop": "", }; + list_devices = devices.map((x) => { - let typ = $(devices[x]).data("device-type"); - const manuf = $(devices[x]).data("device-manufacturer"); - const dhid = $(devices[x]).data("device-dhid"); + let typ = $(x).data("device-type"); + const manuf = $(x).data("device-manufacturer"); + const dhid = $(x).data("device-dhid"); if (computer[typ]) { typ = computer[typ]; }; @@ -203,7 +207,7 @@ function get_device_list() { } function export_file(type_file) { - const devices = $(".deviceSelect").filter(":checked"); + const devices = TableController.getSelectedDevices(); const devices_id = $.map(devices, (x) => $(x).attr("data-device-dhid")).join(","); if (devices_id) { const url = `/inventory/export/${type_file}/?ids=${devices_id}`; @@ -372,7 +376,7 @@ async function processSelectedDevices() { const listHTML = $("#LotsSelector") // Get selected devices - const selectedDevicesID = TableController.getSelectedDevices().map(item => item.data) + const selectedDevicesID = TableController.ProcessTR(TableController.getSelectedDevices()).map(item => item.data) if (selectedDevicesID.length <= 0) { listHTML.html("
  • No devices selected
  • "); From e238fb287a1cb0949849ee503eb2285d79fa5411 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Fri, 29 Apr 2022 13:27:46 +0200 Subject: [PATCH 08/16] Fix remove rows using library API --- ereuse_devicehub/static/js/main_inventory.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index ccb34a05..f7f2531b 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -326,11 +326,15 @@ async function processSelectedDevices() { const newTable = Array.from(tmpDiv.querySelectorAll("table.table > tbody > tr .deviceSelect")).map(x => x.attributes["data-device-dhid"].value) - table.rows().dt.activeRows.forEach(row => { + // https://github.com/fiduswriter/Simple-DataTables/wiki/rows()#removeselect-arraynumber + const rowsToRemove = [] + for (let i = 0; i < table.activeRows.length; i++) { + const row = table.activeRows[i]; if (!newTable.includes(row.querySelector("input").attributes["data-device-dhid"].value)) { - row.remove() + rowsToRemove.push(i) } - }) + } + table.rows().remove(rowsToRemove); } } From f8f4e10f9f8ac4a2eb61e6a459539f55d66ac769 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Fri, 29 Apr 2022 13:33:44 +0200 Subject: [PATCH 09/16] Restore state of checkbox before apply lots changes --- ereuse_devicehub/static/js/main_inventory.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index f7f2531b..74ef3196 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -335,6 +335,11 @@ async function processSelectedDevices() { } } table.rows().remove(rowsToRemove); + + // Restore state of checkbox + const selectAllBTN = document.getElementById("SelectAllBTN"); + selectAllBTN.checked = false; + selectAllBTN.indeterminate = false; } } From 7503895a4fea65bb7f97b94a9336aca045e21034 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Fri, 29 Apr 2022 13:34:45 +0200 Subject: [PATCH 10/16] Adds selector by pages --- ereuse_devicehub/static/js/main_inventory.js | 23 ++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index 74ef3196..0d902a0b 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -19,9 +19,11 @@ $(document).ready(() => { class TableController { static #tableRows = table.rows().dt.activeRows; + + static #tableRowsPage = table.rows().dt.pages[table.rows().dt.currentPage - 1]; /** - * @returns This will return all input attributes from selected devices + * @returns Selected inputs from device list */ static getSelectedDevices() { return this.#tableRows @@ -30,13 +32,30 @@ class TableController { } /** - * @returns This will return all input attributes from all devices in list + * @returns Selected inputs in current page from device list + */ + static getAllSelectedDevicesInCurrentPage() { + return this.#tableRowsPage + .filter(element => element.querySelector("input").checked) + .map(element => element.querySelector("input")) + } + + /** + * @returns All inputs from device list */ static getAllDevices() { return this.#tableRows .map(element => element.querySelector("input")) } + /** + * @returns All inputs from current page in device list + */ + static getAllDevicesInCurrentPage() { + return this.#tableRows + .map(element => element.querySelector("input")) + } + /** * * @param {HTMLElement} DOMElements From b88a514edf95f1b7001e8893c6c41c7fa5c678f2 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Fri, 29 Apr 2022 13:58:48 +0200 Subject: [PATCH 11/16] Fix reactivity un variables avoid outdated data variable --- ereuse_devicehub/static/js/main_inventory.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index 0d902a0b..b9e2c5ff 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -18,9 +18,9 @@ $(document).ready(() => { }) class TableController { - static #tableRows = table.rows().dt.activeRows; - - static #tableRowsPage = table.rows().dt.pages[table.rows().dt.currentPage - 1]; + static #tableRows = table.activeRows; + + static #tableRowsPage = () => table.pages[table.rows().dt.currentPage - 1]; /** * @returns Selected inputs from device list @@ -35,7 +35,7 @@ class TableController { * @returns Selected inputs in current page from device list */ static getAllSelectedDevicesInCurrentPage() { - return this.#tableRowsPage + return this.#tableRowsPage() .filter(element => element.querySelector("input").checked) .map(element => element.querySelector("input")) } @@ -52,7 +52,7 @@ class TableController { * @returns All inputs from current page in device list */ static getAllDevicesInCurrentPage() { - return this.#tableRows + return this.#tableRowsPage() .map(element => element.querySelector("input")) } From 8bbca0301b9ccf14d060347de0531cdf253a49c8 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Fri, 29 Apr 2022 14:06:09 +0200 Subject: [PATCH 12/16] Selection devices by page --- ereuse_devicehub/static/js/main.js | 28 --------------- ereuse_devicehub/static/js/main_inventory.js | 38 +++++++++++++++++++- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/ereuse_devicehub/static/js/main.js b/ereuse_devicehub/static/js/main.js index 55a4951c..1dbaaeb0 100644 --- a/ereuse_devicehub/static/js/main.js +++ b/ereuse_devicehub/static/js/main.js @@ -215,34 +215,6 @@ }, 200); } - /** - * Select all functionality - */ - const btnSelectAll = document.getElementById("SelectAllBTN"); - const tableListCheckboxes = document.querySelectorAll(".deviceSelect"); - - function itemListCheckChanged(event) { - const isAllChecked = Array.from(tableListCheckboxes).map(itm => itm.checked); - if (isAllChecked.every(bool => bool == true)) { - btnSelectAll.checked = true; - btnSelectAll.indeterminate = false; - } else if (isAllChecked.every(bool => bool == false)) { - btnSelectAll.checked = false; - btnSelectAll.indeterminate = false; - } else { - btnSelectAll.indeterminate = true; - } - } - - tableListCheckboxes.forEach(item => { - item.addEventListener("click", itemListCheckChanged); - }) - - btnSelectAll.addEventListener("click", event => { - const checkedState = event.target.checked; - tableListCheckboxes.forEach(ckeckbox => {ckeckbox.checked = checkedState}); - }) - /** * Avoid hide dropdown when user clicked inside */ diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index b9e2c5ff..7bccb247 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -34,7 +34,7 @@ class TableController { /** * @returns Selected inputs in current page from device list */ - static getAllSelectedDevicesInCurrentPage() { + static getAllSelectedDevicesInCurrentPage() { return this.#tableRowsPage() .filter(element => element.querySelector("input").checked) .map(element => element.querySelector("input")) @@ -71,6 +71,42 @@ class TableController { } } +/** + * Select all functionality + */ +window.addEventListener("DOMContentLoaded", () => { + const btnSelectAll = document.getElementById("SelectAllBTN"); + + function itemListCheckChanged() { + const listDevices = TableController.getAllDevicesInCurrentPage() + const isAllChecked = listDevices.map(itm => itm.checked); + + if (isAllChecked.every(bool => bool == true)) { + btnSelectAll.checked = true; + btnSelectAll.indeterminate = false; + } else if (isAllChecked.every(bool => bool == false)) { + btnSelectAll.checked = false; + btnSelectAll.indeterminate = false; + } else { + btnSelectAll.indeterminate = true; + } + } + + TableController.getAllDevices().forEach(item => { + item.addEventListener("click", itemListCheckChanged); + }) + + btnSelectAll.addEventListener("click", event => { + const checkedState = event.target.checked; + TableController.getAllDevicesInCurrentPage().forEach(ckeckbox => { ckeckbox.checked = checkedState }); + }) + + // https://github.com/fiduswriter/Simple-DataTables/wiki/Events + table.on("datatable.page", () => itemListCheckChanged()); + table.on("datatable.perpage", () => itemListCheckChanged()); + table.on("datatable.update", () => itemListCheckChanged()); +}) + function deviceSelect() { const devices_count = TableController.getSelectedDevices().length; get_device_list(); From c78c9c5d7da8a88a143df2f7bd0580f27b0876f2 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Fri, 29 Apr 2022 14:07:04 +0200 Subject: [PATCH 13/16] Lint --- ereuse_devicehub/static/js/main.js | 6 +++--- ereuse_devicehub/static/js/main_inventory.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ereuse_devicehub/static/js/main.js b/ereuse_devicehub/static/js/main.js index 1dbaaeb0..996d8b23 100644 --- a/ereuse_devicehub/static/js/main.js +++ b/ereuse_devicehub/static/js/main.js @@ -14,9 +14,9 @@ el = el.trim() if (all) { return [...document.querySelectorAll(el)] - } - return document.querySelector(el) - + } + return document.querySelector(el) + } /** diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index 7bccb247..5d4fedf3 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -51,7 +51,7 @@ class TableController { /** * @returns All inputs from current page in device list */ - static getAllDevicesInCurrentPage() { + static getAllDevicesInCurrentPage() { return this.#tableRowsPage() .map(element => element.querySelector("input")) } @@ -65,7 +65,7 @@ class TableController { return DOMElements.map(element => { const info = {} info.checked = element.checked - Object.values(element.attributes).forEach(attrib => {info[attrib.nodeName.replace(/-/g, "_")] = attrib.nodeValue}) + Object.values(element.attributes).forEach(attrib => { info[attrib.nodeName.replace(/-/g, "_")] = attrib.nodeValue }) return info }) } From d7f7e4d2e56d8a104bbc856bc5556c52b429ac68 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Tue, 3 May 2022 11:06:05 +0200 Subject: [PATCH 14/16] fixed api not working on recive full list Api needs filter devices to work well --- ereuse_devicehub/static/js/main_inventory.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index 5d4fedf3..9732b5ef 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -348,14 +348,16 @@ async function processSelectedDevices() { this.list.forEach(async action => { if (action.type == "Add") { try { - await Api.devices_add(action.lot.id, action.devices.map(dev => dev.id)); + const devicesIDs = action.devices.filter(dev => !action.lot.devices.includes(dev.id)).map(dev => dev.id) + await Api.devices_add(action.lot.id, devicesIDs); this.notifyUser("Devices sucefully aded to selected lot/s", "", false); } catch (error) { this.notifyUser("Failed to add devices to selected lot/s", error.responseJSON.message, true); } } else if (action.type == "Remove") { try { - await Api.devices_remove(action.lot.id, action.devices.map(dev => dev.id)); + const devicesIDs = action.devices.filter(dev => action.lot.devices.includes(dev.id)).map(dev => dev.id) + await Api.devices_remove(action.lot.id, devicesIDs); this.notifyUser("Devices sucefully removed from selected lot/s", "", false); } catch (error) { this.notifyUser("Fail to remove devices from selected lot/s", error.responseJSON.message, true); From 9d9514e68b66f9596e26924a54fa56af079a0eec Mon Sep 17 00:00:00 2001 From: RubenPX Date: Tue, 3 May 2022 12:13:15 +0200 Subject: [PATCH 15/16] Select full list devices --- ereuse_devicehub/static/js/main_inventory.js | 16 ++++++++++++++++ .../templates/inventory/device_list.html | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index 9732b5ef..b7b4387c 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -76,6 +76,7 @@ class TableController { */ window.addEventListener("DOMContentLoaded", () => { const btnSelectAll = document.getElementById("SelectAllBTN"); + const alertInfoDevices = document.getElementById("select-devices-info"); function itemListCheckChanged() { const listDevices = TableController.getAllDevicesInCurrentPage() @@ -84,11 +85,20 @@ window.addEventListener("DOMContentLoaded", () => { if (isAllChecked.every(bool => bool == true)) { btnSelectAll.checked = true; btnSelectAll.indeterminate = false; + alertInfoDevices.innerHTML = `Selected devices: ${TableController.getSelectedDevices().length} + ${ + TableController.getAllDevices().length != TableController.getSelectedDevices().length + ? `Select all devices (${TableController.getAllDevices().length})` + : "" + }`; + alertInfoDevices.classList.remove("d-none"); } else if (isAllChecked.every(bool => bool == false)) { btnSelectAll.checked = false; btnSelectAll.indeterminate = false; + alertInfoDevices.classList.add("d-none") } else { btnSelectAll.indeterminate = true; + alertInfoDevices.classList.add("d-none") } } @@ -99,6 +109,12 @@ window.addEventListener("DOMContentLoaded", () => { btnSelectAll.addEventListener("click", event => { const checkedState = event.target.checked; TableController.getAllDevicesInCurrentPage().forEach(ckeckbox => { ckeckbox.checked = checkedState }); + itemListCheckChanged() + }) + + alertInfoDevices.addEventListener("click", () => { + TableController.getAllDevices().forEach(ckeckbox => { ckeckbox.checked = true }); + itemListCheckChanged() }) // https://github.com/fiduswriter/Simple-DataTables/wiki/Events diff --git a/ereuse_devicehub/templates/inventory/device_list.html b/ereuse_devicehub/templates/inventory/device_list.html index 827c3b68..c3b910ae 100644 --- a/ereuse_devicehub/templates/inventory/device_list.html +++ b/ereuse_devicehub/templates/inventory/device_list.html @@ -297,6 +297,10 @@ {% endif %} + +
    From 2aab4b49d3bdadc2bb61c91a81d9dea0b9170fc2 Mon Sep 17 00:00:00 2001 From: RubenPX Date: Tue, 3 May 2022 12:52:26 +0200 Subject: [PATCH 16/16] Allow user to cancel all selection --- ereuse_devicehub/static/js/main_inventory.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ereuse_devicehub/static/js/main_inventory.js b/ereuse_devicehub/static/js/main_inventory.js index b7b4387c..a183dd72 100644 --- a/ereuse_devicehub/static/js/main_inventory.js +++ b/ereuse_devicehub/static/js/main_inventory.js @@ -89,7 +89,7 @@ window.addEventListener("DOMContentLoaded", () => { ${ TableController.getAllDevices().length != TableController.getSelectedDevices().length ? `Select all devices (${TableController.getAllDevices().length})` - : "" + : "Cancel selection" }`; alertInfoDevices.classList.remove("d-none"); } else if (isAllChecked.every(bool => bool == false)) { @@ -113,7 +113,8 @@ window.addEventListener("DOMContentLoaded", () => { }) alertInfoDevices.addEventListener("click", () => { - TableController.getAllDevices().forEach(ckeckbox => { ckeckbox.checked = true }); + const checkState = TableController.getAllDevices().length == TableController.getSelectedDevices().length + TableController.getAllDevices().forEach(ckeckbox => { ckeckbox.checked = !checkState }); itemListCheckChanged() })