Compare commits
4 Commits
c0927601b9
...
31de3a040d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31de3a040d | ||
|
|
318ee7bf91 | ||
|
|
5428ac6144 | ||
|
|
e27dd9d9cb |
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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
|
||||
@@ -110,20 +111,96 @@ exports.newNode = async (req, res) => {
|
||||
* @param {*} res Defualt express res from router
|
||||
*/
|
||||
exports.getNodeInfo = async (req, res) => {
|
||||
if (!req.query.id) return res.status(400).json("No id specified");
|
||||
getNodeInfoFromId(req.query.id, (nodeInfo) => {
|
||||
if (!req.params.id) return res.status(400).json("No id specified");
|
||||
getNodeInfoFromId(req.params.id, (nodeInfo) => {
|
||||
res.status(200).json(nodeInfo);
|
||||
})
|
||||
}
|
||||
|
||||
/** Adds 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 add the preset/system to
|
||||
* @param {*} req.body.systemName The name of the system to add
|
||||
* @param {*} req.body.mode The radio mode of the preset
|
||||
* @param {*} req.body.frequencies The frequencies of the preset
|
||||
* @param {*} req.body.trunkFile The trunk file to use for digital stations
|
||||
*/
|
||||
exports.addNodeSystem = 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("Adding system for node: ", req.params.nodeId, req.body);
|
||||
getNodeInfoFromId(req.params.nodeId, (node) => {
|
||||
const reqOptions = new requestOptions("/client/addPreset", "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 adding node system: ", reqBody, reqOptions);
|
||||
sendHttpRequest(reqOptions, JSON.stringify(reqBody), async (responseObj) => {
|
||||
if(responseObj){
|
||||
// Good
|
||||
log.DEBUG("Response from adding node system: ", reqBody, responseObj);
|
||||
return res.sendStatus(200)
|
||||
} else {
|
||||
// Bad
|
||||
log.DEBUG("No Response from adding Node system");
|
||||
return res.status(400).json("No Response from adding Node, could be offline");
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/** 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 system: ", reqBody, responseObj);
|
||||
return res.sendStatus(200)
|
||||
} else {
|
||||
// Bad
|
||||
log.DEBUG("No Response from updating Node system");
|
||||
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
|
||||
* @param {*} res Defualt express res from router
|
||||
*/
|
||||
exports.nodeCheckIn = async (req, res) => {
|
||||
if (!req.body.id) return res.status(400).json("No id specified");
|
||||
getNodeInfoFromId(req.body.id, (nodeInfo) => {
|
||||
exports.updateExistingNode = async = (req, res) => {
|
||||
if (!req.params.nodeId) return res.status(400).json("No id specified");
|
||||
getNodeInfoFromId(req.params.nodeId, (nodeInfo) => {
|
||||
let checkInObject = {};
|
||||
// Convert the online status to a boolean to be worked with
|
||||
log.DEBUG("REQ Body: ", req.body);
|
||||
@@ -163,25 +240,45 @@ exports.nodeCheckIn = async (req, res) => {
|
||||
// If no changes are made tell the client
|
||||
if (!isObjectUpdated) return res.status(200).json("No keys updated");
|
||||
|
||||
log.INFO("Updating the following keys for ID: ", req.body.id, checkInObject);
|
||||
log.INFO("Updating the following keys for ID: ", req.params.nodeId, checkInObject);
|
||||
|
||||
checkInObject._id = req.body.id;
|
||||
checkInObject._id = req.params.nodeId;
|
||||
checkInObject = new nodeObject(checkInObject);
|
||||
|
||||
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 });
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** Allows the bots to check in and get any updates from the server
|
||||
*
|
||||
* @param {*} req Default express req from router
|
||||
* @param {*} res Defualt express res from router
|
||||
*/
|
||||
exports.nodeCheckIn = async (req, res) => {
|
||||
if (!req.params.nodeId) return res.status(400).json("No id specified");
|
||||
getNodeInfoFromId(req.params.nodeId, (nodeInfo) => {
|
||||
if (!nodeInfo.online) {
|
||||
nodeInfo.online = true;
|
||||
updateNodeInfo(nodeInfo, () => {
|
||||
return res.status(200).json(nodeInfo);
|
||||
})
|
||||
}
|
||||
else return res.status(200).json(nodeInfo);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests a specific node to check in with the server, if it's online
|
||||
*
|
||||
|
||||
@@ -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);
|
||||
@@ -78,11 +87,12 @@ function createToast(notificationMessage){
|
||||
document.getElementById("toastZone").appendChild(wrapperDiv);
|
||||
|
||||
$('.toast').toast('show');
|
||||
return $('.toast');
|
||||
}
|
||||
|
||||
function sendNodeHeartbeat(nodeId){
|
||||
const Http = new XMLHttpRequest();
|
||||
const url='/nodes/'+nodeId;
|
||||
const url='/nodes/nodeCheckIn/'+nodeId;
|
||||
Http.open("GET", url);
|
||||
Http.send();
|
||||
|
||||
@@ -139,5 +149,109 @@ function leaveServer(){
|
||||
console.log(Http.status);
|
||||
console.log(responseObject);
|
||||
createToast(`${responseObject} is leaving`);
|
||||
setTimeout(() => {}, 45000);
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
'online': true
|
||||
}
|
||||
|
||||
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!`);
|
||||
}
|
||||
}
|
||||
|
||||
function addNewSystem(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("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(`${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 = JSON.parse(Http.responseText)
|
||||
console.log(Http.status);
|
||||
console.log(responseObject);
|
||||
createToast(`${systemName} Updated!`);
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
function requestNodeUpdate() {
|
||||
|
||||
}
|
||||
|
||||
function removeFrequencyInput(elementId) {
|
||||
const element = document.getElementById(elementId);
|
||||
element.remove();
|
||||
}
|
||||
@@ -5,6 +5,19 @@ const nodesController = require('../controllers/nodesController');
|
||||
/* GET nodes the server knows */
|
||||
router.get('/', nodesController.listAllNodes);
|
||||
|
||||
// TODO Need to authenticate this request
|
||||
/* GET the information the server has on a particular node */
|
||||
router.get('/:nodeId', nodesController.getNodeInfo);
|
||||
|
||||
// Update an existing node
|
||||
router.put('/:nodeId', nodesController.updateExistingNode);
|
||||
|
||||
// Add a system to an existing node
|
||||
router.post('/:nodeId/systems', nodesController.addNodeSystem);
|
||||
|
||||
// Update a system on an existing node
|
||||
router.put('/:nodeId/systems', nodesController.updateNodeSystem);
|
||||
|
||||
// TODO Need to authenticate this request
|
||||
/* POST a new node to the server
|
||||
*
|
||||
@@ -21,14 +34,10 @@ router.get('/', nodesController.listAllNodes);
|
||||
router.post('/newNode', nodesController.newNode);
|
||||
|
||||
// TODO Need to authenticate this request
|
||||
/* GET the information the server has on a particular node */
|
||||
router.get('/nodeInfo', nodesController.getNodeInfo);
|
||||
|
||||
// TODO Need to authenticate this request
|
||||
// Client checkin with the server to update information
|
||||
router.post('/nodeCheckIn', nodesController.nodeCheckIn);
|
||||
// Client checkin with the server to update client information
|
||||
router.post('/nodeCheckIn/:nodeId', nodesController.nodeCheckIn);
|
||||
|
||||
// Request a node to check in with the server
|
||||
router.get('/:nodeId', nodesController.requestNodeCheckIn);
|
||||
router.get('/nodeCheckIn/:nodeId', nodesController.requestNodeCheckIn);
|
||||
|
||||
module.exports = router;
|
||||
|
||||
@@ -9,29 +9,30 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="col-md-12 pt-2">
|
||||
<label class="small mb-1" for="nodeStatus">Online Status:</label>
|
||||
<% if(node.online){%> <span class="badge badge-soft-success mb-0 align-middle fs-6" id="nodeStatus">Online</span>
|
||||
<% } else {%> <span class="badge badge-soft-danger mb-0 align-middle fs-6">Offline</span>
|
||||
<% } %>
|
||||
<br>
|
||||
<div class="py-2"></div>
|
||||
<!-- Join Server button-->
|
||||
<a type="button" class="btn btn-info text-white<% if(!node.online) { %>disabled<% } %>" data-bs-toggle="modal" data-bs-target="#joinModal" href="#">Join Server</a>
|
||||
<!-- Leave Server button -->
|
||||
<a type="button" class="btn btn-danger <% if(!node.online) { %>disabled<% } %>" href="#" onclick="leaveServer()">Leave Server</a>
|
||||
<!-- Checkin with client button -->
|
||||
<a type="button" class="btn btn-secondary" href="#" onclick="sendNodeHeartbeat('<%=node.id%>')">Check-in with Node</a>
|
||||
<!-- Update Client button -->
|
||||
<a type="button" class="btn btn-warning" href="#" onclick="requestNodeUpdate('<%=node.id%>')">Update Node</a>
|
||||
</div>
|
||||
<hr>
|
||||
<form>
|
||||
<div class="row gx-3 mb-3">
|
||||
<div class="">
|
||||
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="small mb-1" for="nodeId">Node ID (this is the assigned Node ID and cannot be
|
||||
changed)</label>
|
||||
<input class="form-control" id="nodeId" type="text" value="<%=node.id%>" disabled></input>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="small mb-1" for="nodeStatus">Online Status:</label>
|
||||
<% if(node.online){%> <span class="badge badge-soft-success mb-0 align-middle fs-6" id="nodeStatus">Online</span>
|
||||
<% } else {%> <span class="badge badge-soft-danger mb-0 align-middle fs-6">Offline</span>
|
||||
<% } %>
|
||||
<hr>
|
||||
<!-- Join Server button-->
|
||||
<a type="button" class="btn btn-info <% if(!node.online) { %>disabled<% } %>" data-bs-toggle="modal" data-bs-target="#joinModal" href="#">Join Server</a>
|
||||
<!-- Leave Server button -->
|
||||
<a type="button" class="btn btn-danger <% if(!node.online) { %>disabled<% } %>" href="#" onclick="leaveServer()">Leave Server</a>
|
||||
<!-- Checkin with client button -->
|
||||
<a type="button" class="btn btn-secondary" href="#" onclick="sendNodeHeartbeat('<%=node.id%>')">Check-in with Node</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row gx-3 mb-3">
|
||||
@@ -112,7 +113,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<% // Update system modal %>
|
||||
<%- include("partials/modifySystemModal.ejs", {'system': system, 'frequencies': node.nearbySystems[system].frequencies}) %>
|
||||
<%- include("partials/modifySystemModal.ejs", {'system': system, 'frequencies': node.nearbySystems[system].frequencies, 'mode': node.nearbySystems[system].mode}) %>
|
||||
<% } %>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -122,34 +123,17 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- Save changes button-->
|
||||
<button class="btn btn-primary <% if(!node.online) { %>disabled<% } %>" type="button">Save changes</button>
|
||||
<button class="btn btn-primary <% if(!node.online) { %>disabled<% } %>" type="button" onclick="saveNodeDetails()">Save changes</button>
|
||||
<!-- Button trigger modal -->
|
||||
<button type="button" class="btn btn-primary float-right <% if(!node.online) { %>disabled<% } %>" data-bs-toggle="modal"
|
||||
data-bs-target="#newSystemModal">Add New System</button>
|
||||
data-bs-target="#updateSystemModal_New_System">Add New System</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% // new System Modal %>
|
||||
<div class="modal fade" id="newSystemModal" tabindex="-1" aria-labelledby="newSystemModal" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="newSystemModal">Add a New System</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
...
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%- include('partials/joinModal.ejs', {'nearbySystems': node.nearbySystems}) %>
|
||||
<%- include("partials/modifySystemModal.ejs", {'system': "New System", 'frequencies': [], 'mode': ''}) %>
|
||||
<%- include('partials/bodyEnd.ejs') %>
|
||||
<script src="/res/js/node.js"></script>
|
||||
<%- include('partials/htmlFooter.ejs') %>
|
||||
@@ -1,25 +1,29 @@
|
||||
<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">
|
||||
<h1 class="modal-title fs-5" id="updateSystemModal_<%=system.replaceAll(" ", "_")%>">Update <%=system%></h1>
|
||||
<h1 class="modal-title fs-5" id="updateSystemModal_<%=system.replaceAll(" ", "_")%>"><%if (!system == "New System") {%>Update<%} else {%>Add a<%}%> <%=system%></h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<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="<%if (!system == "New System") {%><%= system %><%} else {%>Local Radio 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,15 +33,18 @@
|
||||
<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">
|
||||
<option value="<%= node.nearbySystems[system].mode %>" selected><span class="text-uppercase"><%= node.nearbySystems[system].mode %></span></option>
|
||||
<% if(node.nearbySystems[system].mode == "p25") { %>
|
||||
<select class="custom-select" id="<%=system%>_systemMode">
|
||||
<option value="<%= mode ?? 'select' %>" selected><span class="text-uppercase"><%= mode ?? 'Select' %></span></option>
|
||||
<% if(mode == "p25") { %>
|
||||
<option value="nbfm">NBFM</option>
|
||||
<% } else if (node.nearbySystems[system].mode == "nbfm") { %>
|
||||
<% } else if (mode == "nbfm") { %>
|
||||
<option value="p25">P25</option>
|
||||
<% } %>
|
||||
<% } else { %>
|
||||
<option value="nbfm">NBFM</option>
|
||||
<option value="p25">P25</option>
|
||||
<%}%>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -46,8 +53,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" data-bs-dismiss="modal" <%if(!system == "New System") {%>onclick="updateSystem('<%=system%>')"<%} else {%>onclick="addNewSystem('<%=system%>')"<%}%>>Save changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,10 +12,6 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center">
|
||||
<div>
|
||||
<img src="https://bootdey.com/img/Content/avatar/avatar1.png" alt=""
|
||||
class="avatar-md rounded-circle img-thumbnail" />
|
||||
</div>
|
||||
<div class="flex-1 ms-3">
|
||||
<h5 class="font-size-16 mb-1"><a href="/node/<%=node.id%>" class="text-dark">
|
||||
<%= node.name %>
|
||||
@@ -36,20 +32,15 @@
|
||||
<%= node.ip %>:<%= node.port %>
|
||||
</a>
|
||||
</p>
|
||||
<hr>
|
||||
<p class="text-muted mb-0">
|
||||
<div class="dropdown">
|
||||
<i class="bi bi-broadcast-pin font-size-15 align-middle pe-2 text-primary"></i>
|
||||
<a class="dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Nearby Systems
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<i class="bi bi-broadcast-pin font-size-15 pe-2 text-primary"></i>
|
||||
Nearby Systems:
|
||||
<ul>
|
||||
<% for(const system in node.nearbySystems){ %>
|
||||
<li>
|
||||
<%= system %>
|
||||
</li>
|
||||
<% } %>
|
||||
<li><%= system %></li>
|
||||
<% } %>
|
||||
</ul>
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user