- Update local webUI to refresh when joining server to clear modal - Updated client webUI page title - Re-added join modal to node page (client & server) - updated join modal to use node.nearbySystems
407 lines
14 KiB
JavaScript
407 lines
14 KiB
JavaScript
$(document).ready(async () => {
|
|
console.log("Loading stored notifications...");
|
|
await loadStoredToasts();
|
|
console.log("Showing stored notifications...");
|
|
await showStoredToasts();
|
|
});
|
|
|
|
/**
|
|
* Gets all toasts stored in local storage
|
|
*
|
|
* @returns {Object} Object of toasts in storage
|
|
*/
|
|
function getStoredToasts() {
|
|
if (localStorage.getItem("toasts")) {
|
|
const storedToasts = JSON.parse(localStorage.getItem("toasts"));
|
|
console.log("LOADED STORED TOASTS: ", storedToasts);
|
|
navbarUpdateNotificationBellCount(storedToasts);
|
|
return storedToasts;
|
|
}
|
|
else return false
|
|
}
|
|
|
|
/**
|
|
* Adds a toast to storage, will not allow duplicates
|
|
*
|
|
* @param {Date} time The date object from when the toast was created
|
|
* @param {*} message The message of the toast
|
|
*/
|
|
function addToastToStorage(time, message) {
|
|
var toasts = [{ 'time': time, 'message': message }]
|
|
var storedToasts = getStoredToasts();
|
|
console.log("Adding new notification to storage: ", toasts);
|
|
if (storedToasts) {
|
|
toasts = toasts.concat(storedToasts);
|
|
console.log("Combined new and stored notifications: ", toasts);
|
|
toasts = toasts.filter((value, index, self) =>
|
|
index === self.findIndex((t) => (
|
|
t.time === value.time && t.message === value.message
|
|
))
|
|
)
|
|
}
|
|
console.log("Deduped stored notifications: ", toasts);
|
|
localStorage.setItem("toasts", JSON.stringify(toasts));
|
|
navbarUpdateNotificationBellCount(toasts);
|
|
}
|
|
|
|
/**
|
|
* Removes a toast from the local storage
|
|
*
|
|
* @param {Date} time The date object from when the toast was created
|
|
* @param {*} message The message of the toast
|
|
*/
|
|
function removeToastFromStorage(time, message) {
|
|
const toastToRemove = { 'time': time, 'message': message }
|
|
console.log("Toast to remove: ", toastToRemove);
|
|
var toasts = getStoredToasts();
|
|
console.log("Stored toasts: ", toasts);
|
|
if (toasts.indexOf(toastToRemove)) toasts.splice(toasts.indexOf(toastToRemove) - 1, 1)
|
|
console.log("Toasts with selected toast removed: ", toasts);
|
|
localStorage.setItem("toasts", JSON.stringify(toasts));
|
|
navbarUpdateNotificationBellCount(toasts);
|
|
}
|
|
|
|
/**
|
|
* Shows all stored toasts
|
|
*/
|
|
function showStoredToasts() {
|
|
const storedToasts = getStoredToasts();
|
|
if (!storedToasts) return
|
|
console.log("Loaded stored notifications to show: ", storedToasts);
|
|
for (const toast of storedToasts) {
|
|
const toastId = `${toast.time}-toast`;
|
|
console.log("Showing stored toast: ", toast, toastId);
|
|
const toastElement = bootstrap.Toast.getOrCreateInstance(document.getElementById(toastId));
|
|
toastElement.show();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loads all toasts stored in the local storage into the DOM of the webpage
|
|
*/
|
|
function loadStoredToasts() {
|
|
const storedToasts = getStoredToasts();
|
|
if (!storedToasts) return
|
|
console.log("Loaded stored notifications: ", storedToasts);
|
|
for (const toast of storedToasts) {
|
|
createToast(toast.message, { time: toast.time })
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Will update the count of notifications on the bell icon in the navbar
|
|
*
|
|
* @param {Array} storedToasts An array of stored toasts to be counted and updated in the navbar
|
|
*/
|
|
function navbarUpdateNotificationBellCount(storedToasts) {
|
|
const notificationBellIcon = document.getElementById("navbar-notification-bell");
|
|
var notificationBellCount = document.getElementById("notification-bell-icon-count");
|
|
if (!notificationBellCount) {
|
|
notificationBellCount = document.createElement('span');
|
|
notificationBellCount.id = "notification-bell-icon-count";
|
|
notificationBellCount.classList.add('badge');
|
|
notificationBellCount.classList.add('text-bg-secondary');
|
|
notificationBellCount.appendChild(document.createTextNode(storedToasts.length));
|
|
}
|
|
else notificationBellCount.innerHTML = storedToasts.length;
|
|
|
|
notificationBellIcon.appendChild(notificationBellCount);
|
|
}
|
|
|
|
/**
|
|
* Remove a frequency input from the DOM
|
|
*
|
|
* @param {string} system The system name to add the frequency to
|
|
* @param {string} inputId [OPTIONAL] The ID of input, this can be anything unique to this input. If this is not provided the number of frequencies will be used as the ID
|
|
*/
|
|
function addFrequencyInput(system, inputId = null) {
|
|
if (!inputId) inputId = $(`[id^="${system}_systemFreqRow_"]`).length;
|
|
// Create new input
|
|
var icon = document.createElement('i');
|
|
icon.classList.add('bi');
|
|
icon.classList.add('bi-x-circle');
|
|
icon.classList.add('text-black');
|
|
|
|
var remove = document.createElement('a');
|
|
remove.classList.add('align-middle');
|
|
remove.classList.add('float-left');
|
|
remove.href = '#'
|
|
remove.onclick = () => { removeFrequencyInput(`${system}_systemFreqRow_${inputId}`) }
|
|
remove.appendChild(icon);
|
|
|
|
var childColRemoveIcon = document.createElement('div');
|
|
childColRemoveIcon.classList.add('col-2');
|
|
childColRemoveIcon.appendChild(remove);
|
|
|
|
var input = document.createElement('input');
|
|
input.classList.add('form-control');
|
|
input.id = `${system}_systemFreq_${inputId}`;
|
|
input.type = 'text';
|
|
|
|
var childColInput = document.createElement('div');
|
|
childColInput.classList.add('col-10');
|
|
childColInput.appendChild(input);
|
|
|
|
var childRow = document.createElement('div');
|
|
childRow.classList.add("row");
|
|
childRow.classList.add("px-1");
|
|
childRow.appendChild(childColInput);
|
|
childRow.appendChild(childColRemoveIcon);
|
|
|
|
var colParent = document.createElement('div');
|
|
colParent.classList.add("col-md-6");
|
|
colParent.classList.add("mb-1");
|
|
colParent.id = `${system}_systemFreqRow_${inputId}`
|
|
colParent.appendChild(childRow);
|
|
|
|
document.getElementById(`frequencyRow_${system.replaceAll(" ", "_")}`).appendChild(colParent);
|
|
}
|
|
|
|
/**
|
|
* Add a toast element to the DOM
|
|
*
|
|
* @param {*} notificationMessage The message of the notification
|
|
* @param {Date} param1.time The date object for when the toast was created, blank if creating new
|
|
* @param {boolean} param1.showNow Show the toast now or just store it
|
|
* @returns
|
|
*/
|
|
function createToast(notificationMessage, { time = undefined, showNow = false } = {}) {
|
|
if (!time) time = new Date(Date.now());
|
|
else time = new Date(Date.parse(time));
|
|
const toastTitle = document.createElement('strong');
|
|
toastTitle.classList.add('me-auto');
|
|
toastTitle.appendChild(document.createTextNode("Server Notification"));
|
|
|
|
const toastTime = document.createElement('small');
|
|
toastTime.appendChild(document.createTextNode(time.toLocaleString()));
|
|
|
|
const toastClose = document.createElement('button');
|
|
toastClose.type = 'button';
|
|
toastClose.classList.add('btn-close');
|
|
toastClose.ariaLabel = 'Close';
|
|
toastClose.setAttribute('data-bs-dismiss', 'toast');
|
|
toastClose.onclick = () => { removeToastFromStorage(time.toISOString(), notificationMessage); };
|
|
|
|
const toastHeader = document.createElement('div');
|
|
toastHeader.classList.add('toast-header');
|
|
toastHeader.appendChild(toastTitle);
|
|
toastHeader.appendChild(toastTime);
|
|
toastHeader.appendChild(toastClose);
|
|
|
|
const toastMessage = document.createElement('p');
|
|
toastMessage.classList.add("px-2");
|
|
toastMessage.appendChild(document.createTextNode(notificationMessage));
|
|
|
|
const toastBody = document.createElement('div');
|
|
toastBody.classList.add('toast-body');
|
|
toastBody.appendChild(toastMessage);
|
|
|
|
const wrapperDiv = document.createElement('div');
|
|
wrapperDiv.classList.add('toast');
|
|
//wrapperDiv.classList.add('position-fixed');
|
|
wrapperDiv.id = `${time.toISOString()}-toast`;
|
|
wrapperDiv.role = 'alert';
|
|
wrapperDiv.ariaLive = 'assertive';
|
|
wrapperDiv.ariaAtomic = true;
|
|
wrapperDiv.setAttribute('data-bs-delay', "7500");
|
|
wrapperDiv.setAttribute('data-bs-animation', true);
|
|
wrapperDiv.appendChild(toastHeader);
|
|
wrapperDiv.appendChild(toastMessage);
|
|
|
|
document.getElementById("toastZone").appendChild(wrapperDiv);
|
|
addToastToStorage(time.toISOString(), notificationMessage);
|
|
if (showNow) {
|
|
const toastElement = bootstrap.Toast.getOrCreateInstance(document.getElementById(`${time.toISOString()}-toast`));
|
|
toastElement.show();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
function sendNodeHeartbeat(nodeId) {
|
|
const Http = new XMLHttpRequest();
|
|
const url = '/nodes/nodeCheckIn/' + nodeId;
|
|
Http.open("GET", url);
|
|
Http.send();
|
|
|
|
Http.onloadend = (e) => {
|
|
console.log(Http.responseText)
|
|
createToast(Http.responseText, { showNow: true });
|
|
}
|
|
}
|
|
|
|
function joinServer() {
|
|
const preset = document.getElementById("selectRadioPreset").value;
|
|
const nodeId = document.getElementById("nodeId").value;
|
|
const clientId = document.getElementById("inputDiscordClientId").value;
|
|
const channelId = document.getElementById("inputDiscordChannelId").value;
|
|
|
|
const reqBody = {
|
|
'preset': preset,
|
|
'nodeId': nodeId,
|
|
'clientId': clientId,
|
|
'channelId': channelId
|
|
};
|
|
|
|
console.log(reqBody);
|
|
|
|
const Http = new XMLHttpRequest();
|
|
const url = '/admin/join';
|
|
Http.open("POST", url);
|
|
Http.setRequestHeader("Content-Type", "application/json");
|
|
Http.send(JSON.stringify(reqBody));
|
|
|
|
Http.onloadend = (e) => {
|
|
const responseObject = JSON.parse(Http.responseText)
|
|
console.log(Http.status);
|
|
console.log(responseObject);
|
|
createToast(`${responseObject.name} will join shortly`, { showNow: true });
|
|
location.reload();
|
|
}
|
|
}
|
|
|
|
function leaveServer() {
|
|
const nodeId = document.getElementById("nodeId").value;
|
|
const reqBody = {
|
|
'nodeId': nodeId
|
|
};
|
|
|
|
const Http = new XMLHttpRequest();
|
|
const url = '/admin/leave';
|
|
Http.open("POST", url);
|
|
Http.setRequestHeader("Content-Type", "application/json");
|
|
Http.send(JSON.stringify(reqBody));
|
|
|
|
Http.onloadend = (e) => {
|
|
const responseObject = JSON.parse(Http.responseText)
|
|
console.log(Http.status);
|
|
console.log(responseObject);
|
|
createToast(`${responseObject} is leaving`, { showNow: true });
|
|
}
|
|
}
|
|
|
|
function saveNodeDetails() {
|
|
const nodeId = document.getElementById("nodeId").value;
|
|
const nodeName = document.getElementById("inputNodeName").value;
|
|
const nodeIp = document.getElementById("inputNodeIp").value;
|
|
const nodePort = document.getElementById("inputOrgName").value;
|
|
const nodeLocation = document.getElementById("inputNodeLocation").value;
|
|
|
|
const reqBody = {
|
|
'id': nodeId,
|
|
'name': nodeName,
|
|
'ip': nodeIp,
|
|
'port': nodePort,
|
|
'location': nodeLocation
|
|
}
|
|
|
|
console.log("Request Body: ", reqBody);
|
|
|
|
const Http = new XMLHttpRequest();
|
|
const url = '/nodes/' + nodeId;
|
|
Http.open("PUT", url);
|
|
Http.setRequestHeader("Content-Type", "application/json");
|
|
Http.send(JSON.stringify(reqBody));
|
|
|
|
Http.onloadend = (e) => {
|
|
const responseObject = JSON.parse(Http.responseText);
|
|
console.log(Http.status);
|
|
console.log(responseObject);
|
|
createToast(`Node Updated!`);
|
|
location.reload();
|
|
}
|
|
}
|
|
|
|
function addNewSystem() {
|
|
const nodeId = document.getElementById("nodeId").value;
|
|
const systemName = document.getElementById(`New System_systemName`).value;
|
|
const systemMode = document.getElementById(`New System_systemMode`).value;
|
|
const inputSystemFreqs = $(`[id^="New System_systemFreq_"]`);
|
|
let systemFreqs = [];
|
|
for (const inputFreq of inputSystemFreqs) {
|
|
systemFreqs.push(inputFreq.value);
|
|
}
|
|
|
|
const reqBody = {
|
|
'systemName': systemName,
|
|
'mode': systemMode,
|
|
'frequencies': systemFreqs
|
|
}
|
|
|
|
console.log("Request Body: ", reqBody);
|
|
const Http = new XMLHttpRequest();
|
|
const url = '/nodes/' + nodeId + "/systems";
|
|
Http.open("POST", url);
|
|
Http.setRequestHeader("Content-Type", "application/json");
|
|
Http.send(JSON.stringify(reqBody));
|
|
|
|
Http.onloadend = (e) => {
|
|
const responseObject = Http.responseText
|
|
console.log(Http.status);
|
|
console.log(responseObject);
|
|
createToast(`${systemName} Added!`);
|
|
location.reload();
|
|
}
|
|
}
|
|
|
|
function updateSystem(systemName) {
|
|
const nodeId = document.getElementById("nodeId").value;
|
|
const systemMode = document.getElementById(`${systemName}_systemMode`).value;
|
|
const inputSystemFreqs = $(`[id^="${systemName}_systemFreq_"]`);
|
|
let systemFreqs = [];
|
|
for (const inputFreq of inputSystemFreqs) {
|
|
systemFreqs.push(inputFreq.value);
|
|
}
|
|
|
|
const reqBody = {
|
|
'systemName': systemName,
|
|
'mode': systemMode,
|
|
'frequencies': systemFreqs
|
|
}
|
|
|
|
console.log("Request Body: ", reqBody);
|
|
const Http = new XMLHttpRequest();
|
|
const url = '/nodes/' + nodeId + "/systems";
|
|
Http.open("PUT", url);
|
|
Http.setRequestHeader("Content-Type", "application/json");
|
|
Http.send(JSON.stringify(reqBody));
|
|
|
|
Http.onloadend = (e) => {
|
|
const responseObject = Http.responseText;
|
|
console.log(Http.status);
|
|
console.log(responseObject);
|
|
createToast(`${systemName} Updated!`);
|
|
location.reload();
|
|
}
|
|
}
|
|
|
|
function removeSystem(systemName) {
|
|
const nodeId = document.getElementById("nodeId").value;
|
|
|
|
const reqBody = {
|
|
'systemName': systemName,
|
|
}
|
|
|
|
console.log("Request Body: ", reqBody);
|
|
const Http = new XMLHttpRequest();
|
|
const url = '/nodes/' + nodeId + "/systems";
|
|
Http.open("DELETE", url);
|
|
Http.setRequestHeader("Content-Type", "application/json");
|
|
Http.send(JSON.stringify(reqBody));
|
|
Http.onloadend = (e) => {
|
|
const responseObject = Http.responseText;
|
|
console.log(Http.status);
|
|
console.log(responseObject);
|
|
createToast(`${systemName} Removed!`);
|
|
location.reload();
|
|
}
|
|
}
|
|
|
|
function requestNodeUpdate() {
|
|
|
|
}
|
|
|
|
function removeFrequencyInput(elementId) {
|
|
const element = document.getElementById(elementId);
|
|
element.remove();
|
|
} |