// Socket class class BrickSocket { constructor(id, path, namespace, messages, bulk=false) { this.id = id; this.path = path; this.namespace = namespace; this.messages = messages; this.bulk = bulk; this.disabled = false; this.socket = undefined; // Listeners this.add_listener = undefined; this.confirm_listener = undefined; // Form elements (built based on the initial id) this.html_button = document.getElementById(id); this.html_complete = document.getElementById(`${id}-complete`); this.html_count = document.getElementById(`${id}-count`); this.html_fail = document.getElementById(`${id}-fail`); this.html_input = document.getElementById(`${id}-set`); this.html_no_confim = document.getElementById(`${id}-no-confirm`); this.html_progress = document.getElementById(`${id}-progress`); this.html_progress_bar = document.getElementById(`${id}-progress-bar`); this.html_progress_message = document.getElementById(`${id}-progress-message`); this.html_spinner = document.getElementById(`${id}-spinner`); this.html_status = document.getElementById(`${id}-status`); this.html_status_icon = document.getElementById(`${id}-status-icon`); // Card elements this.html_card = document.getElementById(`${id}-card`); this.html_card_number = document.getElementById(`${id}-card-number`); this.html_card_name = document.getElementById(`${id}-card-name`); this.html_card_image_container = document.getElementById(`${id}-card-image-container`); this.html_card_image = document.getElementById(`${id}-card-image`); this.html_card_footer = document.getElementById(`${id}-card-footer`); this.html_card_confirm = document.getElementById(`${id}-card-confirm`); this.html_card_dismiss = document.getElementById(`${id}-card-dismiss`); if (this.html_button) { this.add_listener = ((bricksocket) => (e) => { if (!bricksocket.disabled) { bricksocket.toggle(false); // Split and save the list if bulk if (bricksocket.bulk) { bricksocket.read_set_list() } if (bricksocket.bulk || (bricksocket.html_no_confim && bricksocket.html_no_confim.checked)) { bricksocket.import_set(true); } else { bricksocket.load_set(); } } })(this); this.html_button.addEventListener("click", this.add_listener); } if (this.html_card_dismiss && this.html_card) { this.html_card_dismiss.addEventListener("click", ((card) => (e) => { card.classList.add("d-none"); })(this.html_card)); } // Socket status window.setInterval(((bricksocket) => () => { bricksocket.status(); })(this), 500); // Setup the socket this.setup(); } // Clear form clear() { this.clear_status(); if (this.html_count) { this.html_count.classList.add("d-none"); } if(this.html_progress_bar) { this.html_progress.setAttribute("aria-valuenow", "0"); this.html_progress_bar.setAttribute("style", "width: 0%"); this.html_progress_bar.textContent = ""; } this.spinner(false); if (this.html_card) { this.html_card.classList.add("d-none"); } if (this.html_card_footer) { this.html_card_footer.classList.add("d-none"); if (this.html_card_confirm) { this.html_card_footer.classList.add("d-none"); } } } // Clear status message clear_status() { if (this.html_complete) { this.html_complete.classList.add("d-none"); if (this.bulk) { this.html_complete.innerHTML = ""; } else { this.html_complete.textContent = ""; } } if (this.html_fail) { this.html_fail.classList.add("d-none"); this.html_fail.textContent = ""; } } // Upon receiving a complete message complete(data) { if(this.html_progress_bar) { this.html_progress.setAttribute("aria-valuenow", "100"); this.html_progress_bar.setAttribute("style", "width: 100%"); this.html_progress_bar.textContent = "100%"; } if (this.bulk) { if (this.html_complete) { this.html_complete.classList.remove("d-none"); // Create a message (not ideal as it is template inside code) const success = document.createElement("div"); success.classList.add("alert", "alert-success"); success.setAttribute("role", "alert"); success.innerHTML = `Success: ${data.message}` this.html_complete.append(success) } // Import the next set this.import_set(true, undefined, true); } else { this.spinner(false); if (this.html_complete) { this.html_complete.classList.remove("d-none"); this.html_complete.innerHTML = `Success: ${data.message}`; } if (this.html_fail) { this.html_fail.classList.add("d-none"); } } } // Update the count count(count, total) { if (this.html_count) { this.html_count.classList.remove("d-none"); // If there is no total, display a question mark instead if (total == 0) { total = "?" } this.html_count.textContent = `(${count}/${total})`; } } // Upon receiving a fail message fail(data) { this.spinner(false); if (this.html_fail) { this.html_fail.classList.remove("d-none", ); this.html_fail.innerHTML = `Error: ${data.message}`; } if (!this.bulk && this.html_complete) { this.html_complete.classList.add("d-none"); } if (this.html_progress_bar) { this.html_progress_bar.classList.remove("progress-bar-animated"); } if (this.bulk && this.html_input) { if (this.set_list_last_number !== undefined) { this.set_list.unshift(this.set_list_last_number); this.set_list_last_number = undefined; } this.html_input.value = this.set_list.join(', '); } } // Import a set import_set(no_confirm, number, from_complete=false) { if (this.html_input) { if (!this.bulk || !from_complete) { // Reset the progress if (no_confirm) { this.clear(); } else { this.clear_status(); } } // Grab from the list if bulk if (this.bulk) { number = this.set_list.shift() // Abort if nothing left to process if (number === undefined) { // Clear the input this.html_input.value = ""; // Settle the form this.spinner(false); this.toggle(true); return; } // Save the pulled number this.set_list_last_number = number; } this.spinner(true); this.socket.emit(this.messages.IMPORT_SET, { set_num: (number !== undefined) ? number : this.html_input.value, }); } else { this.fail("Could not find the input field for the set number"); } } // Load a set load_set() { if (this.html_input) { // Reset the progress this.clear() this.spinner(true); this.socket.emit(this.messages.LOAD_SET, { set_num: this.html_input.value }); } else { this.fail("Could not find the input field for the set number"); } } // Update the progress progress(data={}) { let total = data["total"]; let count = data["count"] // Fix the total if bogus if (!total || isNaN(total) || total <= 1) { total = 0; } // Fix the count if bogus if (!count || isNaN(count) || count <= 1) { count = 1; } this.count(count, total); this.progress_message(data["message"]); if (this.html_progress && this.html_progress_bar) { // Infinite progress bar if (!total) { this.html_progress.setAttribute("aria-valuenow", "100"); this.html_progress_bar.classList.add("progress-bar-striped", "progress-bar-animated"); this.html_progress_bar.setAttribute("style", "width: 100%"); this.html_progress_bar.textContent = ""; } else { if (count > total) { total = count; } const progress = (count - 1) * 100 / total; this.html_progress.setAttribute("aria-valuenow", progress); this.html_progress_bar.classList.remove("progress-bar-striped", "progress-bar-animated"); this.html_progress_bar.setAttribute("style", `width: ${progress}%`); this.html_progress_bar.textContent = `${progress.toFixed(2)}%`; } } } // Update the progress message progress_message(message) { if (this.html_progress_message) { this.html_progress_message.classList.remove("d-none"); this.html_progress_message.textContent = message; } } // Bulk: read the input as a list read_set_list() { this.set_list = []; if (this.html_input) { const value = this.html_input.value; this.set_list = value.split(",").map((el) => el.trim()) } } // Set is loaded set_loaded(data) { if (this.html_card) { this.html_card.classList.remove("d-none"); if (this.html_card_number) { this.html_card_number.textContent = data["set_num"]; } if (this.html_card_name) { this.html_card_name.textContent = data["name"]; } if (this.html_card_image_container) { this.html_card_image_container.setAttribute("style", `background-image: url(${data["set_img_url"]})`); } if (this.html_card_image) { this.html_card_image.setAttribute("src", data["set_img_url"]); this.html_card_image.setAttribute("alt", data["set_num"]); } if (this.html_card_footer) { this.html_card_footer.classList.add("d-none"); if (!data.download) { this.html_card_footer.classList.remove("d-none"); if (this.html_card_confirm) { if (this.confirm_listener !== undefined) { this.html_card_confirm.removeEventListener("click", this.confirm_listener); } this.confirm_listener = ((bricksocket, number) => (e) => { if (!bricksocket.disabled) { bricksocket.toggle(false); bricksocket.import_set(false, number); } })(this, data["set_num"]); this.html_card_confirm.addEventListener("click", this.confirm_listener); } } } } } // Setup the actual socket setup() { if (this.socket === undefined) { this.socket = io.connect(`${window.location.origin}/${this.namespace}`, { path: this.path, transports: ["websocket"], }); // Complete this.socket.on(this.messages.COMPLETE, ((bricksocket) => (data) => { bricksocket.complete(data); if (!bricksocket.bulk) { bricksocket.toggle(true); } })(this)); // Fail this.socket.on(this.messages.FAIL, ((bricksocket) => (data) => { bricksocket.fail(data); bricksocket.toggle(true); })(this)); // Progress this.socket.on(this.messages.PROGRESS, ((bricksocket) => (data) => { bricksocket.progress(data); })(this)); // Set loaded this.socket.on(this.messages.SET_LOADED, ((bricksocket) => (data) => { bricksocket.set_loaded(data); })(this)); } } // Toggle the spinner spinner(show) { if (this.html_spinner) { if (show) { this.html_spinner.classList.remove("d-none"); } else { this.html_spinner.classList.add("d-none"); } } } // Toggle the status status() { if (this.html_status) { if (this.socket === undefined) { this.html_status.textContent = "Socket is not initialized"; if (this.html_status_icon) { this.html_status_icon.classList.remove("ri-checkbox-circle-fill", "ri-close-circle-fill"); this.html_status_icon.classList.add("ri-question-fill"); } } else if (this.socket.connected) { this.html_status.textContent = "Socket is connected"; if (this.html_status_icon) { this.html_status_icon.classList.remove("ri-question-fill", "ri-close-circle-fill"); this.html_status_icon.classList.add("ri-checkbox-circle-fill"); } } else { this.html_status.textContent = "Socket is disconnected"; if (this.html_status_icon) { this.html_status_icon.classList.remove("ri-question-fill", "ri-checkbox-circle-fill"); this.html_status_icon.classList.add("ri-close-circle-fill"); } } } } // Toggle clicking on the button, or sending events toggle(enabled) { this.disabled = !enabled; if (this.html_button) { this.html_button.disabled = !enabled; } if (this.html_input) { this.html_input.disabled = !enabled; } if (this.html_card_confirm) { this.html_card_confirm.disabled = !enabled; } if (this.html_card_dismiss) { this.html_card_dismiss.disabled = !enabled; } } }