Files
Server_Monitorizare_v2/templates/dashboard.html
2026-04-23 15:55:46 +03:00

334 lines
11 KiB
HTML

{% extends "base.html" %}
{% block title %}Dashboard - Server Monitoring{% endblock %}
{% block page_title %}Dashboard{% endblock %}
{% block extra_css %}
<style>
.stats-row {
margin-bottom: 30px;
}
.stat-card {
height: 120px;
display: flex;
align-items: center;
padding: 20px;
border-left: 4px solid #3498db;
transition: transform 0.2s ease;
}
.stat-card:hover {
transform: translateY(-2px);
}
.stat-card.devices {
border-left-color: #2ecc71;
}
.stat-card.logs {
border-left-color: #e74c3c;
}
.stat-card.templates {
border-left-color: #f39c12;
}
.stat-card.active {
border-left-color: #9b59b6;
}
.stat-icon {
font-size: 2.5rem;
margin-right: 20px;
}
.stat-details h3 {
margin: 0;
font-size: 2rem;
font-weight: bold;
}
.stat-details p {
margin: 0;
color: #7f8c8d;
font-size: 0.9rem;
}
.refresh-timer {
text-align: center;
margin-bottom: 20px;
font-size: 1.1rem;
color: #2c3e50;
font-weight: 500;
}
.action-buttons {
text-align: center;
margin-bottom: 30px;
}
.action-buttons .btn {
margin: 5px;
}
.recent-logs-section {
margin-top: 30px;
}
.activity-section {
margin-top: 30px;
}
</style>
{% endblock %}
{% block content %}
<!-- Auto-refresh Timer -->
<div class="refresh-timer">
<i class="fas fa-clock"></i>
Time until refresh: <span id="refresh-timer">30</span> seconds
</div>
<!-- Action Buttons -->
<div class="action-buttons">
<a href="{{ url_for('main.devices') }}" class="btn btn-primary">
<i class="fas fa-desktop"></i> Manage Devices
</a>
<a href="{{ url_for('main.logs') }}" class="btn btn-secondary">
<i class="fas fa-list-alt"></i> View All Logs
</a>
<a href="{{ url_for('main.stats') }}" class="btn btn-info">
<i class="fas fa-chart-bar"></i> System Stats
</a>
<a href="{{ url_for('ansible_web.index') }}" class="btn btn-success">
<i class="fas fa-cogs"></i> Automation
</a>
<button class="btn btn-danger" onclick="resetDatabase(event)" title="Clear all logs and reset database">
<i class="fas fa-trash-alt"></i> Clear Database
</button>
</div>
<!-- Activity in Last 24 Hours -->
{% if activity_stats %}
<div class="activity-section">
<h4><i class="fas fa-clock"></i> Last 24 Hours Activity</h4>
<div class="row">
<div class="col-md-6">
<div class="card">
<div class="card-body text-center">
<h5 class="card-title">{{ activity_stats.logs_24h|default(0) }}</h5>
<p class="card-text text-muted">New Log Entries</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="card">
<div class="card-body text-center">
<h5 class="card-title">{{ activity_stats.devices_seen_24h|default(0) }}</h5>
<p class="card-text text-muted">Devices Active</p>
</div>
</div>
</div>
</div>
</div>
{% endif %}
<!-- Recent Logs Section -->
<div class="recent-logs-section">
<h4><i class="fas fa-list-alt"></i> Recent Activity</h4>
<div class="table-container">
<table class="table table-striped table-hover">
<thead class="table-dark">
<tr>
<th width="20%">Device</th>
<th width="15%">IP Address</th>
<th width="15%">Location</th>
<th width="20%">Timestamp</th>
<th width="30%">Event Description</th>
</tr>
</thead>
<tbody>
{% if recent_logs %}
{% for log in recent_logs %}
<tr>
<td>
<a href="{{ url_for('main.device_detail', device_id=log.device_id) }}" class="text-decoration-none">
<strong>{{ log.device.hostname }}</strong>
</a>
</td>
<td>{{ log.device.device_ip }}</td>
<td>
{% if log.device.nume_masa %}
<span class="badge bg-info">{{ log.device.nume_masa }}</span>
{% else %}
<span class="text-muted">-</span>
{% endif %}
</td>
<td>
<small>{{ log.timestamp.strftime('%Y-%m-%d %H:%M:%S') if log.timestamp else 'N/A' }}</small>
</td>
<td>
<span class="badge bg-{% if log.severity == 'error' %}danger{% elif log.severity == 'warning' %}warning{% elif log.severity == 'info' %}primary{% else %}secondary{% endif %}">
{{ log.severity|default('info') }}
</span>
{{ log.resolved_message[:100] }}{% if log.resolved_message|length > 100 %}...{% endif %}
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td colspan="5" class="text-center text-muted py-4">
<i class="fas fa-inbox fa-2x"></i><br>
No recent logs available
</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
{% if recent_logs|length >= 50 %}
<div class="text-center mt-3">
<a href="{{ url_for('main.logs') }}" class="btn btn-outline-primary">
<i class="fas fa-arrow-right"></i> View All Logs
</a>
</div>
{% endif %}
</div>
<!-- Compression Statistics -->
{% if compression_stats %}
<div class="activity-section">
<h4><i class="fas fa-compress-arrows-alt"></i> Compression Statistics</h4>
<div class="row">
<div class="col-md-4">
<div class="card">
<div class="card-body text-center">
<h5 class="card-title">{{ compression_stats.get('average_ratio', 0) | round(1) }}%</h5>
<p class="card-text text-muted">Compression Ratio</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body text-center">
<h5 class="card-title">{{ compression_stats.get('total_saved_bytes', 0) | filesizeformat }}</h5>
<p class="card-text text-muted">Space Saved</p>
</div>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-body text-center">
<h5 class="card-title">{{ compression_stats.get('template_count', 0) }}</h5>
<p class="card-text text-muted">Active Templates</p>
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% endblock %}
{% block extra_js %}
<script>
// Countdown timer for refresh
let countdown = 30; // 30 seconds
function updateTimer() {
const timerElement = document.getElementById('refresh-timer');
if (timerElement) {
timerElement.innerText = countdown;
}
countdown--;
if (countdown < 0) {
location.reload(); // Refresh the page
}
}
// Start the timer immediately
setInterval(updateTimer, 1000); // Update every second
// Database reset functionality
async function resetDatabase(event) {
try {
// First confirmation
const confirmed = confirm(
'⚠️ WARNING: Database Reset Operation ⚠️\n\n' +
'This will permanently delete ALL logs and device history!\n\n' +
'This action cannot be undone!\n\n' +
'Are you sure you want to proceed?'
);
if (!confirmed) {
return;
}
// Second confirmation for safety
const doubleConfirmed = confirm(
'🚨 FINAL CONFIRMATION 🚨\n\n' +
'You are about to permanently DELETE all data!\n\n' +
'This is your LAST CHANCE to cancel!\n\n' +
'Click OK to proceed with deletion.'
);
if (!doubleConfirmed) {
return;
}
// Show loading indicator
const button = event.target;
const originalText = button.innerHTML;
button.innerHTML = '<span class="spinner-border spinner-border-sm" role="status"></span> Clearing Database...';
button.disabled = true;
// Send reset request (this would need to be implemented on the backend)
try {
const response = await fetch('/api/reset-database', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
});
if (response.ok) {
alert('✅ Database cleared successfully!');
location.reload(); // Refresh to show empty database
} else {
throw new Error('Server error: ' + response.statusText);
}
} catch (fetchError) {
alert('❌ Error clearing database: ' + fetchError.message);
}
} catch (error) {
alert('❌ Network Error: ' + error.message);
} finally {
// Restore button
if (event.target) {
event.target.innerHTML = '<i class="fas fa-trash-alt"></i> Clear Database';
event.target.disabled = false;
}
}
}
// Initialize page
document.addEventListener('DOMContentLoaded', function() {
console.log('Dashboard loaded successfully');
// Add hover effects to stat cards
const statCards = document.querySelectorAll('.stat-card');
statCards.forEach(card => {
card.addEventListener('mouseenter', function() {
this.style.boxShadow = '0 4px 20px rgba(0, 0, 0, 0.15)';
});
card.addEventListener('mouseleave', function() {
this.style.boxShadow = '0 2px 10px rgba(0, 0, 0, 0.1)';
});
});
});
</script>
{% endblock %}