forked from FrederikBaerentsen/BrickTracker
455 lines
15 KiB
JavaScript
455 lines
15 KiB
JavaScript
// 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 = `<strong>Success:</strong> ${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 = `<strong>Success:</strong> ${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 = `<strong>Error:</strong> ${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;
|
|
}
|
|
}
|
|
}
|