From 0f114066a66e29fb24dc3149b18fcacdb00c1537 Mon Sep 17 00:00:00 2001 From: Logan Cusano Date: Sun, 16 Jul 2023 22:30:18 -0400 Subject: [PATCH] Implement functioning method to update systems on web app --- Client/controllers/clientController.js | 15 +++++-- Server/controllers/nodesController.js | 41 +++++++++++++++++ Server/public/res/js/node.js | 49 ++++++++++++++++++--- Server/routes/nodes.js | 5 ++- Server/views/partials/modifySystemModal.ejs | 22 +++++---- 5 files changed, 113 insertions(+), 19 deletions(-) diff --git a/Client/controllers/clientController.js b/Client/controllers/clientController.js index 8d02999..2101d44 100644 --- a/Client/controllers/clientController.js +++ b/Client/controllers/clientController.js @@ -94,10 +94,12 @@ exports.checkConfig = async function checkConfig() { } /** Check in with the server - * If the bot has a saved ID, check in with the server to update any information or just check back in + * If the bot has a saved ID, check in with the server to get any updated information or just check back in * If the bot does not have a saved ID, it will attempt to request a new ID from the server + * + * @param {boolean} init If set to true, the client will update the server to it's config, instead of taking the server's config */ -exports.checkIn = async () => { +exports.checkIn = async (init = false) => { let reqOptions; await this.checkConfig(); runningClientConfig.online = true; @@ -134,7 +136,8 @@ exports.checkIn = async () => { } else { // ID is in the config, checking in with the server - reqOptions = new requestOptions("/nodes/nodeCheckIn", "POST"); + if (init) reqOptions = new requestOptions(`/nodes/${runningClientConfig.id}`, "PUT"); + else reqOptions = new requestOptions(`/nodes/nodeCheckIn/${runningClientConfig.id}`, "POST"); sendHttpRequest(reqOptions, JSON.stringify(runningClientConfig), (responseObject) => { log.DEBUG("Check In Respose: ", responseObject); // Check if the server responded @@ -178,7 +181,8 @@ exports.requestCheckIn = async (req, res) => { * This is the endpoint wrapper to get the presets object */ exports.getPresets = async (req, res) => { - return res.status(200).json(getPresets()); + runningClientConfig.nearbySystems = getPresets(); + return res.status(200).json(runningClientConfig.nearbySystems); } /** Controller for the /client/updatePreset endpoint @@ -187,6 +191,7 @@ exports.getPresets = async (req, res) => { exports.updatePreset = async (req, res) => { checkBodyForPresetFields(req, res, () => { updatePreset(req.body.systemName, () => { + runningClientConfig.nearbySystems = getPresets(); return res.sendStatus(200); }, {frequencies: req.body.frequencies, mode: req.body.mode, trunkFile: req.body.trunkFile}); }) @@ -198,6 +203,7 @@ exports.updatePreset = async (req, res) => { exports.addNewPreset = async (req, res) => { checkBodyForPresetFields(req, res, () => { addNewPreset(req.body.systemName, req.body.frequencies, req.body.mode, () => { + runningClientConfig.nearbySystems = getPresets(); return res.sendStatus(200); }, req.body.trunkFile); }); @@ -210,6 +216,7 @@ exports.removePreset = async (req, res) => { checkBodyForPresetFields(req, res, () => { if (!req.body.systemName) return res.status("500").json({"message": "You must specify a system name to delete, this must match exactly to how the system name is saved."}) removePreset(req.body.systemName, () => { + runningClientConfig.nearbySystems = getPresets(); return res.sendStatus(200); }, req.body.trunkFile); }); diff --git a/Server/controllers/nodesController.js b/Server/controllers/nodesController.js index 3012067..63588a6 100644 --- a/Server/controllers/nodesController.js +++ b/Server/controllers/nodesController.js @@ -8,6 +8,7 @@ const { sendHttpRequest, requestOptions } = require("../utilities/httpRequests.j const { nodeObject } = require("../utilities/recordHelper.js"); const refreshInterval = process.env.NODE_MONITOR_REFRESH_INTERVAL ?? 1200000; +const digitalModes = ['p25']; /** * Check in with a singular node, mark it offline if it's offline and @@ -116,6 +117,44 @@ exports.getNodeInfo = async (req, res) => { }) } +/** Updates a specific system/preset on a given node + * + * @param {*} req Default express req from router + * @param {*} res Defualt express res from router + * @param {*} req.params.nodeId The Node ID to update the preset/system on + * @param {*} req.body.systemName The name of the system to update + * @param {*} req.body.mode The radio mode of the preset to + * @param {*} req.body.frequencies The frequencies of the preset + * @param {*} req.body.trunkFile The trunk file to use for digital stations + */ +exports.updateNodeSystem = async (req, res) => { + if (!req.params.nodeId) return res.status(400).json("No id specified"); + if (!req.body.systemName) return res.status(400).json("No system specified"); + log.DEBUG("Updating system for node: ", req.params.nodeId, req.body); + getNodeInfoFromId(req.params.nodeId, (node) => { + const reqOptions = new requestOptions("/client/updatePreset", "POST", node.ip, node.port); + const reqBody = { + 'systemName': req.body.systemName, + 'mode': req.body.mode, + 'frequencies': req.body.frequencies, + } + if(digitalModes.includes(req.body.mode)) reqBody['trunkFile'] = req.body.trunkFile ?? 'none' + + log.DEBUG("Request body for updating node: ", reqBody, reqOptions); + sendHttpRequest(reqOptions, JSON.stringify(reqBody), async (responseObj) => { + if(responseObj){ + // Good + log.DEBUG("Response from updating node: ", reqBody, responseObj); + return res.sendStatus(200) + } else { + // Bad + log.DEBUG("No Response from updating Node"); + return res.status(400).json("No Response from updating Node, could be offline"); + } + }) + }) +} + /** Updates the information received from the client based on ID * * @param {*} req Default express req from router @@ -171,11 +210,13 @@ exports.updateExistingNode = async = (req, res) => { if (!nodeInfo) { log.WARN("No existing node found with this ID, adding node: ", checkInObject); addNewNode(checkInObject, (newNode) => { + this.requestNodeCheckIn(checkInObject.id); return res.status(201).json({ "updatedKeys": newNode }); }); } else { updateNodeInfo(checkInObject, () => { + this.requestNodeCheckIn(checkInObject.id); return res.status(202).json({ "updatedKeys": checkInObject }); }); } diff --git a/Server/public/res/js/node.js b/Server/public/res/js/node.js index e439c30..e4e5274 100644 --- a/Server/public/res/js/node.js +++ b/Server/public/res/js/node.js @@ -1,4 +1,11 @@ -function addFrequencyInput(system){ +/** + * 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'); @@ -9,6 +16,7 @@ function addFrequencyInput(system){ 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'); @@ -17,7 +25,7 @@ function addFrequencyInput(system){ var input = document.createElement('input'); input.classList.add('form-control'); - input.id = 'nodeFreq'; + input.id = `${system}_systemFreq_${inputId}`; input.type = 'text'; var childColInput = document.createElement('div'); @@ -33,6 +41,7 @@ function addFrequencyInput(system){ 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); @@ -169,22 +178,52 @@ function saveNodeDetails() { Http.send(JSON.stringify(reqBody)); Http.onloadend = (e) => { - const responseObject = JSON.parse(Http.responseText) + const responseObject = JSON.parse(Http.responseText); console.log(Http.status); console.log(responseObject); createToast(`Node Updated!`); } - } function addNewSystem() { } -function updateSystem() { +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 = JSON.parse(Http.responseText) + console.log(Http.status); + console.log(responseObject); + createToast(`${systemName} Updated!`); + } } function requestNodeUpdate() { +} + +function removeFrequencyInput(elementId) { + const element = document.getElementById(elementId); + element.remove(); } \ No newline at end of file diff --git a/Server/routes/nodes.js b/Server/routes/nodes.js index 3a2b7d2..d110343 100644 --- a/Server/routes/nodes.js +++ b/Server/routes/nodes.js @@ -12,6 +12,9 @@ router.get('/:nodeId', nodesController.getNodeInfo); // Update an existing node router.put('/:nodeId', nodesController.updateExistingNode); +// Update an existing node's system +router.put('/:nodeId/systems', nodesController.updateNodeSystem); + // TODO Need to authenticate this request /* POST a new node to the server * @@ -28,7 +31,7 @@ router.put('/:nodeId', nodesController.updateExistingNode); router.post('/newNode', nodesController.newNode); // TODO Need to authenticate this request -// Client checkin with the server to update information +// Client checkin with the server to update client information router.post('/nodeCheckIn/:nodeId', nodesController.nodeCheckIn); // Request a node to check in with the server diff --git a/Server/views/partials/modifySystemModal.ejs b/Server/views/partials/modifySystemModal.ejs index d24e83f..88ae381 100644 --- a/Server/views/partials/modifySystemModal.ejs +++ b/Server/views/partials/modifySystemModal.ejs @@ -1,5 +1,5 @@