diff --git a/ereuse_devicehub/static/js/main_inventory.build.js b/ereuse_devicehub/static/js/main_inventory.build.js
index 4ee7afe9..e948d26c 100644
--- a/ereuse_devicehub/static/js/main_inventory.build.js
+++ b/ereuse_devicehub/static/js/main_inventory.build.js
@@ -26,8 +26,10 @@ $(document).ready(() => {
newTrade(show_trade_form);
} else {
$(".deviceSelect").on("change", deviceSelect);
- } // $('#selectLot').selectpicker();
+ }
+ ;
+ select_shift(); // $('#selectLot').selectpicker();
});
class TableController {
@@ -239,6 +241,756 @@ function addTag() {
$("#addTagAlertModal").click();
}
+function select_shift() {
+ const chkboxes = $('.deviceSelect');
+ var lastChecked = null;
+ chkboxes.click(function (e) {
+ if (!lastChecked) {
+ lastChecked = this;
+ return;
+ }
+
+ if (e.shiftKey) {
+ var start = chkboxes.index(this);
+ var end = chkboxes.index(lastChecked);
+ chkboxes.slice(Math.min(start, end), Math.max(start, end) + 1).prop('checked', lastChecked.checked);
+ }
+
+ lastChecked = this;
+ });
+ selectorController("softInit");
+}
+
+function newTrade(action) {
+ let title = "Trade ";
+ const user_to = $("#user_to").data("email");
+ const user_from = $("#user_from").data("email");
+
+ if (action == "user_from") {
+ title = "Trade Incoming";
+ $("#user_to").attr("readonly", "readonly");
+ $("#user_from").prop("readonly", false);
+ $("#user_from").val("");
+ $("#user_to").val(user_to);
+ } else if (action == "user_to") {
+ title = "Trade Outgoing";
+ $("#user_from").attr("readonly", "readonly");
+ $("#user_to").prop("readonly", false);
+ $("#user_to").val("");
+ $("#user_from").val(user_from);
+ }
+
+ $("#tradeLotModal #title-action").html(title);
+ $("#activeTradeModal").click();
+}
+
+function newAction(action) {
+ $("#actionModal #type").val(action);
+ $("#actionModal #title-action").html(action);
+ deviceSelect();
+ $("#activeActionModal").click();
+}
+
+function newAllocate(action) {
+ $("#allocateModal #type").val(action);
+ $("#allocateModal #title-action").html(action);
+ deviceSelect();
+ $("#activeAllocateModal").click();
+}
+
+function newDataWipe(action) {
+ $("#datawipeModal #type").val(action);
+ $("#datawipeModal #title-action").html(action);
+ deviceSelect();
+ $("#activeDatawipeModal").click();
+}
+
+function get_device_list() {
+ const devices = TableController.getSelectedDevices();
+ /* Insert the correct count of devices in actions form */
+
+ const devices_count = devices.length;
+ $("#datawipeModal .devices-count").html(devices_count);
+ $("#allocateModal .devices-count").html(devices_count);
+ $("#actionModal .devices-count").html(devices_count);
+ /* Insert the correct value in the input devicesList */
+
+ const devices_id = $.map(devices, x => $(x).attr("data")).join(",");
+ $.map($(".devicesList"), x => {
+ $(x).val(devices_id);
+ });
+ /* Create a list of devices for human representation */
+
+ const computer = {
+ "Desktop": "",
+ "Laptop": ""
+ };
+ const list_devices = devices.map(x => {
+ let typ = $(x).data("device-type");
+ const manuf = $(x).data("device-manufacturer");
+ const dhid = $(x).data("device-dhid");
+
+ if (computer[typ]) {
+ typ = computer[typ];
+ }
+
+ ;
+ return "".concat(typ, " ").concat(manuf, " ").concat(dhid);
+ });
+ const description = $.map(list_devices, x => x).join(", ");
+ $(".enumeration-devices").html(description);
+}
+
+function export_file(type_file) {
+ const devices = TableController.getSelectedDevices();
+ const devices_id = $.map(devices, x => $(x).attr("data-device-dhid")).join(",");
+
+ if (devices_id) {
+ const url = "/inventory/export/".concat(type_file, "/?ids=").concat(devices_id);
+ window.location.href = url;
+ } else {
+ $("#exportAlertModal").click();
+ }
+}
+
+class lotsSearcher {
+ static enable() {
+ if (this.lotsSearchElement) this.lotsSearchElement.disabled = false;
+ }
+
+ static disable() {
+ if (this.lotsSearchElement) this.lotsSearchElement.disabled = true;
+ }
+ /**
+ * do search when lot change in the search input
+ */
+
+
+ static doSearch(inputSearch) {
+ const lots = this.getListLots();
+
+ for (let i = 0; i < lots.length; i++) {
+ const lot = lots[i];
+
+ if (lot.innerText.toLowerCase().includes(inputSearch.toLowerCase())) {
+ lot.style.display = "";
+ } else {
+ lot.style.display = "none";
+ }
+ }
+ }
+
+}
+
+_defineProperty(lotsSearcher, "lots", []);
+
+_defineProperty(lotsSearcher, "lotsSearchElement", null);
+
+_defineProperty(lotsSearcher, "getListLots", () => {
+ const lotsList = document.getElementById("LotsSelector");
+
+ if (lotsList) {
+ // Apply filter to get only labels
+ return Array.from(lotsList.children).filter(item => item.querySelector("label"));
+ }
+
+ return [];
+});
+
+document.addEventListener("DOMContentLoaded", () => {
+ lotsSearcher.lotsSearchElement = document.getElementById("lots-search");
+ lotsSearcher.lotsSearchElement.addEventListener("input", e => {
+ lotsSearcher.doSearch(e.target.value);
+ });
+});
+/**
+ * Reactive lots button
+ */
+
+async function processSelectedDevices() {
+ class Actions {
+ constructor() {
+ this.list = []; // list of petitions of requests @item --> {type: ["Remove" | "Add"], "LotID": string, "devices": number[]}
+ }
+ /**
+ * 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[]} selectedDevices device id
+ */
+
+
+ manage(event, lot, selectedDevices) {
+ event.preventDefault();
+ const lotID = lot.id;
+ const srcElement = event.srcElement.parentElement.children[0];
+ const checked = !srcElement.checked;
+ const {
+ indeterminate
+ } = srcElement;
+ const found = this.list.filter(list => list.lot.id == lotID)[0];
+
+ if (checked) {
+ if (found && found.type == "Remove") {
+ const affectedDevices = found.devices.filter(dev => found.lot.devices.includes(dev.id));
+
+ if (affectedDevices.length > 0 && found.indeterminate == false) {
+ // Remove action from list
+ actions.list = actions.list.filter(x => x.lot.id != found.lot.id);
+ } else {
+ found.type = "Add";
+ }
+ } else {
+ this.list.push({
+ type: "Add",
+ lot,
+ devices: selectedDevices,
+ indeterminate
+ });
+ }
+ } else if (found && found.type == "Add") {
+ const affectedDevices = found.devices.filter(dev => !found.lot.devices.includes(dev.id));
+
+ if (affectedDevices.length > 0 && found.indeterminate == false) {
+ // Remove action from list
+ actions.list = actions.list.filter(x => x.lot.id != found.lot.id);
+ } else {
+ found.type = "Remove";
+ }
+ } else {
+ this.list.push({
+ type: "Remove",
+ lot,
+ devices: selectedDevices,
+ indeterminate
+ });
+ }
+
+ if (this.list.length > 0) {
+ document.getElementById("ApplyDeviceLots").classList.remove("disabled");
+ } else {
+ document.getElementById("ApplyDeviceLots").classList.add("disabled");
+ }
+ }
+ /**
+ * Creates notification to give feedback to user
+ * @param {string} title notification title
+ * @param {string | null} toastText notification text
+ * @param {boolean} isError defines if a toast is a error
+ */
+
+
+ notifyUser(title, toastText, isError) {
+ const toast = document.createElement("div");
+ toast.classList = "alert alert-dismissible fade show ".concat(isError ? "alert-danger" : "alert-success");
+ toast.attributes["data-autohide"] = !isError;
+ toast.attributes.role = "alert";
+ toast.style = "margin-left: auto; width: fit-content;";
+ toast.innerHTML = "".concat(title, "");
+
+ if (toastText && toastText.length > 0) {
+ toast.innerHTML += "
".concat(toastText);
+ }
+
+ document.getElementById("NotificationsContainer").appendChild(toast);
+
+ if (!isError) {
+ setTimeout(() => toast.classList.remove("show"), 3000);
+ }
+
+ setTimeout(() => document.getElementById("NotificationsContainer").innerHTML == "", 3500);
+ }
+ /**
+ * Get actions and execute call request to add or remove devices from lots
+ */
+
+
+ doActions() {
+ let requestCount = 0; // This is for count all requested api count, to perform reRender of table device list
+
+ this.list.forEach(async action => {
+ if (action.type == "Add") {
+ try {
+ 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 added 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 {
+ 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("Failed to remove devices from selected lot/s", error.responseJSON.message, true);
+ }
+ }
+
+ requestCount += 1;
+
+ if (requestCount == this.list.length) {
+ this.reRenderTable();
+ this.list = [];
+ }
+ });
+ $("#confirmLotsModal").modal("hide"); // Hide dialog when click "Save changes"
+
+ document.getElementById("dropDownLotsSelector").classList.remove("show");
+ }
+ /**
+ * Re-render list in table
+ */
+
+
+ async reRenderTable() {
+ const newRequest = await Api.doRequest(window.location);
+ const tmpDiv = document.createElement("div");
+ tmpDiv.innerHTML = newRequest;
+ const newTable = document.createElement("table");
+ newTable.innerHTML = tmpDiv.querySelector("table").innerHTML;
+ newTable.classList = "table";
+ const oldTable = document.querySelector(".dataTable-wrapper");
+ oldTable.parentElement.replaceChild(newTable, oldTable);
+ table = new simpleDatatables.DataTable(newTable, {
+ perPage: 20
+ }); // // Restore state of checkbox
+
+ const selectAllBTN = document.getElementById("SelectAllBTN");
+ selectAllBTN.checked = false;
+ selectAllBTN.indeterminate = false; // Re-init SelectorController
+
+ selectorController("softInit");
+ }
+
+ }
+
+ let eventClickActions;
+ /**
+ * Generates a list item with a correspondient checkbox state
+ * @param {Object} lot Lot model server
+ * @param {Device[]} selectedDevices list selected devices
+ * @param {HTMLElement} elementTarget
+ * @param {Action[]} actions
+ */
+
+ function templateLot(lot, selectedDevices, elementTarget, actions) {
+ elementTarget.innerHTML = "";
+ const {
+ id,
+ name,
+ state
+ } = lot;
+ const htmlTemplate = "\n ");
+ const doc = document.createElement("li");
+ doc.innerHTML = htmlTemplate;
+
+ switch (state) {
+ case "true":
+ doc.children[0].checked = true;
+ break;
+
+ case "false":
+ doc.children[0].checked = false;
+ break;
+
+ case "indetermined":
+ doc.children[0].indeterminate = true;
+ break;
+
+ default:
+ console.warn("This shouldn't be happend: Lot without state: ", lot);
+ break;
+ }
+
+ 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 selectedDevicesID = TableController.ProcessTR(TableController.getSelectedDevices()).map(item => item.data);
+
+ if (selectedDevicesID.length <= 0) {
+ listHTML.html("
\n ").concat(devices.map(item => { + const name = "".concat(item.type, " ").concat(item.manufacturer, " ").concat(item.model); + return "").concat(item.devicehubID, ""); + }).join(" "), "\n
\n