130 lines
No EOL
5.1 KiB
HTML
130 lines
No EOL
5.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<title>MinIPAM</title>
|
|
<style>
|
|
.status_online {
|
|
background-color: lawngreen;
|
|
color: black;
|
|
}
|
|
.status_offline {
|
|
background-color: orangered;
|
|
color: black;
|
|
}
|
|
.status_free {
|
|
background-color: dimgray;
|
|
color: black;
|
|
}
|
|
body {
|
|
background-color: black;
|
|
color: white;
|
|
}
|
|
</style>
|
|
<script>
|
|
function formatHumanFriendlyTime(timestamp) {
|
|
const now = new Date();
|
|
const time = new Date(timestamp);
|
|
|
|
// Calculate the difference in milliseconds
|
|
const diffMilliseconds = now - time;
|
|
|
|
// Convert milliseconds to seconds
|
|
const diffSeconds = Math.floor(diffMilliseconds / 1000);
|
|
|
|
// Define time thresholds in seconds
|
|
const minuteThreshold = 60;
|
|
const hourThreshold = 3600;
|
|
const dayThreshold = 86400;
|
|
|
|
// Format the time relative to the current moment
|
|
if (diffSeconds < minuteThreshold) {
|
|
return `${diffSeconds} seconds ago`;
|
|
} else if (diffSeconds < hourThreshold) {
|
|
const minutes = Math.floor(diffSeconds / 60);
|
|
return `${minutes} minute${minutes > 1 ? 's' : ''} ago`;
|
|
} else if (diffSeconds < dayThreshold) {
|
|
const hours = Math.floor(diffSeconds / 3600);
|
|
return `${hours} hour${hours > 1 ? 's' : ''} ago`;
|
|
} else {
|
|
const days = Math.floor(diffSeconds / 86400);
|
|
return `${days} day${days > 1 ? 's' : ''} ago`;
|
|
}
|
|
}
|
|
var data = {}
|
|
function start() {
|
|
|
|
let xhr = new XMLHttpRequest();
|
|
xhr.open('GET', '/data');
|
|
xhr.onload = function() {
|
|
if (xhr.status != 200) { // analyze HTTP status of the response
|
|
alert(`Error ${xhr.status}: ${xhr.statusText}`); // e.g. 404: Not Found
|
|
} else { // show the result
|
|
data = JSON.parse(xhr.responseText)
|
|
let last=""
|
|
for (const subnet in data.Subnets) {
|
|
document.getElementById("subnetscontainer").innerHTML+="<button onClick=viewSubnet(this.innerText)>"+subnet+"</button>"
|
|
last=subnet
|
|
}
|
|
if(last != "") {
|
|
viewSubnet(last)
|
|
}
|
|
|
|
}
|
|
};
|
|
xhr.send();
|
|
}
|
|
function viewSubnet(subnet) {
|
|
|
|
usedAddresses = data.Subnets[subnet].used_addresses
|
|
totalAddresses = data.Subnets[subnet].total_addresses
|
|
|
|
document.getElementById("subnetCidrField").innerText=subnet
|
|
document.getElementById("subnetUsedField").innerText=usedAddresses+" of "+totalAddresses
|
|
document.getElementById("subnetUsageBar").max=totalAddresses
|
|
document.getElementById("subnetUsageBar").value=usedAddresses
|
|
|
|
|
|
let tableHTML = '<table border="1"><thead><tr><th>IP Address</th><th>RevDNS</th><th>First seen</th><th>Last seen</th></tr></thead><tbody>';
|
|
|
|
|
|
const hosts = data.Subnets[subnet].hosts;
|
|
|
|
// Iterate over IPs in the subnet
|
|
data.Subnets[subnet].host_list.forEach(ip => {
|
|
const hostDetails = hosts[ip] || {}; // Get host details if available
|
|
|
|
// Determine the status based on the presence in hosts and online status
|
|
let revdns="";
|
|
let ls=""
|
|
let fs=""
|
|
let status;
|
|
if (ip in hosts) {
|
|
status = hostDetails.online ? 'online' : 'offline';
|
|
revdns = hostDetails.rev_dns;
|
|
ls = formatHumanFriendlyTime(hostDetails.last_seen)
|
|
fs = formatHumanFriendlyTime(hostDetails.first_seen)
|
|
|
|
} else {
|
|
status = 'free';
|
|
}
|
|
// Add a row to the HTML table
|
|
tableHTML += `<tr class="status_${status}"><td>${ip}</td><td>${revdns}</td><td>${fs}</td><td>${ls}</td></tr>`;
|
|
});
|
|
|
|
tableHTML += '</tbody></table>';
|
|
document.getElementById("subnetview").innerHTML=""
|
|
document.getElementById("subnetview").innerHTML=tableHTML
|
|
|
|
}
|
|
</script>
|
|
</head>
|
|
<body onLoad="start()">
|
|
Subnets:<br>
|
|
<div id="subnetscontainer"></div>
|
|
<hr>
|
|
<p>Subnet <span id="subnetCidrField"></span></p>
|
|
<p>Space usage <span id="subnetUsedField"></span></p>
|
|
<progress id="subnetUsageBar"></progress><br>
|
|
<div id="subnetview"></div>
|
|
</body>
|
|
</html> |