170 lines
4.2 KiB
HTML
170 lines
4.2 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="it">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>Cloudflare DDNS Status</title>
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<style>
|
||
/* Stile generale */
|
||
body {
|
||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||
background: #121212;
|
||
color: #e0e0e0;
|
||
margin: 0;
|
||
padding: 0;
|
||
}
|
||
header {
|
||
background: #1f1f1f;
|
||
padding: 20px;
|
||
text-align: center;
|
||
font-size: 1.7em;
|
||
font-weight: bold;
|
||
color: #00bcd4;
|
||
box-shadow: 0 2px 5px rgba(0,0,0,0.5);
|
||
}
|
||
main {
|
||
padding: 20px;
|
||
max-width: 1000px;
|
||
margin: auto;
|
||
}
|
||
table {
|
||
width: 100%;
|
||
border-collapse: separate;
|
||
border-spacing: 0 10px; /* Spazi tra le righe */
|
||
}
|
||
th {
|
||
background: #1f1f1f;
|
||
color: #00bcd4;
|
||
font-weight: bold;
|
||
text-transform: uppercase;
|
||
font-size: 0.9em;
|
||
text-align: center;
|
||
padding: 12px;
|
||
border-radius: 8px 8px 0 0;
|
||
}
|
||
td {
|
||
background: #1a1a1a;
|
||
text-align: center;
|
||
padding: 12px;
|
||
color: #e0e0e0;
|
||
border-radius: 8px;
|
||
transition: all 0.3s ease;
|
||
}
|
||
tr:hover td {
|
||
background: #272727;
|
||
transform: scale(1.02);
|
||
}
|
||
.badge {
|
||
display: inline-block;
|
||
padding: 5px 12px;
|
||
border-radius: 20px;
|
||
font-weight: bold;
|
||
font-size: 0.85em;
|
||
}
|
||
.ok {
|
||
background: linear-gradient(45deg, #4caf50, #81c784);
|
||
color: #fff;
|
||
}
|
||
.bad {
|
||
background: linear-gradient(45deg, #ff5252, #ff8a65);
|
||
color: #fff;
|
||
}
|
||
.time {
|
||
color: #9e9e9e;
|
||
font-size: 0.85em;
|
||
}
|
||
footer {
|
||
text-align: center;
|
||
padding: 15px;
|
||
font-size: 0.85em;
|
||
color: #777;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<header>Cloudflare DDNS – Stato DNS</header>
|
||
|
||
<main>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Record</th>
|
||
<th>DNS IP</th>
|
||
<th>IP Pubblico</th>
|
||
<th>Proxy</th>
|
||
<th>Stato</th>
|
||
<th>Ultimo aggiornamento</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for r in records %}
|
||
<tr>
|
||
<td>{{ r.name }}</td>
|
||
<td>{{ r.dns_ip }}</td>
|
||
<td>{{ r.public_ip }}</td>
|
||
<td>{{ "ON" if r.proxied else "OFF" }}</td>
|
||
<td><span class="badge {{ 'ok' if r.status == 'OK' else 'bad' }}">{{ r.status }}</span></td>
|
||
<td class="time" data-timestamp="{{ r.last_updated }}">{{ r.last_updated_human }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</main>
|
||
|
||
<footer id="status">
|
||
Visualizzazione aggiornata ogni {{ refresh_seconds }} secondi | Ultimo aggiornamento: <span id="last-update">ora</span>
|
||
</footer>
|
||
|
||
<script>
|
||
function timeAgo(date) {
|
||
const seconds = Math.floor((new Date() - new Date(date)) / 1000);
|
||
let interval = Math.floor(seconds / 86400);
|
||
if (interval >= 1) return interval + " giorni fa";
|
||
interval = Math.floor(seconds / 3600);
|
||
if (interval >= 1) return interval + " ore fa";
|
||
interval = Math.floor(seconds / 60);
|
||
if (interval >= 1) return interval + " minuti fa";
|
||
return "pochi secondi fa";
|
||
}
|
||
|
||
function updateTimeAgo() {
|
||
document.querySelectorAll('.time').forEach(td => {
|
||
td.textContent = timeAgo(td.dataset.timestamp);
|
||
});
|
||
}
|
||
|
||
function updateRecords() {
|
||
fetch('/api/records')
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
if (data.success) {
|
||
const tbody = document.querySelector('tbody');
|
||
tbody.innerHTML = data.records.map(r => `
|
||
<tr>
|
||
<td>${r.name}</td>
|
||
<td>${r.dns_ip}</td>
|
||
<td>${r.public_ip}</td>
|
||
<td>${r.proxied ? 'ON' : 'OFF'}</td>
|
||
<td><span class="badge ${r.status === 'OK' ? 'ok' : 'bad'}">${r.status}</span></td>
|
||
<td class="time" data-timestamp="${r.last_updated}">${timeAgo(r.last_updated)}</td>
|
||
</tr>
|
||
`).join('');
|
||
document.getElementById('last-update').textContent = new Date().toLocaleTimeString('it-IT');
|
||
}
|
||
})
|
||
.catch(err => {
|
||
console.error('Errore aggiornamento:', err);
|
||
document.getElementById('status').style.color = '#ff5252';
|
||
});
|
||
}
|
||
|
||
// Init
|
||
updateTimeAgo();
|
||
setInterval(updateTimeAgo, 5000);
|
||
setInterval(updateRecords, {{ refresh_seconds }} * 1000);
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|