Dateien
Hetzner-Backup/v2_adminpanel/templates/monitoring/analytics.html

358 Zeilen
11 KiB
HTML

{% extends "base.html" %}
{% block title %}Analytics{% endblock %}
{% block extra_css %}
<style>
.analytics-card {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
margin-bottom: 20px;
height: 100%;
}
.chart-container {
position: relative;
height: 300px;
margin-top: 20px;
}
.stat-box {
text-align: center;
padding: 15px;
background: #f8f9fa;
border-radius: 8px;
margin-bottom: 15px;
}
.stat-value {
font-size: 2rem;
font-weight: bold;
color: #495057;
}
.stat-label {
font-size: 0.875rem;
color: #6c757d;
text-transform: uppercase;
margin-top: 5px;
}
.trend-up {
color: #28a745;
}
.trend-down {
color: #dc3545;
}
.date-range-selector {
background: white;
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
}
.export-buttons {
margin-top: 20px;
}
.grafana-info {
background: #e7f3ff;
border: 1px solid #b3d9ff;
padding: 15px;
border-radius: 8px;
margin-bottom: 20px;
}
</style>
{% endblock %}
{% block content %}
<div class="row mb-4">
<div class="col">
<h2><i class="bi bi-bar-chart-line"></i> Analytics</h2>
<p class="text-muted">Detaillierte Analyse und Berichte</p>
</div>
</div>
<!-- Grafana Integration Info -->
<div class="grafana-info">
<div class="row align-items-center">
<div class="col-md-8">
<h5><i class="bi bi-graph-up"></i> Erweiterte Analytics verfügbar</h5>
<p class="mb-0">Für detaillierte Dashboards und erweiterte Analysen nutzen Sie unser Grafana Dashboard.</p>
</div>
<div class="col-md-4 text-end">
<a href="http://localhost:3000/d/license-server-overview" target="_blank" class="btn btn-primary">
<i class="bi bi-box-arrow-up-right"></i> Grafana öffnen
</a>
</div>
</div>
</div>
<!-- Date Range Selector -->
<div class="date-range-selector">
<div class="row align-items-center">
<div class="col-md-6">
<label>Zeitraum auswählen:</label>
<select class="form-select" id="date-range" onchange="updateAnalytics()">
<option value="today">Heute</option>
<option value="week" selected>Letzte 7 Tage</option>
<option value="month">Letzte 30 Tage</option>
<option value="quarter">Letztes Quartal</option>
<option value="year">Letztes Jahr</option>
</select>
</div>
<div class="col-md-6 text-end">
<button class="btn btn-outline-primary" onclick="refreshAnalytics()">
<i class="bi bi-arrow-clockwise"></i> Aktualisieren
</button>
</div>
</div>
</div>
<!-- Key Metrics Overview -->
<div class="row mb-4">
<div class="col-md-3">
<div class="stat-box">
<div class="stat-value">1,234</div>
<div class="stat-label">Aktive Lizenzen</div>
<div class="trend-up">
<i class="bi bi-arrow-up"></i> +12% vs. Vormonat
</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-box">
<div class="stat-value">45.2K</div>
<div class="stat-label">Validierungen</div>
<div class="trend-up">
<i class="bi bi-arrow-up"></i> +8% vs. Vormonat
</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-box">
<div class="stat-value">€12.5K</div>
<div class="stat-label">MRR</div>
<div class="trend-up">
<i class="bi bi-arrow-up"></i> +15% vs. Vormonat
</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-box">
<div class="stat-value">2.3%</div>
<div class="stat-label">Churn Rate</div>
<div class="trend-down">
<i class="bi bi-arrow-down"></i> -0.5% vs. Vormonat
</div>
</div>
</div>
</div>
<!-- Charts Row 1 -->
<div class="row">
<div class="col-md-6">
<div class="analytics-card">
<h5>Lizenz-Nutzung über Zeit</h5>
<div class="chart-container">
<canvas id="usageChart"></canvas>
</div>
</div>
</div>
<div class="col-md-6">
<div class="analytics-card">
<h5>Validierungen nach Stunde</h5>
<div class="chart-container">
<canvas id="validationChart"></canvas>
</div>
</div>
</div>
</div>
<!-- Charts Row 2 -->
<div class="row mt-4">
<div class="col-md-4">
<div class="analytics-card">
<h5>Lizenztyp-Verteilung</h5>
<div class="chart-container">
<canvas id="licenseTypeChart"></canvas>
</div>
</div>
</div>
<div class="col-md-4">
<div class="analytics-card">
<h5>Geografische Verteilung</h5>
<div class="chart-container">
<canvas id="geoChart"></canvas>
</div>
</div>
</div>
<div class="col-md-4">
<div class="analytics-card">
<h5>Top 10 Kunden</h5>
<div style="height: 300px; overflow-y: auto;">
<table class="table table-sm">
<thead>
<tr>
<th>Kunde</th>
<th>Lizenzen</th>
<th>Nutzung</th>
</tr>
</thead>
<tbody>
<tr>
<td>ACME Corp</td>
<td>45</td>
<td><span class="badge bg-success">Hoch</span></td>
</tr>
<tr>
<td>TechStart GmbH</td>
<td>32</td>
<td><span class="badge bg-success">Hoch</span></td>
</tr>
<tr>
<td>Global Solutions</td>
<td>28</td>
<td><span class="badge bg-warning">Mittel</span></td>
</tr>
<!-- More rows... -->
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Export Options -->
<div class="analytics-card mt-4">
<h5>Berichte exportieren</h5>
<div class="export-buttons">
<button class="btn btn-outline-primary me-2" onclick="exportReport('pdf')">
<i class="bi bi-file-pdf"></i> PDF Export
</button>
<button class="btn btn-outline-success me-2" onclick="exportReport('excel')">
<i class="bi bi-file-excel"></i> Excel Export
</button>
<button class="btn btn-outline-info" onclick="exportReport('csv')">
<i class="bi bi-file-text"></i> CSV Export
</button>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.js"></script>
<script>
let usageChart, validationChart, licenseTypeChart, geoChart;
function initCharts() {
// Usage over time
const usageCtx = document.getElementById('usageChart').getContext('2d');
usageChart = new Chart(usageCtx, {
type: 'line',
data: {
labels: ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'],
datasets: [{
label: 'Aktive Lizenzen',
data: [1180, 1205, 1195, 1220, 1234, 1150, 1100],
borderColor: 'rgb(75, 192, 192)',
backgroundColor: 'rgba(75, 192, 192, 0.1)',
tension: 0.1
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
// Validations by hour
const validationCtx = document.getElementById('validationChart').getContext('2d');
validationChart = new Chart(validationCtx, {
type: 'bar',
data: {
labels: ['00', '04', '08', '12', '16', '20'],
datasets: [{
label: 'Validierungen',
data: [120, 80, 450, 680, 520, 340],
backgroundColor: 'rgba(54, 162, 235, 0.5)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
// License type distribution
const typeCtx = document.getElementById('licenseTypeChart').getContext('2d');
licenseTypeChart = new Chart(typeCtx, {
type: 'doughnut',
data: {
labels: ['Professional', 'Enterprise', 'Starter', 'Trial'],
datasets: [{
data: [45, 30, 20, 5],
backgroundColor: [
'rgba(255, 99, 132, 0.5)',
'rgba(54, 162, 235, 0.5)',
'rgba(255, 205, 86, 0.5)',
'rgba(75, 192, 192, 0.5)'
]
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
// Geographic distribution
const geoCtx = document.getElementById('geoChart').getContext('2d');
geoChart = new Chart(geoCtx, {
type: 'bar',
data: {
labels: ['DE', 'AT', 'CH', 'US', 'UK'],
datasets: [{
label: 'Aktive Nutzer',
data: [580, 230, 180, 120, 90],
backgroundColor: 'rgba(153, 102, 255, 0.5)',
borderColor: 'rgba(153, 102, 255, 1)',
borderWidth: 1
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
indexAxis: 'y'
}
});
}
function updateAnalytics() {
const range = document.getElementById('date-range').value;
// In production, this would fetch new data based on the selected range
console.log('Updating analytics for range:', range);
}
function refreshAnalytics() {
// Refresh all data
location.reload();
}
function exportReport(format) {
alert(`Exporting report as ${format.toUpperCase()}...`);
// In production, this would trigger actual export
}
// Initialize charts on page load
document.addEventListener('DOMContentLoaded', function() {
initCharts();
});
</script>
{% endblock %}