Add input validation to SpiriLink
This commit is contained in:
parent
7a804b8ba6
commit
f74c3f6e1e
|
@ -32,26 +32,26 @@ enabled = true;
|
||||||
// Runs the initPage when the document is loaded
|
// Runs the initPage when the document is loaded
|
||||||
document.onload = InitPage();
|
document.onload = InitPage();
|
||||||
// Save file button
|
// Save file button
|
||||||
document.getElementById("save").addEventListener("click", SaveSettings);
|
document.getElementById("save").addEventListener("click", saveSettings);
|
||||||
|
|
||||||
// This attempts to read the conf file, if it exists, then it will parse it and fill out the table
|
// This attempts to read the conf file, if it exists, then it will parse it and fill out the table
|
||||||
// if it fails then the values are loaded with defaults.
|
// if it fails then the values are loaded with defaults.
|
||||||
function InitPage() {
|
function InitPage() {
|
||||||
cockpit.script(scriptLocation + "cockpitScript.sh -v")
|
cockpit.script(scriptLocation + "cockpitScript.sh -v")
|
||||||
.then((content) => version.innerHTML=content)
|
.then((content) => version.innerHTML=content)
|
||||||
.catch(error => Fail(error));
|
.catch(error => displayFail(error));
|
||||||
cockpit.script(scriptLocation + "cockpitScript.sh -u")
|
cockpit.script(scriptLocation + "cockpitScript.sh -u")
|
||||||
.then(function(content) {
|
.then(function(content) {
|
||||||
ipsubnet1.innerHTML=content;
|
ipsubnet1.innerHTML=content;
|
||||||
ipsubnet2.innerHTML=content;
|
ipsubnet2.innerHTML=content;
|
||||||
})
|
})
|
||||||
.catch(error => Fail(error));
|
.catch(error => displayFail(error));
|
||||||
|
|
||||||
file_location.innerHTML = confLocation + "main.conf";
|
file_location.innerHTML = confLocation + "main.conf";
|
||||||
|
|
||||||
cockpit.file(confLocation + "main.conf")
|
cockpit.file(confLocation + "main.conf")
|
||||||
.read().then((content, tag) => SuccessReadFile(content))
|
.read().then((content, tag) => SuccessReadFile(content))
|
||||||
.catch(error => FailureReadFile(error));
|
.catch(error => failureReadFile(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getValueByKey(text, sectionName, sectionLength, key) {
|
function getValueByKey(text, sectionName, sectionLength, key) {
|
||||||
|
@ -158,7 +158,7 @@ function SuccessReadFile(content) {
|
||||||
var currentbaudRate = getValueByKey(content, "[UartEndpoint alpha]", 2, "Baud");
|
var currentbaudRate = getValueByKey(content, "[UartEndpoint alpha]", 2, "Baud");
|
||||||
cockpit.script(scriptLocation + "cockpitScript.sh -s")
|
cockpit.script(scriptLocation + "cockpitScript.sh -s")
|
||||||
.then((content) => AddDropDown(fmuDevice, content.split("\n"), currentfmuDevice))
|
.then((content) => AddDropDown(fmuDevice, content.split("\n"), currentfmuDevice))
|
||||||
.catch(error => Fail(error));
|
.catch(error => displayFail(error));
|
||||||
AddDropDown(baudrate, baudRateArray, currentbaudRate);
|
AddDropDown(baudrate, baudRateArray, currentbaudRate);
|
||||||
|
|
||||||
//UDP Telemetry
|
//UDP Telemetry
|
||||||
|
@ -225,7 +225,7 @@ function SuccessReadFile(content) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
FailureReadFile(e);
|
failureReadFile(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,11 +249,11 @@ function AddDropDown(box, theArray, defaultValue) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
Fail(e)
|
displayFail(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function FailureReadFile(error) {
|
function failureReadFile(error) {
|
||||||
// Display error message
|
// Display error message
|
||||||
console.log("Error : " + error.message);
|
console.log("Error : " + error.message);
|
||||||
output.innerHTML = "Error : " + error.message;
|
output.innerHTML = "Error : " + error.message;
|
||||||
|
@ -267,7 +267,7 @@ function FailureReadFile(error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function SaveSettings() {
|
function saveSettings() {
|
||||||
|
|
||||||
//lets do some validation
|
//lets do some validation
|
||||||
|
|
||||||
|
@ -306,7 +306,7 @@ function SaveSettings() {
|
||||||
//open the file for writing, and callback function for modification
|
//open the file for writing, and callback function for modification
|
||||||
cockpit.file(confLocation + "main.conf")
|
cockpit.file(confLocation + "main.conf")
|
||||||
.read().then((content, tag) => SuccessReadforSaveFile(content))
|
.read().then((content, tag) => SuccessReadforSaveFile(content))
|
||||||
.catch(error => FailureReadFile(error));
|
.catch(error => failureReadFile(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
function SuccessReadforSaveFile(content) {
|
function SuccessReadforSaveFile(content) {
|
||||||
|
@ -335,23 +335,23 @@ function SuccessReadforSaveFile(content) {
|
||||||
content = setValueByKey(content, "[UartEndpoint alpha]",2, "Baud", baudrate.value )
|
content = setValueByKey(content, "[UartEndpoint alpha]",2, "Baud", baudrate.value )
|
||||||
|
|
||||||
cockpit.file(confLocation + "main.conf", { superuser : "try" }).replace(content)
|
cockpit.file(confLocation + "main.conf", { superuser : "try" }).replace(content)
|
||||||
.then(Success)
|
.then(displaySuccess)
|
||||||
.catch(Fail);
|
.catch(displayFail);
|
||||||
|
|
||||||
cockpit.spawn(["systemctl", "restart", "mavlink-router"], { superuser : "try" });
|
cockpit.spawn(["systemctl", "restart", "mavlink-router"], { superuser : "try" });
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
FailureReadFile(e);
|
failureReadFile(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Success() {
|
function displaySuccess() {
|
||||||
result.style.color = "green";
|
result.style.color = "green";
|
||||||
result.innerHTML = "Success, mavlink-router restarting...";
|
result.innerHTML = "Success, mavlink-router restarting...";
|
||||||
setTimeout(() => result.innerHTML = "", 5000);
|
setTimeout(() => result.innerHTML = "", 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Fail(error) {
|
function displayFail(error) {
|
||||||
result.style.color = "red";
|
result.style.color = "red";
|
||||||
result.innerHTML = error.message;
|
result.innerHTML = error.message;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<title>SpiriLink Configuration</title>
|
<title>SpiriLink Configuration</title>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<link href="../base1/bootstrap.min.css" type="text/css" rel="stylesheet">
|
<link href="../base1/bootstrap.min.css" type="text/css" rel="stylesheet">
|
||||||
<link href="../base1/style.css" type="text/css" rel="stylesheet">
|
<!-- <link href="../base1/style.css" type="text/css" rel="stylesheet"> -->
|
||||||
<script src="../base1/cockpit.js"></script>
|
<script src="../base1/cockpit.js"></script>
|
||||||
<script src="../base1/jquery-3.7.1.min.js"></script>
|
<script src="../base1/jquery-3.7.1.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
@ -20,163 +20,177 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Save Button -->
|
<form class="row" id="spiriLinkForm" action="javascript:void(0);" novalidate>
|
||||||
<div class="row mt-4 mb-4">
|
<!-- Save Button -->
|
||||||
<div class="col-6">
|
<div class="row mt-2 mb-3">
|
||||||
<button class="btn btn-primary" id="save">Save/Update</button>
|
<div class="col-6">
|
||||||
|
<button class="btn btn-primary" id="save">Save/Update</button>
|
||||||
|
</div>
|
||||||
|
<div class="col-6 d-flex justify-content-end">
|
||||||
|
<button id="applyEncryptionFile" class="btn btn-primary">Apply Encryption File from Base Station</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 d-flex justify-content-end">
|
|
||||||
<button id="applyEncryptionFile" class="btn btn-primary">Apply Encryption File from Base Station</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<pre id="result" class="mt-3 mb-3"></pre>
|
<pre id="result" class="ms-1"></pre>
|
||||||
|
|
||||||
<!-- WiFi Configuration -->
|
<!-- WiFi Configuration -->
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<img src="assets/icons/settings_wifi.svg" class="me-2"/><span>WiFi Configuration</span>
|
<img src="assets/icons/settings_wifi.svg" class="me-2"/><span>WiFi Configuration</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="wifiChannel" class="form-label">WiFi Channel</label>
|
<label for="wifiChannel" class="form-label">WiFi Channel</label>
|
||||||
<select id="wifiChannel" class="form-select"></select>
|
<select id="wifiChannel" class="form-select"></select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="wifiRegion" class="form-label">WiFi Region</label>
|
<label for="wifiRegion" class="form-label">WiFi Region</label>
|
||||||
<select id="wifiRegion" class="form-select">
|
<select id="wifiRegion" class="form-select">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<label for="wifiTxPower" class="form-label">WiFi Tx Power (dBm * 100)</label>
|
<label for="wifiTxPower" class="form-label">WiFi Tx Power (dBm * 100)</label>
|
||||||
<input type="number" id="wifiTxPower" class="form-control"
|
<input type="number" id="wifiTxPower" class="form-control"
|
||||||
placeholder="e.g., 3000 for 30dBm">
|
placeholder="e.g., 3000 for 30dBm">
|
||||||
|
<div class="invalid-feedback">Must be an integer.</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Temperature Configuration -->
|
<!-- Temperature Configuration -->
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<img src="assets/icons/settings_temp.svg" class="me-2"/><span>Temperature Configuration</span>
|
<img src="assets/icons/settings_temp.svg" class="me-2"/><span>Temperature Configuration</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="tempInterval" class="form-label">Measurement Interval (s)</label>
|
<label for="tempInterval" class="form-label">Measurement Interval (s)</label>
|
||||||
<input type="number" id="tempInterval" class="form-control" value="10">
|
<input type="number" id="tempInterval" class="form-control" required>
|
||||||
</div>
|
<div class="invalid-feedback">Must be an integer.</div>
|
||||||
<div class="col-md-6">
|
</div>
|
||||||
<label for="tempWarning" class="form-label">Overheat Warning (°C)</label>
|
<div class="col-md-6">
|
||||||
<input type="number" id="tempWarning" class="form-control" value="60">
|
<label for="tempWarning" class="form-label">Overheat Warning (°C)</label>
|
||||||
|
<input type="number" id="tempWarning" class="form-control" step="0.1" required>
|
||||||
|
<div class="invalid-feedback">Must be a number with at most one decimal. </div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Drone Video Configuration -->
|
<!-- Drone Video Configuration -->
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<img src="assets/icons/settings_video.svg" class="me-2"/><span>Drone Video Configuration</span>
|
<img src="assets/icons/settings_video.svg" class="me-2"/><span>Drone Video Configuration</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<label for="droneVideoFwmark" class="form-label">FWMark</label>
|
<label for="droneVideoFwmark" class="form-label">FWMark</label>
|
||||||
<input type="number" id="droneVideoFwmark" class="form-control">
|
<input type="number" id="droneVideoFwmark" class="form-control" required>
|
||||||
</div>
|
<div class="invalid-feedback">Must be an integer.</div>
|
||||||
<div class="col-md-3">
|
</div>
|
||||||
<label for="droneVideoType" class="form-label">Connection Type</label>
|
<div class="col-md-3">
|
||||||
<select id="droneVideoType" class="form-select"></select>
|
<label for="droneVideoType" class="form-label">Connection Type</label>
|
||||||
</div>
|
<select id="droneVideoType" class="form-select" required></select>
|
||||||
<div class="col-md-3">
|
</div>
|
||||||
<label for="droneVideoIP" class="form-label">IP Address</label>
|
<div class="col-md-3">
|
||||||
<input type="text" id="droneVideoIP" class="form-control">
|
<label for="droneVideoIP" class="form-label">IP Address</label>
|
||||||
</div>
|
<input type="text" id="droneVideoIP" class="form-control" required>
|
||||||
<div class="col-md-3">
|
<div class="invalid-feedback">IP Address must be in the format xxx.xxx.xxx.xxx</div>
|
||||||
<label for="droneVideoPort" class="form-label">Port</label>
|
</div>
|
||||||
<input type="number" id="droneVideoPort" class="form-control">
|
<div class="col-md-3">
|
||||||
|
<label for="droneVideoPort" class="form-label">Port</label>
|
||||||
|
<input type="number" id="droneVideoPort" class="form-control" required>
|
||||||
|
<div class="invalid-feedback">Port must be between 1 and 65535</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Drone MAVLink Configuration -->
|
<!-- Drone MAVLink Configuration -->
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<img src="assets/icons/lan.svg" class="me-2"/><span>Drone MAVLink Configuration</span>
|
<img src="assets/icons/lan.svg" class="me-2"/><span>Drone MAVLink Configuration</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<label for="droneMavlinkFwmark" class="form-label">FWMark</label>
|
<label for="droneMavlinkFwmark" class="form-label">FWMark</label>
|
||||||
<input type="number" id="droneMavlinkFwmark" class="form-control">
|
<input type="number" id="droneMavlinkFwmark" class="form-control" required>
|
||||||
</div>
|
<div class="invalid-feedback">Must be an integer.</div>
|
||||||
<div class="col-md-3">
|
</div>
|
||||||
<label for="droneMavlinkType" class="form-label">Connection Type</label>
|
<div class="col-md-3">
|
||||||
<select id="droneMavlinkType" class="form-select"></select>
|
<label for="droneMavlinkType" class="form-label">Connection Type</label>
|
||||||
</div>
|
<select id="droneMavlinkType" class="form-select" required></select>
|
||||||
<div class="col-md-3">
|
</div>
|
||||||
<label for="droneMavlinkIP" class="form-label">IP Address</label>
|
<div class="col-md-3">
|
||||||
<input type="text" id="droneMavlinkIP" class="form-control">
|
<label for="droneMavlinkIP" class="form-label">IP Address</label>
|
||||||
</div>
|
<input type="text" id="droneMavlinkIP" class="form-control" required>
|
||||||
<div class="col-md-3">
|
<div class="invalid-feedback">IP Address must be in the format xxx.xxx.xxx.xxx</div>
|
||||||
<label for="droneMavlinkPort" class="form-label">Port</label>
|
</div>
|
||||||
<input type="number" id="droneMavlinkPort" class="form-control">
|
<div class="col-md-3">
|
||||||
|
<label for="droneMavlinkPort" class="form-label">Port</label>
|
||||||
|
<input type="number" id="droneMavlinkPort" class="form-control" required>
|
||||||
|
<div class="invalid-feedback">Port must be between 1 and 65535</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- MAVLink Configuration -->
|
<!-- MAVLink Configuration -->
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<img src="assets/icons/settings_ethernet.svg" class="me-2"/><span>MAVLink Settings</span>
|
<img src="assets/icons/settings_ethernet.svg" class="me-2"/><span>MAVLink Settings</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<label for="injectRssi" class="form-label">Inject RSSI</label>
|
<label for="injectRssi" class="form-label">Inject RSSI</label>
|
||||||
<input type="checkbox" id="injectRssi" class="form-check-input">
|
<input type="checkbox" id="injectRssi" class="form-check-input">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<label for="mavlinkSysId" class="form-label">System ID</label>
|
<label for="mavlinkSysId" class="form-label">System ID</label>
|
||||||
<input type="number" id="mavlinkSysId" class="form-control" required>
|
<input type="number" id="mavlinkSysId" class="form-control" min="1" max="255" required>
|
||||||
</div>
|
<div class="invalid-feedback">System ID must be between 1 and 255</div>
|
||||||
<div class="col-md-3">
|
</div>
|
||||||
<label for="mavlinkCompId" class="form-label">Component ID</label>
|
<div class="col-md-3">
|
||||||
<input type="number" id="mavlinkCompId" class="form-control">
|
<label for="mavlinkCompId" class="form-label">Component ID</label>
|
||||||
</div>
|
<input type="number" id="mavlinkCompId" class="form-control" min="1" max="255" required>
|
||||||
<div class="col-md-3">
|
<div class="invalid-feedback">Comp ID must be between 1 and 255</div>
|
||||||
<label for="mavlinkTcpPort" class="form-label">MAVLink TCP Port</label>
|
</div>
|
||||||
<input type="number" id="mavlinkTcpPort" class="form-control"
|
<div class="col-md-3">
|
||||||
placeholder="None if left blank">
|
<label for="mavlinkTcpPort" class="form-label">MAVLink TCP Port</label>
|
||||||
|
<input type="number" id="mavlinkTcpPort" class="form-control"
|
||||||
|
placeholder="None if left blank">
|
||||||
|
<div class="invalid-feedback">Port must be between 1 and 65535</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="spirilink.js"></script>
|
<script src="spirilink.js"></script>
|
||||||
|
|
|
@ -23,6 +23,7 @@ const mavlinkSysId = document.getElementById("mavlinkSysId");
|
||||||
const mavlinkCompId = document.getElementById("mavlinkCompId");
|
const mavlinkCompId = document.getElementById("mavlinkCompId");
|
||||||
const mavlinkTcpPort = document.getElementById("mavlinkTcpPort");
|
const mavlinkTcpPort = document.getElementById("mavlinkTcpPort");
|
||||||
|
|
||||||
|
const spiriLinkForm = document.getElementById("spiriLinkForm");
|
||||||
const output = document.getElementById("output");
|
const output = document.getElementById("output");
|
||||||
|
|
||||||
const wifiChannels = [
|
const wifiChannels = [
|
||||||
|
@ -74,7 +75,7 @@ function initPage() {
|
||||||
|
|
||||||
const inputs = document.querySelectorAll("input, select, textarea");
|
const inputs = document.querySelectorAll("input, select, textarea");
|
||||||
inputs.forEach(input => {
|
inputs.forEach(input => {
|
||||||
input.addEventListener("focus", clearResult);
|
input.addEventListener("focus", resetForm);
|
||||||
});
|
});
|
||||||
|
|
||||||
cockpit.file(confLocation)
|
cockpit.file(confLocation)
|
||||||
|
@ -85,6 +86,7 @@ function initPage() {
|
||||||
// Load configuration values from the configuration file
|
// Load configuration values from the configuration file
|
||||||
function successReadFile(content) {
|
function successReadFile(content) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// WiFi Configuration
|
// WiFi Configuration
|
||||||
// Remove surrounding quotes from wifi_region value if present
|
// Remove surrounding quotes from wifi_region value if present
|
||||||
const currentWifiChannel = getValueByKey(content, "common", "wifi_channel");
|
const currentWifiChannel = getValueByKey(content, "common", "wifi_channel");
|
||||||
|
@ -131,14 +133,69 @@ function successReadFile(content) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Log error message and display it
|
||||||
|
// TODO: Add more error handling for failed file reads
|
||||||
function failureReadFile(error) {
|
function failureReadFile(error) {
|
||||||
// Display error message
|
console.error("Error : " + error.message);
|
||||||
console.log("Error : " + error.message);
|
|
||||||
displayFail(error.message)
|
displayFail(error.message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate the form using non-standard input validation conditions.
|
||||||
|
// Additional checks for IP, port, and system/component ID fields
|
||||||
|
// Returns true if all fields are valid, false otherwise
|
||||||
|
function validateSpiriLinkForm(form) {
|
||||||
|
const ipformat = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
||||||
|
const portformat = /^([1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/;
|
||||||
|
let isValid = true;
|
||||||
|
|
||||||
|
defaultValidation = form.checkValidity();
|
||||||
|
|
||||||
|
const inputs = form.querySelectorAll("input, select, textarea");
|
||||||
|
inputs.forEach(input => {
|
||||||
|
if (input.value === "") {
|
||||||
|
isValid = !input.hasAttribute("required");
|
||||||
|
setValidationVisuals(input, isValid);
|
||||||
|
} else {
|
||||||
|
if (input.id === "droneMavlinkIP" || input.id === "droneVideoIP") {
|
||||||
|
isValid = input.value.match(ipformat);
|
||||||
|
setValidationVisuals(input, isValid);
|
||||||
|
}
|
||||||
|
else if (input.id === "droneMavlinkPort" || input.id === "droneVideoPort" || input.id === "mavlinkTcpPort") {
|
||||||
|
isValid = input.value.match(portformat);
|
||||||
|
setValidationVisuals(input, isValid);
|
||||||
|
}
|
||||||
|
else if (input.id === "mavlinkSysId" || input.id === "mavlinkCompId") {
|
||||||
|
isValid = input.value > 1 || input.value < 255;
|
||||||
|
setValidationVisuals(input, isValid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
form.classList.add("was-validated");
|
||||||
|
if (!isValid || !defaultValidation) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set validation visuals for input fields
|
||||||
|
// Adds or removes is-invalid class based on the validity of the input
|
||||||
|
// The setCustomValidity function triggers the actual field visuals.
|
||||||
|
// Giving it an empty string assumes the input is valid.
|
||||||
|
function setValidationVisuals(input, isValid) {
|
||||||
|
if (isValid) {
|
||||||
|
input.classList.remove("is-invalid");
|
||||||
|
input.setCustomValidity("");
|
||||||
|
} else {
|
||||||
|
input.classList.add("is-invalid");
|
||||||
|
input.setCustomValidity("Invalid input");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Save configuration values to the configuration file
|
// Save configuration values to the configuration file
|
||||||
function saveSettings() {
|
function saveSettings() {
|
||||||
|
|
||||||
|
const dataIsValid = validateSpiriLinkForm(spiriLinkForm);
|
||||||
|
if (!dataIsValid) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cockpit.file(confLocation)
|
cockpit.file(confLocation)
|
||||||
.read()
|
.read()
|
||||||
|
@ -231,9 +288,18 @@ function displayFail(error) {
|
||||||
result.innerHTML = "Error : " + error;
|
result.innerHTML = "Error : " + error;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the result message
|
// Reset & clear form data
|
||||||
function clearResult() {
|
function resetForm() {
|
||||||
result.innerHTML = "";
|
result.innerHTML = "";
|
||||||
|
const inputs = spiriLinkForm.querySelectorAll("input, select, textarea");
|
||||||
|
inputs.forEach(input => {
|
||||||
|
input.setCustomValidity("");
|
||||||
|
input.classList.remove("is-invalid");
|
||||||
|
input.classList.remove("is-valid");
|
||||||
|
});
|
||||||
|
|
||||||
|
spiriLinkForm.classList.remove("was-validated");
|
||||||
|
spiriLinkForm.classList.add("needs-validation");
|
||||||
}
|
}
|
||||||
|
|
||||||
function addDropDown(box, pairs, defaultValue) {
|
function addDropDown(box, pairs, defaultValue) {
|
||||||
|
@ -245,7 +311,6 @@ function addDropDown(box, pairs, defaultValue) {
|
||||||
option.text = pairs[i][1];
|
option.text = pairs[i][1];
|
||||||
box.add(option);
|
box.add(option);
|
||||||
if (defaultValue === option.value) {
|
if (defaultValue === option.value) {
|
||||||
console.log("found")
|
|
||||||
box.value = option.value;
|
box.value = option.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue