Implement functioning method to update systems on web app

This commit is contained in:
Logan Cusano
2023-07-16 22:30:18 -04:00
parent 5428ac6144
commit 318ee7bf91
5 changed files with 113 additions and 19 deletions

View File

@@ -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);
});

View File

@@ -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 });
});
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -1,5 +1,5 @@
<div class="modal fade" id="updateSystemModal_<%=system.replaceAll(" ", "_")%>" tabindex="-1" aria-labelledby="updateSystemModal_<%=system.replaceAll(" ", "_")%>"
aria-hidden="true">
aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
@@ -10,16 +10,20 @@
<div class="card mb-4">
<div class="card-body">
<form>
<div class="row gx-3 mb-3">
<label class="small mb-1 fs-6" for="systemName">System Name</label>
<input class="form-control" id="systemName" type="text" value="<%= system %>"></input>
</div>
<div class="row gx-3 mb-3" id="frequencyRow_<%=system.replaceAll(" ", "_")%>">
<label class="small mb-1 fs-6" for="nodeFreq">Frequencies</label>
<label class="small mb-1 fs-6" for="systemFreq">Frequencies</label>
<% for(const frequency of frequencies) { %>
<div class="col-md-6 mb-1">
<div class="col-md-6 mb-1" id="<%=system%>_systemFreqRow_<%=frequency%>">
<div class="row px-1">
<div class="col-10">
<input class="form-control" id="nodeFreq" type="text" value="<%= frequency %>"></input>
<input class="form-control" id="<%=system%>_systemFreq_<%=frequency%>" type="text" value="<%= frequency %>"></input>
</div>
<div class="col-2">
<a class="align-middle float-left" href="#"><i class="bi bi-x-circle text-black"></i></a>
<a class="align-middle float-left" href="#" onclick="removeFrequencyInput('<%=system%>_systemFreqRow_<%=frequency%>')"><i class="bi bi-x-circle text-black"></i></a>
</div>
</div>
</div>
@@ -29,9 +33,9 @@
<hr>
<div class="row gx-3 mb-3">
<div class="col-md-6">
<label class="small mb-1 fs-6" for="modeSelect">Mode</label>
<label class="small mb-1 fs-6" for="<%=system%>_systemMode">Mode</label>
<br>
<select class="custom-select" id="modeSelect">
<select class="custom-select" id="<%=system%>_systemMode">
<option value="<%= node.nearbySystems[system].mode %>" selected><span class="text-uppercase"><%= node.nearbySystems[system].mode %></span></option>
<% if(node.nearbySystems[system].mode == "p25") { %>
<option value="nbfm">NBFM</option>
@@ -46,8 +50,8 @@
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal" onclick="location.reload()">Close</button>
<button type="button" class="btn btn-primary" onclick="updateSystem('<%=system%>')">Save changes</button>
</div>
</div>
</div>