### Navigate to FTS Web UI Installation Directory Source: https://github.com/freetakteam/ui/blob/master/README.md Command to change the current working directory to the default installation path of the FreeTAKServer Web UI application, which is necessary before starting the UI. ```Shell cd /usr/local/lib/python3.8/dist-packages/FreeTAKServer-UI ``` -------------------------------- ### Start FreeTAKServer Web UI Application Source: https://github.com/freetakteam/ui/blob/master/README.md Command to launch the FreeTAKServer Web UI application. Similar to starting the backend, `nohup` allows the UI to run continuously in the background. ```Shell nohup sudo python3 run.py ``` -------------------------------- ### Install FreeTAKServer with Web UI Source: https://github.com/freetakteam/ui/blob/master/README.md Command to install the FreeTAKServer backend and its Web UI component using Python's pip package manager. This command ensures all necessary dependencies for both server and UI are installed. ```Shell sudo python3 -m pip install FreeTAKServer[ui] ``` -------------------------------- ### Start FreeTAKServer Backend Service Source: https://github.com/freetakteam/ui/blob/master/README.md Command to initiate the FreeTAKServer backend service. The `nohup` command ensures the process continues to run in the background even if the terminal session is closed. ```Shell nohup sudo python3 -m FreeTAKServer.controllers.services.FTS ``` -------------------------------- ### Preformatted Text Block Example Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/ui-typography.html Illustrates a block of preformatted text, often used for displaying code or plain text where whitespace and line breaks are preserved. This format is useful for presenting multi-line code examples or structured text. ```Generic 1. #This is an example of preformatted text. 2. #Here is another line of code ``` -------------------------------- ### JavaScript: Download File via API Fetch Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/mission.html The `downloadFile` function initiates a file download by fetching data from a specified API endpoint. It uses `fetch` with GET method and includes authorization headers. Upon successful retrieval, it creates a Blob, generates a temporary URL, and programmatically triggers a file download, providing user feedback via a snackbar. ```JavaScript function downloadFile(param, name) { let url = `{{protocol}}://{{ip}}:8080/Marti/api/sync/metadata/${param}/tool`; headers = { Authorization: "{{apikey | safe}}", Connection: "Keep-Alive" }; fetch(url, { method: "GET", headers: headers, }) .then(resp => resp.blob()) .then(blob => { const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; // the filename you want a.download = name; document.body.appendChild(a); a.click(); window.URL.revokeObjectURL(url); snackFunction("File Downloaded Successfully!"); // alert('your file has downloaded!'); // or you know, something with better UX... }) .catch(() => { snackFunction("File downloaded Failed! Contact Administrator."); }); } ``` -------------------------------- ### JavaScript DOM Manipulation and Event Handling Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/connect.html This snippet demonstrates client-side JavaScript for dynamically updating the UI. It hides a notification element, creates a dropdown menu from an array of events, and initializes an empty array on window load. It also calls an `establishConnection` function, likely for WebSocket or similar. Note: The snippet appears to be a fragment, starting with a closing brace and using a shorthand `tById`. ```javascript tById("notif").style.display = "none"; } let ul = document.createElement("ul"); ul.className = "dropdown-menu dropdown-menu-right dropdown-navbar"; document.getElementById("events-info").appendChild(ul); for (let [index, row] of eventsArr.entries()) { var li = document.createElement("li"); li.className = "nav-link"; var a = document.createElement("a"); a.className = "nav-item dropdown-item"; a.innerHTML = row; li.appendChild(a); ul.appendChild(li); } }); }; establishConnection(); $(window).on("load", function () { emergencyArr = []; }); ``` -------------------------------- ### JavaScript: Establish WebSocket Connection Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/connect.html This asynchronous function establishes a WebSocket connection using Socket.IO to the specified server. It then attempts to authenticate the connection and, if successful, proceeds to get event information from the server. ```JavaScript async function establishConnection() { console.log("Make connection"); var socket = io.connect(`{{protocol}}://{{ip}}:{{port}}`); console.log("Emit event authenticate..."); let isAuth = await authenticate(socket); if (isAuth === "True") { getEventsInfo(socket); } else { // throw error } } ``` -------------------------------- ### Jinja2: Extending a Base Template Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/page-500.html This snippet demonstrates how to use the `{% extends %}` tag in Jinja2 to specify a parent template from which the current template will inherit blocks and structure. This is a fundamental concept for building consistent web layouts. ```Jinja2 {% extends "errors/500.html" %} ``` -------------------------------- ### Inline CSS Class Code Example Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/ui-typography.html Demonstrates an inline code element for a CSS class name, typically wrapped within a `` tag in HTML to display code snippets or technical terms within a paragraph. ```CSS .css-class-as-code ``` -------------------------------- ### Jinja2 Template: Extending a Base HTML File Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/page-404.html This snippet shows the `extends` tag in Jinja2, which specifies that the current template should inherit from 'errors/404.html'. This allows the current template to override or add content to blocks defined in the parent template, promoting code reuse and consistent page layouts. ```Jinja2 {% extends "errors/404.html" %} ``` -------------------------------- ### JavaScript Function to Establish Socket.IO Connection and Authenticate Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/users.html `establishConnection` initializes a Socket.IO connection to the server using dynamic protocol, IP, and port variables. It then calls the `authenticate` function and, upon successful authentication, proceeds to fetch user and event information. ```JavaScript // this gets current server data async function establishConnection() { console.log("Make connection"); var socket = io.connect(`{{protocol}}://{{ip}}:{{port}}`); console.log("Emit event authenticate..."); let isAuth = await authenticate(socket); if (isAuth === "True") { getUserInfo(socket); getEventsInfo(socket); } else { // throw error } } ``` -------------------------------- ### Initialize UI Switches based on Service Status Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/configure.html This JavaScript snippet reads the current status of various services (TCP CoT, SSL CoT, Data Package, REST API, Federation) from a `serviceInfoObject` and updates the corresponding UI toggle switches (checkboxes) to reflect their 'on' or 'off' state. It ensures the UI accurately represents the backend service configuration upon page load. ```javascript ; if(serviceInfoObject.services.TCP_CoT_service.status == "on") { document.getElementById("TCPCoTOnOffSwitch").checked = true; } else { document.getElementById("TCPCoTOnOffSwitch").checked = false; } if(serviceInfoObject.services.SSL_CoT_service.status == "on") { document.getElementById("SSLCoTOnOffSwitch").checked = true; } else { document.getElementById("SSLCoTOnOffSwitch").checked = false; } if(serviceInfoObject.services.TCP_DataPackage_service.status == "on") { document.getElementById("HTTPDPOnOffSwitch").checked = true; } else { document.getElementById("HTTPDPOnOffSwitch").checked = false; } if(serviceInfoObject.services.SSL_DataPackage_service.status == "on") { document.getElementById("SSLDPOnOffSwitch").checked = true; } else { document.getElementById("SSLDPOnOffSwitch").checked = false; } if(serviceInfoObject.services.Rest_API_service.status == "on") { document.getElementById("APIOnOffSwitch").checked = true; } else { document.getElementById("APIOnOffSwitch").checked = false; } if(serviceInfoObject.services.Federation_server_service.status == "on") { document.getElementById("FEDOnOffSwitch").checked = true; } else { document.getElementById("FEDOnOffSwitch").checked = false; } }); ``` -------------------------------- ### JavaScript Socket.IO Connection and Authentication Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/configure.html This JavaScript code initializes a Socket.IO connection to a server using dynamically provided protocol, IP, and port. It includes an asynchronous function to authenticate the client with a websocket key and proceeds to fetch initial service and event information upon successful authentication. ```JavaScript var socket = io.connect(`{{protocol}}://{{ip}}:{{port}}`); var orig_tcp_cot_status; var orig_ssl_cot_status; var orig_tcp_dp_status; var orig_ssl_cot_status; var orig_api_cot_status; var orig_fed_cot_status; // this gets current server data async function establishConnection() { let isAuth = await authenticate(socket); if (isAuth === "True") { getServiceInfo(socket); getEventsInfo(socket); } else { // throw error } } const authenticate = (socket) => { socket.emit("authenticate", JSON.stringify({ Authenticate: "{{websocketkey | safe}}" })); return new Promise(function (resolve, reject) { socket.on("authentication", function (data) { let authenticateObject = JSON.parse(data); if (authenticateObject.successful === "True") { resolve("True"); } else { reject("False"); } }); }); }; ``` -------------------------------- ### Jinja2 Template Structure and Dynamic Content Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/configure.html This snippet demonstrates the basic structure of a Jinja2 template, including extending a base layout and defining content blocks. It also shows how to iterate over data and display variables dynamically within the HTML structure. ```Jinja2 {% extends "base-site.html" %} {% block title %} Configure {% endblock %} {% block stylesheets %}{% endblock stylesheets %} {% block content %} [SYSTEM CONFIGURATION] Data Package IP TCP COT HTTP DP API SSL COT SSL DP FED Apply [OUTGOING FEDERATION] Name IP / Domain Reconnect Port Max Retries Fallback {% for items in outgoing_federation_json_data %} {{items['name']}} {% endfor %} Enabled Disabled Apply {{ msg if msg is defined else ' ' }} {% endblock content %} {% block javascripts %} {% endblock javascripts %} ``` -------------------------------- ### JavaScript: Get WebSocket Events Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/connect.html This function emits an 'events' event to the WebSocket server and listens for 'eventsUpdate' events. If the received 'eventsArr' has a length greater than 0, it makes a notification element visible on the page. ```JavaScript const getEventsInfo = (socket) => { socket.emit("events"); socket.on("eventsUpdate", function (data) { let eventsArr = data.events; if (eventsArr.lenght > 0) { document.getElementById("notif").style.display = "block"; } else { document.getElemen ``` -------------------------------- ### jQuery Document Ready Initialization Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/base/templates/login/login.html This JavaScript snippet uses jQuery to ensure that the `demo.initDashboardPageCharts()` function is called only after the DOM is fully loaded. This is a common pattern for initializing page-specific scripts. ```JavaScript $(document).ready(function() { // Javascript method's body can be found in assets/js/demos.js demo.initDashboardPageCharts(); }); ``` -------------------------------- ### JavaScript Function to Fetch and Display System User Information Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/users.html The `getUserInfo` function requests system user data by emitting a "systemUsers" event. Upon receiving a "systemUsersUpdate" event, it parses the JSON response, hides a loading spinner, and dynamically constructs an HTML table to display user details. It also attaches a click handler to each row for selection. ```JavaScript const getUserInfo = (socket) => { console.log("calling..."); socket.emit("systemUsers"); console.log("calling..emitted..."); socket.on("systemUsersUpdate", function (data) { let userInfoObject = JSON.parse(data); let tableArr = JSON.parse(data).SystemUsers; // console.log("Print USER Response:" + JSON.stringify(userInfoObject)); document.getElementById("loading").style.display = "none"; //create a Table Object let tablehdr = document.createElement("table"); tablehdr.className = "table-style-hdr"; let headerRow = tablehdr.insertRow(); let nameHdr = headerRow.insertCell(); nameHdr.textContent = "Name"; nameHdr.className = "user_c1"; let groupHdr = headerRow.insertCell(); groupHdr.textContent = "Group"; groupHdr.className = "user_c1"; let tokenHdr = headerRow.insertCell(); tokenHdr.textContent = "Token"; tokenHdr.className = "user_c1"; let passwordHdr = headerRow.insertCell(); passwordHdr.textContent = "Password"; passwordHdr.className = "user_c1"; let certsHdr = headerRow.insertCell(); certsHdr.textContent = "Certs"; certsHdr.className = "user_c1"; let deviceTypeHdr = headerRow.insertCell(); deviceTypeHdr.textContent = "Device Type"; deviceTypeHdr.className = "user_c1"; document.getElementById("user-table-hdr").appendChild(tablehdr); let table = document.createElement("table"); table.className = "user-table-style"; if (tableArr.length == 0) { let no_recs = table.insertRow(); no_recs.className = "row-color-nohover row-class"; let noRecsCell = no_recs.insertCell(); noRecsCell.textContent = "No Records"; noRecsCell.className = "user-cell-style-1"; document.getElementById("user-table").appendChild(table); } else { // removeUsers for (let [index, row] of tableArr.entries()) { let t_row = table.insertRow(index); t_row.className = "row-color-nohover row-class"; t_row.setAttribute("data-myID", row.Uid); // t_row.onclick = (function() { // console.log(this.getAttribute("data-myID")); // }); t_row.onclick = function () { $(this).toggleClass("rowselected"); captureClick(this.getAttribute("data-myID")); }; let nameCell = t_row.insertCell(); nameCell.textContent = row.Name; nameCell.className = "user-cell-style-1"; let groupCell = t_row.insertCell(); groupCell.textContent = row.Group; groupCell.className = "user-cell-style-1"; let tokenCell = t_row.insertCell(); // tokenCell.textContent = row.Token; tokenCell.textContent = "************"; tokenCell.className = "user-cell-style-1"; let passwordCell = t_row.insertCell(); passwordCell.textContent = "************"; // passwordCell.textContent = row.Password; passwordCell.className = "user-cell-style-1"; let certsCell = t_row.insertCell(); certsCell.textContent = row.Certs; certsCell.className = "user-cell-style-1"; let deviceTypeCell = t_row.insertCell(); deviceTypeCell.textContent = row.DeviceType; deviceTypeCell.className = "user-cell-style-1"; } document.getElementById("user-table").appendChild(table); } }); }; ``` -------------------------------- ### JavaScript: Open Multiple QR Code URLs Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/mission.html The `openQR` function iterates through a global array `gArr`, which is expected to contain objects with a `hash` property. For each item, it constructs a URL to a QR code page and opens it in a new browser window, facilitating bulk QR code viewing. ```JavaScript function openQR() { for (let i = 0; i < gArr.length; i++) { window.open(window.location.origin+"/mission/"+gArr.at(i).hash+"/qr") } } ``` -------------------------------- ### Establish Socket Connection (Reference) Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/users.html A call to `establishConnection()` is present in the code, indicating that a socket connection is set up elsewhere in the application. This function is crucial for real-time communication with the server. ```javascript establishConnection(); ``` -------------------------------- ### JavaScript: Hide UI Element and Establish Connection Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/configure.html This JavaScript code snippet is likely part of a `setTimeout` function, designed to remove the 'show' class from an element `x` after a 3-second delay, effectively hiding it. Following this, it calls `establishConnection()` to initiate a network or application connection. This pattern is common for transient UI feedback or splash screens, often found within template blocks like `{% block javascripts %}`. ```JavaScript { x.className = x.className.replace("show", ""); }, 3000); } establishConnection(); ``` -------------------------------- ### JavaScript: Establish WebSocket Connection and Initialize Data Fetching Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/index.html This function initializes a WebSocket connection to the FreeTAKServer instance. It handles connection errors by updating the UI to show error states. Upon successful authentication, it proceeds to fetch various system data like user information, logs, service status, server health, and events, setting up periodic polling for updates. ```javascript async function establishConnection() { console.log("Make connection"); var socket = io.connect(`{{protocol}}://{{ip}}:{{port}}`); socket.on('connect_error', function() { console.log("Sorry, there seems to be an issue with the connection!"); snackFunction("Sorry, there seems to be an issue with the connection!"); document.getElementById("loading-systemstatus1").style.display = "none"; document.getElementById("loading-systemstatus2").style.display = "none"; document.getElementById("loading-systemstatus3").style.display = "none"; document.getElementById("loading-systemstatus4").style.display = "none"; document.getElementById("loading-systemstatus5").style.display = "none"; document.getElementById("loading-systemstatus6").style.display = "none"; document.getElementById("tcp_error").style.display = "block"; document.getElementById("ssl_error").style.display = "block"; document.getElementById("rest_api_error").style.display = "block"; document.getElementById("fed_error").style.display = "block"; document.getElementById("cot_tcp_error").style.display = "block"; document.getElementById("cot_ssl_error").style.display = "block"; }) getConnectInfo(socket); console.log("Emit event authenticate..."); let isAuth = await authenticate(socket); if (isAuth === "True") { getUsers(socket); getLogs(socket); getServiceInfo(socket); getServerHealth(socket); getSystemStatus(socket); getEventsInfo(socket); setInterval(() => { getUsers(socket); }, '{{userinterval}}'); setInterval(() => { getServerHealth(socket); }, '{{serverhealthinterval}}'); setInterval(() => { refresh(); getSystemStatus(socket); }, '{{sysstatusinterval}}'); } else { } } ``` -------------------------------- ### JavaScript WebSocket Connection and Authentication Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/mission.html Initializes a Socket.IO connection to the server and defines an asynchronous function `establishConnection` to handle the authentication process. The `authenticate` function emits an 'authenticate' event with a key and returns a Promise that resolves upon successful authentication or rejects otherwise. ```JavaScript var socket = io.connect(`{{protocol}}://{{ip}}:{{port}}`); var tcpip; var tcpport; async function establishConnection() { console.log("Emit event authenticate..."); let isAuth = await authenticate(socket); if (isAuth === "True") { getServiceInfo(socket); getEventsInfo(socket); } else { // throw error } } const authenticate = (socket) => { socket.emit("authenticate", JSON.stringify({ Authenticate: "{{websocketkey | safe}}" })); return new Promise(function (resolve, reject) { socket.on("authentication", function (data) { let authenticateObject = JSON.parse(data); if (authenticateObject.successful === "True") { resolve("True"); } else { reject("False"); } }); }); }; ``` -------------------------------- ### Jinja2 Base Template and Dynamic Content Rendering Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/connect.html This snippet illustrates the foundational Jinja2 template structure for a web page, including extending a base template, defining content blocks, and integrating JavaScript. It also demonstrates how to dynamically render data from a 'json_data' variable using a 'for' loop and display a conditional message if no records are present. ```Jinja2 {% extends "base-site.html" %} {% block title %} Connect {% endblock %} {% block stylesheets %}{% endblock stylesheets %} {% block content %} {% for dict_items in json_data %} {{dict_items['name']}} {{dict_items['lat']}} {{dict_items['lon']}} {{dict_items['type']}} {{dict_items['uid']}} {% endfor %} {% if json_data|length == 0 %} No Records. {% endif %} {{ msg if msg is defined else ' ' }} {% endblock content %} {% block javascripts %} // JavaScript functions would be included here {% endblock javascripts %} ``` -------------------------------- ### JavaScript Socket.IO Connection and Authentication Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/page-user.html This JavaScript code establishes a Socket.IO connection to a specified IP and port. It defines an 'authenticate' function that emits an "authenticate" event with a WebSocket key and returns a Promise that resolves upon successful authentication or rejects otherwise. ```JavaScript var socket = io.connect(`http://{{ip}}:{{port}}`); const authenticate = (socket) => { socket.emit("authenticate", JSON.stringify({ Authenticate: "{{websocketkey | safe}}" })); return new Promise(function (resolve, reject) { socket.on("authentication", function (data) { let authenticateObject = JSON.parse(data); if (authenticateObject.successful === "True") { resolve("True"); } else { reject("False"); } }); }); }; authenticate(socket) ``` -------------------------------- ### Apply Service Configuration Changes via Socket Emit Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/configure.html This JavaScript function collects the current status and port values for various services (CoT, Data Package, Federation, REST API) from UI input fields. It constructs a `serviceInfo` object, then selectively removes service entries from the object if their values haven't changed from their original state. Finally, it emits the modified configuration object as a JSON string via a `socket.emit` event named 'changeServiceInfo' to update the backend, followed by a UI refresh. ```javascript const applyServiceInfo = () => { let obj = { services: { SSL_CoT_service: { status: document.getElementById("SSLCoTOnOffSwitch").checked === true ? "on" : "off", port: +document.getElementById("ssl_cot_port").value }, TCP_CoT_service: { status: document.getElementById("TCPCoTOnOffSwitch").checked === true ? "on" : "off", port: +document.getElementById("tcp_cot_port").value }, SSL_DataPackage_service: { status: document.getElementById("SSLDPOnOffSwitch").checked === true ? "on" : "off", port: +document.getElementById("ssl_dp_port").value }, TCP_DataPackage_service: { status: document.getElementById("HTTPDPOnOffSwitch").checked === true ? "on" : "off", port: +document.getElementById("http_dp_port").value }, Federation_server_service: { status: document.getElementById("FEDOnOffSwitch").checked === true ? "on" : "off", port: +document.getElementById("fed_port").value }, Rest_API_service: { status: document.getElementById("APIOnOffSwitch").checked === true ? "on" : "off", port: +document.getElementById("api_port").value } }, ip: document.getElementById("ip").value } var status_mapper = {"on": true, "off": false} if((status_mapper[orig_tcp_cot_status] === document.getElementById("TCPCoTOnOffSwitch").checked) && (String(orig_tcp_cot_port) === document.getElementById("tcp_cot_port").value)) { delete obj.services.TCP_CoT_service; } if((status_mapper[orig_ssl_cot_status] === document.getElementById("SSLCoTOnOffSwitch").checked) && (String(orig_ssl_cot_port) === document.getElementById("ssl_cot_port").value)) { delete obj.services.SSL_CoT_service; } if((status_mapper[orig_tcp_dp_status] === document.getElementById("HTTPDPOnOffSwitch").checked) && (String(orig_tcp_dp_port) === document.getElementById("http_dp_port").value)) { delete obj.services.TCP_DataPackage_service; } if((status_mapper[orig_ssl_dp_status] === document.getElementById("SSLDPOnOffSwitch").checked) && (String(orig_ssl_dp_port) === document.getElementById("ssl_dp_port").value)) { delete obj.services.SSL_DataPackage_service; } if((status_mapper[orig_api_cot_status] === document.getElementById("APIOnOffSwitch").checked) && (String(orig_api_cot_port) === document.getElementById("api_port").value)) { delete obj.services.Rest_API_service; } if((status_mapper[orig_fed_cot_status] === document.getElementById("FEDOnOffSwitch").checked) && (String(orig_fed_cot_port) === document.getElementById("fed_port").value)) { delete obj.services.Federation_server_service; } socket.emit("changeServiceInfo", JSON.stringify(obj) ); snackFunction("Configuration updated. Refreshing data."); refresh(); }; ``` -------------------------------- ### Initialize WebSocket Connection on Page Load Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/about.html This line of code ensures that the 'establishConnection' function is called when the page's JavaScript content is loaded, initiating the WebSocket connection process as soon as the UI is ready. ```javascript establishConnection(); ``` -------------------------------- ### Dynamically Display Log Table in UI with JavaScript Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/index.html This function creates and populates an HTML table with log entries. It dynamically generates table headers and rows, formats timestamps using 'moment' library, and applies specific CSS classes for styling. It expects an array of log objects, each containing 'time', 'type', 'file', and 'message' properties. ```JavaScript const displayLogTable = (tableArr) => { let tablehdr = document.createElement("table"); tablehdr.className = "table-style"; let headerRow = tablehdr.insertRow(0); let timeHdr = headerRow.insertCell(); timeHdr.textContent = "TIME"; timeHdr.className = "hdr_c1"; let typeHdr = headerRow.insertCell(); typeHdr.textContent = "TYPE"; typeHdr.className = "hdr_c2"; let fileHdr = headerRow.insertCell(); fileHdr.textContent = "FILE"; fileHdr.className = "hdr_c3"; let messageHdr = headerRow.insertCell(); messageHdr.textContent = "MESSAGE"; messageHdr.className = "hdr_c4"; document.getElementById("log-table-hdr").appendChild(tablehdr); let table = document.createElement("table"); table.className = "table-style"; for (let [index, row] of tableArr.entries()) { let t_row = table.insertRow(index); t_row.className = "row-color-nohover"; let timeCell = t_row.insertCell(); timeCell.textContent = moment(row.time).format("HH:MM"); timeCell.className = "cell-style-1"; let typeCell = t_row.insertCell(); typeCell.textContent = row.type; typeCell.className = "cell-style-2"; let fileCell = t_row.insertCell(); fileCell.textContent = row.file; fileCell.className = "cell-style-3"; let messageCell = t_row.insertCell(); messageCell.textContent = row.message; messageCell.className = "cell-style-4"; } document.getElementById("log-table").appendChild(table); }; ``` -------------------------------- ### Jinja2 Basic Page Structure Template Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/page-blank.html This snippet showcases a minimal Jinja2 template for a web page. It extends a 'base-site.html' file and defines standard blocks for the page title, CSS stylesheets, main content, and JavaScript. The content block includes simple headings and a link as placeholder content. ```Jinja2 {% extends "base-site.html" %} {% block title %} Page Blank {% endblock %} {% block stylesheets %}{% endblock stylesheets %} {% block content %} ###### Page Blank #### Add your content [Home](/) {% endblock content %} {% block javascripts %}{% endblock javascripts %} ``` -------------------------------- ### Add New Outgoing Federation Entry Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/configure.html This JavaScript function gathers details for a new outgoing federation (name, address, port, fallback, status, reconnect interval, max retries) from UI input fields. It constructs a JSON object and sends it as a POST request to the `/FederationTable` API endpoint. The request includes an authorization header with an API key. Upon successful submission, it triggers a UI notification and page refresh. ```javascript function addOF() { let obj = { outgoingFederations:[{ name: document.getElementById("nameof").value, address: document.getElementById("ipaddressof").value, port: document.getElementById("portof").value, fallBack: document.getElementById("fallbackserverof").value, status: document.getElementById("statusof").value, reconnectInterval: document.getElementById("recintervalof").value, maxRetries: document.getElementById("maxretriesof").value, }] } headers = { Authorization: "{{apikey | safe}}" }; fetch("{{protocol}}://{{ip}}:{{port}}/FederationTable", { method: "POST", headers: headers, body: JSON.stringify(obj), }).then((response) => { snackFunction("Add Outgoing Federation Successful. Refreshing data."); refresh(); }); } ``` -------------------------------- ### Initialize Google Maps with jQuery Document Ready Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/ui-maps.html This JavaScript snippet ensures that the 'demo.initGoogleMaps()' function is executed only after the entire HTML document has been loaded and parsed. It uses jQuery's '$(document).ready()' method, which is a common practice for safe DOM manipulation. The 'demo.initGoogleMaps()' function itself is defined externally. ```JavaScript $(document).ready(function() { // Javascript method's body can be found in assets/js/demos.js demo.initGoogleMaps(); }); ``` -------------------------------- ### JavaScript Socket.IO Client for System Service Status Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/configure.html This function retrieves current system service information (e.g., TCP CoT, SSL CoT, Data Package, API, Federation) from the server using Socket.IO. It parses the received JSON data, stores original service statuses and ports, and updates corresponding input fields in the HTML form to reflect the current configuration. ```JavaScript const getServiceInfo = (socket) => { socket.emit("serviceInfo"); socket.on("serviceInfoUpdate", function (data) { let serviceInfoObject = JSON.parse(data); orig_tcp_cot_status = serviceInfoObject.services.TCP_CoT_service.status; orig_tcp_cot_port = serviceInfoObject.services.TCP_CoT_service.port; orig_ssl_cot_status = serviceInfoObject.services.SSL_CoT_service.status; orig_ssl_cot_port = serviceInfoObject.services.SSL_CoT_service.port; orig_tcp_dp_status = serviceInfoObject.services.TCP_DataPackage_service.status; orig_tcp_dp_port = serviceInfoObject.services.TCP_DataPackage_service.port; orig_ssl_dp_status = serviceInfoObject.services.SSL_DataPackage_service.status; orig_ssl_dp_port = serviceInfoObject.services.SSL_DataPackage_service.port; orig_api_cot_status = serviceInfoObject.services.Rest_API_service.status; orig_api_cot_port = serviceInfoObject.services.Rest_API_service.port; orig_fed_cot_status = serviceInfoObject.services.Federation_server_service.status; orig_fed_cot_port = serviceInfoObject.services.Federation_server_service.port; console.log("Print CONFIGURE serviceInfoUpdate Response:" + JSON.stringify(serviceInfoObject)); document.getElementById("tcp_cot_port").value = serviceInfoObject.services.TCP_CoT_service.port; document.getElementById("ssl_cot_port").value = serviceInfoObject.services.SSL_CoT_service.port; document.getElementById("http_dp_port").value = serviceInfoObject.services.TCP_DataPackage_service.port; document.getElementById("ssl_dp_port").value = serviceInfoObject.services.SSL_DataPackage_service.port; document.getElementById("api_port").value = serviceInfoObject.services.Rest_API_service.port; document.getElementById("fed_port").value = serviceInfoObject.services.Federation_server_service.port; document.getElementById("ip").value = serviceInfoObject.ip; }); }; ``` -------------------------------- ### JavaScript: Fetch and Display System Logs Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/index.html This function requests system logs from the WebSocket server, specifying a current timestamp. It listens for 'logUpdate' events, parses the received log data, hides a loading indicator, and begins to construct an HTML table to display the log entries. ```javascript const getLogs = (socket) => { let logdate = moment().format("YYYY-MM-DD HH:mm:ss,SSS"); let obj = { "time": logdate } socket.emit("logs", JSON.stringify(obj)); socket.on("logUpdate", function (data) { let logsObject = JSON.parse(data); console.log(' received log data ' ); document.getElementById("loading-systemstatus8").style.display = "none"; let tableArr = JSON.parse(data).log_data; let tablehdr = document.createElement("table"); tablehdr.className = "table-style-hdr"; let headerRow = tablehdr.insertRow(); let timeHdr = headerRow.insertCell(); timeHdr.textContent = "TIME"; timeHdr.className = "hdr_c1"; let typeHdr = headerRow.in ``` -------------------------------- ### Initialize User Selection Array on Window Load Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/users.html This jQuery snippet initializes the global array `uArr` to an empty array when the entire window content has finished loading. This ensures a clean state for user selections every time the page is loaded. ```javascript $(window).on("load", function () { uArr = []; }); ``` -------------------------------- ### Identify FreeTAKServer Configuration Files Source: https://github.com/freetakteam/ui/blob/master/README.md Lists the primary configuration files that administrators need to set up for both the FreeTAKServer UI and the FreeTAKServer backend to ensure proper operation and connectivity. ```Text Config.py for the UI MainConfig.py for FTS ``` -------------------------------- ### WebSocket API: System Logs Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/index.html API for fetching and receiving real-time system log entries. ```APIDOC WebSocket API: Client -> Server: Event: "logs" Payload: JSON.stringify({ time: "YYYY-MM-DD HH:mm:ss,SSS" }) Description: Requests log entries from a specified timestamp. Server -> Client: Event: "logUpdate" Payload: JSON.parse(data) -> { log_data: [...] } Description: Provides an array of log data entries. ``` -------------------------------- ### Jinja2 Data Package Table Display Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/mission.html Renders a table displaying data package information by iterating over `json_data`. It extracts and formats fields like Name, SubmissionUser (cleaned), PrimaryKey, Size, and SubmissionDateTime for presentation. ```Jinja2 \[DATA PACKAGE\] Name Author Index Is Private Size (KB) Submitted {% for dict_items in json_data %} {% if loop.index == 1 %} {% endif %} {{dict_items['Name']}} {{dict_items['SubmissionUser'] | replace("[", "") | replace("(", "") | replace("'", "") | replace("'", "") | replace(")", "") | replace("]", "") | replace(",", "") }} {{dict_items['PrimaryKey']}} {{dict_items['Size'] /1000}} {{dict_items['SubmissionDateTime']}} {% endfor %} DELETE QR ADD ``` -------------------------------- ### JavaScript Data Package Selection Handler Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/mission.html Manages the selection state of data packages for bulk actions. The `captureClick` function adds or removes a data package hash from a global array (`gArr`) and dynamically updates the UI to show the count of selected items and enable/disable a delete button. ```JavaScript // this is a global variable var gArr; function captureClick(param, index) { if (!gArr.some((item) => item.hash === param)) { let vv = { hash: param, index: index }; gArr.push(vv); } else { gArr = gArr.filter((item) => item.hash !== param); } // classList if (gArr.length > 0) { document.getElementById("del-count").innerHTML = ` [${gArr.length}]`; document.getElementById("data-package-delete").classList.add("btn", "btn-simple", "btn-twitter", "enable-delete"); } else { document.getElementById("del-count").innerHTML = ``; document.getElementById("data-package-delete").classList.add("btn", "btn-simple", "btn-twitter", "disable-delete"); } } ``` -------------------------------- ### Initialize Global Arrays on Window Load in JavaScript Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/mission.html This JavaScript snippet uses jQuery's `$(window).on("load", ...)` to initialize several global arrays (`gArr`, `ofDelArr`, `ofEditArr`, `excheckArr`) to empty arrays once the entire page, including all resources, has fully loaded. ```JavaScript $(window).on("load", function () { gArr = []; ofDelArr = []; ofEditArr = []; excheckArr = []; }); ``` -------------------------------- ### JavaScript: Process Connection Information Updates Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/index.html This function listens for 'connectUpdate' events from the WebSocket server. It parses the received connection data, calculates the server's uptime, and updates the 'start-time' and 'up-time' elements in the HTML document. ```javascript const getConnectInfo = (socket) => { socket.on("connectUpdate", function (data) { let connectObject = JSON.parse(data); let now = moment(); let start_time = moment(connectObject.starttime); let up_time = moment(moment().diff(moment(connectObject.starttime))).format("HH MM SS"); var durationX = moment.duration(now.diff(start_time)); var hours = Math.floor(durationX.asHours()); var minutes = durationX.minutes(); var seconds = durationX.seconds(); document.getElementById("start-time").innerText = moment(connectObject.starttime).format("DD/MM/YYYY HH:MM z"); document.getElementById("up-time").innerText = [hours + "H", minutes + "M", seconds + "S"].join(" "); }); }; ``` -------------------------------- ### Jinja2 Template for User and Group Management UI Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/users.html This Jinja2 template defines the basic structure of the user management page, extending a base template. It includes sections for system users and group permissions, with placeholders for dynamic content and integrates CSS and JavaScript blocks. ```Jinja2 {% extends "base-site.html" %} {% block title %} Users {% endblock %} {% block stylesheets %} .multiselect { height: auto; max-height: 400px; background-color: #27293d; padding: 20px; margin: 20px 0px 20px 20px; overflow: auto; } .multiselect label { display: block; } .multiselect-on { color: #ffffff; background-color: #278aed; } {% endblock stylesheets %} {% block content %} [SYSTEM USERS] ![](/static/assets/img/spinner1.svg) DELETE       ADD Certs True False Device Type Mobile WinTAK Submit [GROUP PERMISSIONS] Name Description Yellow Admins Green Users Blue Morons Enemy CoT Create Friendly CoT Create EMS CoT Create Routes CoT DELETE       ADD {% endblock content %} ``` -------------------------------- ### JavaScript: Upload Data Package File via API Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/mission.html The `upload` function handles the client-side logic for uploading a file to a 'DataPackageTable' endpoint. It performs validation checks for file presence, name, extension, and size against a configured limit. The file is then sent as `FormData` via a POST request, with success or failure feedback provided through a snackbar and a data refresh. ```JavaScript // Select your input type file and store it in a variable const input = document.getElementById("fileinput"); // This will upload the file after having read it const upload = (file) => { if (file === undefined) { snackFunction("Select a file to Add"); return false; } if (document.getElementById("filename").value == "") { snackFunction("Select a file to Add"); return false; } if (!checkExtn(file.name)) { return false; } if(file.size > '{{datapackagesizelimit}}') { snackFunction(" ``` -------------------------------- ### Fetch Service Information via WebSockets in JavaScript Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/index.html This function initiates a request for service information from the server using a WebSocket connection. It emits a 'serviceInfo' event and listens for a 'serviceInfoUpdate' event, parsing the received JSON data into a JavaScript object. ```JavaScript const getServiceInfo = (socket) => { socket.emit("serviceInfo"); socket.on("serviceInfoUpdate", function (data) { let serviceInfoObject = JSON.parse(data); }); }; ``` -------------------------------- ### JavaScript Function to Post Emergency Alerts (Partial) Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/connect.html This snippet shows the initial part of the 'postEmergency' JavaScript function, which is designed to handle the submission of emergency alert data. It begins with client-side validation, ensuring that the 'name' field is populated before proceeding, indicating a similar pattern of data collection and API interaction as other posting functions on the page. ```JavaScript const postEmergency = () => { if (document.getElementById("name2").value === "") { snackF ``` -------------------------------- ### Establish Connection Function Call in JavaScript Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/mission.html This line of JavaScript code invokes the `establishConnection()` function, which is presumably responsible for initiating a network or WebSocket connection within the application. ```JavaScript establishConnection(); ``` -------------------------------- ### Add New System User via Socket Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/users.html This asynchronous function handles the addition of a new system user. It performs client-side validation for mandatory input fields. If all fields are valid, it collects user data from the form, connects to a Socket.IO server, authenticates, and emits an 'addSystemUser' event. After successful addition, it clears the form, toggles the add user form visibility, displays a success notification, and refreshes the page. ```javascript const addUser = async () => { if (document.getElementById("name1").value === "") { snackFunction("Name field is mandatory"); return false; } else if (document.getElementById("group1").value === "") { snackFunction("Group field is mandatory"); return false; } else if (document.getElementById("token1").value === "") { snackFunction("Token field is mandatory"); return false; } else if (document.getElementById("password1").value === "") { snackFunction("Password field is mandatory"); return false; } else if (document.getElementById("certbool").value === "") { snackFunction("Certification field is mandatory"); return false; } else if (document.getElementById("deviceType").value === "") { snackFunction("device type field is mandatory"); return false; } let obj = { systemUsers: [ { Name: document.getElementById("name1").value, Group: document.getElementById("group1").value, Token: document.getElementById("token1").value, Password: document.getElementById("password1").value, Certs: document.getElementById("certbool").value, DeviceType: document.getElementById("deviceType").value } ] }; var socket = io.connect(`{{protocol}}://{{ip}}:{{port}}`); console.log("Emit event authenticate..."); let isAuth = await authenticate(socket); if (isAuth === "True") { socket.emit("addSystemUser", JSON.stringify(obj)); document.getElementById("name1").value = ""; document.getElementById("group1").value = ""; document.getElementById("token1").value = ""; document.getElementById("password1").value = ""; document.getElementById("certbool").value = ""; document.getElementById("deviceType").value = ""; addUserToggle(); snackFunction("User Added, refreshing data"); refresh(); } else { // throw error } }; ``` -------------------------------- ### Jinja2 Template for UI Icons Page Structure Source: https://github.com/freetakteam/ui/blob/master/FreeTAKServer-UI/app/home/templates/ui-icons.html This snippet shows a Jinja2 template defining the basic structure for a UI icons page. It extends a base HTML template, sets the page title, and includes a content block where a comprehensive list of Nucleo icon names is displayed for reference. ```Jinja2 {% extends "base-site.html" %} {% block title %} UI Icons {% endblock %} {% block stylesheets %}{% endblock stylesheets %} {% block content %} ##### 1001 Awesome Nucleo Icons Handcrafted by our friends from [NucleoApp](https://nucleoapp.com/?ref=1712) icon-alert-circle-exc icon-align-center icon-align-left-2 icon-app icon-atom icon-attach-87 icon-badge icon-bag-16 icon-bank icon-basket-simple icon-bell-55 icon-bold icon-book-bookmark icon-double-right icon-bulb-63 icon-bullet-list-67 icon-bus-front-12 icon-button-power icon-camera-18 icon-calendar-60 icon-caps-small icon-cart icon-chart-bar-32 icon-chart-pie-36 icon-chat-33 icon-check-2 icon-cloud-download-93 icon-cloud-upload-94 icon-coins icon-compass-05 icon-controller icon-credit-card icon-delivery-fast icon-email-85 icon-gift-2 icon-globe-2 icon-headphones icon-heart-2 icon-html5 icon-double-left icon-image-02 icon-istanbul icon-key-25 icon-laptop icon-light-3 icon-link-72 icon-lock-circle icon-map-big icon-minimal-down icon-minimal-left icon-minimal-right icon-minimal-up icon-mobile icon-molecule-40 icon-money-coins icon-notes icon-palette icon-paper icon-pin icon-planet icon-puzzle-10 icon-pencil icon-satisfied icon-scissors icon-send icon-settings-gear-63 icon-settings icon-wifi icon-single-02 icon-single-copy-04 icon-sound-wave icon-spaceship icon-square-pin icon-support-17 icon-tablet-2 icon-tag icon-tap-02 icon-tie-bow icon-time-alarm icon-trash-simple icon-trophy icon-tv-2 icon-upload icon-user-run icon-vector icon-video-66 icon-wallet-43 icon-volume-98 icon-watch-time icon-world icon-zoom-split icon-refresh-01 icon-refresh-02 icon-shape-star icon-components icon-triangle-right-17 icon-button-pause icon-simple-remove icon-simple-add icon-simple-delete {% endblock content %} {% block javascripts %}{% endblock javascripts %} ```