-
Notifications
You must be signed in to change notification settings - Fork 70
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Simple HTML frontend for Bisq 2 monitor
Accessible via http://localhost:8082/node-monitor/index.html The hostlist and portlist-filter can be set in settings as a list, separated by newlines or commas, and will be saved in a cookie.
- Loading branch information
Showing
10 changed files
with
607 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Core app logic | ||
|
||
async function loadDataForHost(host, totalHosts, completedCallback) { | ||
try { | ||
const reportsUrl = `http://localhost:8082/api/v1/report/get-report/${host}`; | ||
const reportsResponse = await fetch(reportsUrl); | ||
|
||
const contentType = reportsResponse.headers.get("Content-Type") || ""; | ||
|
||
let reportData; | ||
if (contentType.startsWith("application/json")) { | ||
try { | ||
reportData = await reportsResponse.json(); | ||
} catch (parseError) { | ||
const responseText = await reportsResponse.text(); | ||
reportData = { successful: false, errorMessage: responseText || "Invalid JSON response" }; | ||
} | ||
} else { | ||
const responseText = await reportsResponse.text(); | ||
reportData = { successful: false, errorMessage: responseText }; | ||
} | ||
|
||
displaySingleReport(reportData, host); | ||
|
||
} catch (error) { | ||
displaySingleReport({ successful: false, errorMessage: "Failed to fetch report" }, host); | ||
} finally { | ||
completedCallback(); | ||
} | ||
} | ||
|
||
function updateStatusMessage(message, color = "grey") { | ||
const statusMessage = document.getElementById("statusMessage"); | ||
statusMessage.textContent = message; | ||
statusMessage.style.color = color; | ||
statusMessage.style.display = "block"; | ||
} | ||
|
||
function loadData() { | ||
const hostList = getFilteredHostList(); | ||
|
||
if (hostList.length === 0) { | ||
updateStatusMessage("Please enter a Host:port list in the settings to start fetching data.", "red"); | ||
return; | ||
} | ||
|
||
updateStatusMessage("Loading...", "grey"); | ||
|
||
const reportContainer = document.getElementById("reportContainer"); | ||
reportContainer.innerHTML = ""; | ||
|
||
let completedRequests = 0; | ||
const totalHosts = hostList.length; | ||
|
||
hostList.forEach(host => { | ||
createPlaceholderForHost(host); | ||
loadDataForHost(host, totalHosts, () => { | ||
completedRequests += 1; | ||
if (completedRequests === totalHosts) { | ||
document.getElementById("statusMessage").style.display = "none"; | ||
} | ||
}); | ||
}); | ||
} | ||
|
41 changes: 41 additions & 0 deletions
41
apps/rest-api-app/src/main/resources/node-monitor/eventHandlers.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// Event handlers and initialization | ||
|
||
// Automatic loading at startup if a host list is available | ||
window.onload = () => { | ||
const savedHosts = getHostsCookie(); | ||
const savedPorts = getPortsCookie(); | ||
|
||
if (savedHosts) { | ||
document.getElementById("hostListInput").value = savedHosts; | ||
} | ||
if (savedPorts && savedPorts.length > 0) { | ||
document.getElementById("portListInput").value = savedPorts.join('\n'); | ||
} | ||
|
||
if (savedHosts.trim().length > 0) { | ||
loadData(); | ||
} else { | ||
updateStatusMessage("Please enter a Host:port list in the settings to start fetching data.", "red"); | ||
} | ||
}; | ||
|
||
// Toggle Settings Panel | ||
document.getElementById("hamburgerButton").addEventListener("click", toggleSettingsMenu); | ||
|
||
// Save Configuration and Close Settings Panel | ||
document.getElementById("saveConfigButton").addEventListener("click", function() { | ||
const rawHostListText = document.getElementById("hostListInput").value; | ||
const portList = parseHostListInput(document.getElementById("portListInput").value).map(Number); | ||
|
||
setHostsCookie(rawHostListText); | ||
setPortsCookie(portList); | ||
|
||
loadData(); | ||
toggleSettingsMenu(); | ||
}); | ||
|
||
// Toggle all details (global expand/collapse button) | ||
document.getElementById("toggleAllButton").addEventListener('click', function() { | ||
const expand = this.textContent === "Expand All Details"; | ||
toggleAllDetails(expand); | ||
}); |
82 changes: 82 additions & 0 deletions
82
apps/rest-api-app/src/main/resources/node-monitor/helpers.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Helper functions | ||
|
||
function setHostsCookie(rawHostListText) { | ||
const date = new Date(); | ||
date.setTime(date.getTime() + (365 * 24 * 60 * 60 * 1000)); | ||
const expires = "expires=" + date.toUTCString(); | ||
document.cookie = `hosts=${encodeURIComponent(rawHostListText)}; ${expires}; path=/; SameSite=None; Secure`; | ||
} | ||
|
||
function getHostsCookie() { | ||
const name = "hosts="; | ||
const decodedCookie = decodeURIComponent(document.cookie); | ||
const cookieArray = decodedCookie.split(';'); | ||
|
||
for (let i = 0; i < cookieArray.length; i++) { | ||
let cookie = cookieArray[i].trim(); | ||
if (cookie.indexOf(name) === 0) { | ||
return cookie.substring(name.length); | ||
} | ||
} | ||
return ""; | ||
} | ||
|
||
function setPortsCookie(portList) { | ||
const date = new Date(); | ||
date.setTime(date.getTime() + (365 * 24 * 60 * 60 * 1000)); | ||
const expires = "expires=" + date.toUTCString(); | ||
document.cookie = `ports=${encodeURIComponent(JSON.stringify(portList))}; ${expires}; path=/; SameSite=None; Secure`; | ||
} | ||
|
||
function getPortsCookie() { | ||
const name = "ports="; | ||
const decodedCookie = decodeURIComponent(document.cookie); | ||
const cookiesArray = decodedCookie.split(';'); | ||
for (let cookie of cookiesArray) { | ||
cookie = cookie.trim(); | ||
if (cookie.indexOf(name) === 0) { | ||
return JSON.parse(cookie.substring(name.length)); | ||
} | ||
} | ||
return []; | ||
} | ||
|
||
function formatColumnName(name) { | ||
return name.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase()); | ||
} | ||
|
||
function parseHostListInput(input) { | ||
const uniqueHosts = new Set(); | ||
input.split(/\r?\n/) | ||
.forEach(line => { | ||
line = line.trim(); | ||
|
||
if (line.startsWith('#') || line === '') return; | ||
|
||
line.split(',') | ||
.map(host => host.trim()) | ||
.filter(host => host) | ||
.forEach(host => uniqueHosts.add(host)); | ||
}); | ||
return Array.from(uniqueHosts); | ||
} | ||
|
||
function isValidHostFormat(host) { | ||
const hostPattern = /^[a-zA-Z0-9.-]+:\d+$/; | ||
return hostPattern.test(host); | ||
} | ||
|
||
function getFilteredHostList() { | ||
const hostList = parseHostListInput(document.getElementById("hostListInput").value); | ||
const portList = parseHostListInput(document.getElementById("portListInput").value).map(Number); | ||
|
||
if (portList.length === 0) { | ||
return hostList; | ||
} | ||
|
||
return hostList.filter(host => { | ||
const [, port] = host.split(':'); | ||
return portList.includes(Number(port)); | ||
}); | ||
} | ||
|
47 changes: 47 additions & 0 deletions
47
apps/rest-api-app/src/main/resources/node-monitor/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Bisq Node Monitor</title> | ||
<link rel="stylesheet" href="styles.css"> | ||
</head> | ||
<body> | ||
|
||
<h2>Bisq Node Monitor</h2> | ||
|
||
<div class="hamburger-menu" id="hamburgerButton"> | ||
☰ | ||
</div> | ||
|
||
<div id="settingsPanel" style="display: none;"> | ||
<h3>Settings</h3> | ||
<div> | ||
<label>Host List (comma or newline separated):</label> | ||
<textarea id="hostListInput" placeholder="Host:port list, separated by commas or new lines" rows="3" style="width: 100%;"></textarea> | ||
</div> | ||
<div> | ||
<label>Port List (comma or newline separated, optional):</label> | ||
<textarea id="portListInput" placeholder="Port list for filtering, separated by commas or new lines" rows="2" style="width: 100%;"></textarea> | ||
</div> | ||
<button id="saveConfigButton" class="toggle-button" style="margin-top: 10px;">Save Configuration</button> | ||
</div> | ||
|
||
<button id="toggleAllButton" class="toggle-all-button">Expand All Details</button> | ||
|
||
<div id="statusMessage" style="display: none; text-align: center; margin-top: 20px; color: grey;"> | ||
<!-- Dynamically generated message data will appear here --> | ||
</div> | ||
|
||
<div id="reportContainer"> | ||
<!-- Dynamically generated node data will appear here --> | ||
</div> | ||
|
||
<script src="helpers.js"></script> | ||
<script src="toggleFunctions.js"></script> | ||
<script src="ui.js"></script> | ||
<script src="app.js"></script> | ||
<script src="eventHandlers.js"></script> | ||
</body> | ||
</html> | ||
|
Oops, something went wrong.