Finalizing Server webUI

Still needed:
- Way to update clients' versions
- Way to delete nodes
- working dashboard
- working search function
This commit is contained in:
Logan Cusano
2023-07-22 01:19:54 -04:00
parent 75156d059e
commit ace762fc76
18 changed files with 327 additions and 67 deletions

View File

@@ -1,11 +1,119 @@
$(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);
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;
function addFrequencyInput(system, inputId = null) {
if (!inputId) inputId = $(`[id^="${system}_systemFreqRow_"]`).length;
// Create new input
var icon = document.createElement('i');
icon.classList.add('bi');
@@ -16,7 +124,7 @@ function addFrequencyInput(system, inputId = null){
remove.classList.add('align-middle');
remove.classList.add('float-left');
remove.href = '#'
remove.onclick = () => {removeFrequencyInput(`${system}_systemFreqRow_${inputId}`)}
remove.onclick = () => { removeFrequencyInput(`${system}_systemFreqRow_${inputId}`) }
remove.appendChild(icon);
var childColRemoveIcon = document.createElement('div');
@@ -31,7 +139,7 @@ function addFrequencyInput(system, inputId = null){
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");
@@ -47,19 +155,30 @@ function addFrequencyInput(system, inputId = null){
document.getElementById(`frequencyRow_${system.replaceAll(" ", "_")}`).appendChild(colParent);
}
function createToast(notificationMessage){
/**
* 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(new Date(Date.now()).toLocaleString()));
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');
@@ -67,7 +186,6 @@ function createToast(notificationMessage){
toastHeader.appendChild(toastTime);
toastHeader.appendChild(toastClose);
const toastMessage = document.createElement('p');
toastMessage.classList.add("px-2");
toastMessage.appendChild(document.createTextNode(notificationMessage));
@@ -78,31 +196,39 @@ function createToast(notificationMessage){
const wrapperDiv = document.createElement('div');
wrapperDiv.classList.add('toast');
wrapperDiv.role ='alert';
//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);
$('.toast').toast('show');
return $('.toast');
addToastToStorage(time.toISOString(), notificationMessage);
if (showNow) {
const toastElement = bootstrap.Toast.getOrCreateInstance(document.getElementById(`${time.toISOString()}-toast`));
toastElement.show();
}
return;
}
function sendNodeHeartbeat(nodeId){
function sendNodeHeartbeat(nodeId) {
const Http = new XMLHttpRequest();
const url='/nodes/nodeCheckIn/'+nodeId;
const url = '/nodes/nodeCheckIn/' + nodeId;
Http.open("GET", url);
Http.send();
Http.onloadend = (e) => {
console.log(Http.responseText)
createToast(Http.responseText);
console.log(Http.responseText)
createToast(Http.responseText, { showNow: true });
}
}
function joinServer(){
function joinServer() {
const preset = document.getElementById("selectRadioPreset").value;
const nodeId = document.getElementById("nodeId").value;
const clientId = document.getElementById("inputDiscordClientId").value;
@@ -118,7 +244,7 @@ function joinServer(){
console.log(reqBody);
const Http = new XMLHttpRequest();
const url='/admin/join';
const url = '/admin/join';
Http.open("POST", url);
Http.setRequestHeader("Content-Type", "application/json");
Http.send(JSON.stringify(reqBody));
@@ -127,19 +253,19 @@ function joinServer(){
const responseObject = JSON.parse(Http.responseText)
console.log(Http.status);
console.log(responseObject);
createToast(`${responseObject.name} will join shortly`);
createToast(`${responseObject.name} will join shortly`, { showNow: true });
$("#joinModal").modal('toggle');
}
}
function leaveServer(){
function leaveServer() {
const nodeId = document.getElementById("nodeId").value;
const reqBody = {
'nodeId': nodeId
};
const Http = new XMLHttpRequest();
const url='/admin/leave';
const url = '/admin/leave';
Http.open("POST", url);
Http.setRequestHeader("Content-Type", "application/json");
Http.send(JSON.stringify(reqBody));
@@ -148,8 +274,7 @@ function leaveServer(){
const responseObject = JSON.parse(Http.responseText)
console.log(Http.status);
console.log(responseObject);
createToast(`${responseObject} is leaving`);
setTimeout(() => {}, 45000);
createToast(`${responseObject} is leaving`, { showNow: true });
}
}
@@ -171,7 +296,7 @@ function saveNodeDetails() {
console.log("Request Body: ", reqBody);
const Http = new XMLHttpRequest();
const url='/nodes/'+nodeId;
const url = '/nodes/' + nodeId;
Http.open("PUT", url);
Http.setRequestHeader("Content-Type", "application/json");
Http.send(JSON.stringify(reqBody));
@@ -181,15 +306,17 @@ function saveNodeDetails() {
console.log(Http.status);
console.log(responseObject);
createToast(`Node Updated!`);
location.reload();
}
}
function addNewSystem(systemName) {
function addNewSystem() {
const nodeId = document.getElementById("nodeId").value;
const systemMode = document.getElementById(`${systemName}_systemMode`).value;
const inputSystemFreqs = $(`[id^="${systemName}_systemFreq_"]`);
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){
for (const inputFreq of inputSystemFreqs) {
systemFreqs.push(inputFreq.value);
}
@@ -201,13 +328,13 @@ function addNewSystem(systemName) {
console.log("Request Body: ", reqBody);
const Http = new XMLHttpRequest();
const url='/nodes/'+nodeId+"/systems";
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 = JSON.parse(Http.responseText)
const responseObject = Http.responseText
console.log(Http.status);
console.log(responseObject);
createToast(`${systemName} Added!`);
@@ -218,9 +345,9 @@ function addNewSystem(systemName) {
function updateSystem(systemName) {
const nodeId = document.getElementById("nodeId").value;
const systemMode = document.getElementById(`${systemName}_systemMode`).value;
const inputSystemFreqs = $(`[id^="${systemName}_systemFreq_"]`);
const inputSystemFreqs = $(`[id^="${systemName}_systemFreq_"]`);
let systemFreqs = [];
for (const inputFreq of inputSystemFreqs){
for (const inputFreq of inputSystemFreqs) {
systemFreqs.push(inputFreq.value);
}
@@ -232,13 +359,13 @@ function updateSystem(systemName) {
console.log("Request Body: ", reqBody);
const Http = new XMLHttpRequest();
const url='/nodes/'+nodeId+"/systems";
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 = JSON.parse(Http.responseText)
const responseObject = Http.responseText;
console.log(Http.status);
console.log(responseObject);
createToast(`${systemName} Updated!`);
@@ -246,6 +373,28 @@ function updateSystem(systemName) {
}
}
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() {
}