2025-08-12 13:33:25 +03:00

458 lines
19 KiB
HTML

{% extends 'base.html' %}
{% load static %}
{% block title %}Analytics Dashboard{% endblock %}
{% block css %}
<style>
.stat-card {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border-radius: 15px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
}
.stat-card.success {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
.stat-card.warning {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
.stat-card.danger {
background: linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%);
}
.stat-card.info {
background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
}
.stat-number {
font-size: 2.5rem;
font-weight: bold;
margin-bottom: 5px;
}
.stat-label {
font-size: 0.9rem;
opacity: 0.9;
}
.activity-card {
height: 400px;
overflow-y: auto;
}
.dashboard-card {
display: flex;
align-items: center;
padding: 10px;
margin-bottom: 10px;
border-radius: 8px;
background-color: #f8f9fa;
border-left: 4px solid #007bff;
}
.dashboard-icon {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #007bff;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
margin-right: 10px;
}
.execution-status {
padding: 2px 8px;
border-radius: 12px;
font-size: 0.8rem;
font-weight: bold;
}
.execution-status.success {
background-color: #d4edda;
color: #155724;
}
.execution-status.failed {
background-color: #f8d7da;
color: #721c24;
}
.execution-status.running {
background-color: #fff3cd;
color: #856404;
}
.data-source-health {
padding: 4px 8px;
border-radius: 12px;
font-size: 0.8rem;
font-weight: bold;
}
.data-source-health.healthy {
background-color: #d4edda;
color: #155724;
}
.data-source-health.unhealthy {
background-color: #f8d7da;
color: #721c24;
}
.metric-card {
background: white;
border-radius: 8px;
padding: 15px;
margin-bottom: 15px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
border-left: 4px solid #28a745;
}
</style>
{% endblock %}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="d-flex justify-content-between align-items-center mb-4">
<h1 class="h3 mb-0">Analytics Dashboard</h1>
<div class="btn-group" role="group">
<a href="{% url 'analytics:dashboard_create' %}" class="btn btn-success">
<i class="fas fa-plus"></i> New Dashboard
</a>
<a href="{% url 'analytics:report_create' %}" class="btn btn-primary">
<i class="fas fa-file-alt"></i> New Report
</a>
<a href="{% url 'analytics:data_source_create' %}" class="btn btn-info">
<i class="fas fa-database"></i> Add Data Source
</a>
</div>
</div>
</div>
</div>
<!-- Key Performance Indicators -->
<div class="row" hx-get="{% url 'analytics:analytics_stats' %}" hx-trigger="load, every 30s">
<div class="col-md-3">
<div class="stat-card">
<div class="stat-number">{{ total_dashboards }}</div>
<div class="stat-label">Total Dashboards</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-card success">
<div class="stat-number">{{ total_reports }}</div>
<div class="stat-label">Total Reports</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-card info">
<div class="stat-number">{{ total_data_sources }}</div>
<div class="stat-label">Active Data Sources</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-card warning">
<div class="stat-number">{{ total_metrics }}</div>
<div class="stat-label">Metric Definitions</div>
</div>
</div>
</div>
<!-- Execution Statistics -->
<div class="row">
<div class="col-md-3">
<div class="stat-card success">
<div class="stat-number">{{ executions_today }}</div>
<div class="stat-label">Executions Today</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-card info">
<div class="stat-number">{{ successful_executions }}</div>
<div class="stat-label">Successful Today</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-card danger">
<div class="stat-number">{{ failed_executions }}</div>
<div class="stat-label">Failed Today</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-card">
<div class="stat-number">{{ healthy_data_sources }}</div>
<div class="stat-label">Healthy Sources</div>
</div>
</div>
</div>
<!-- Recent Activity and Dashboard Information -->
<div class="row">
<div class="col-md-6">
<div class="card activity-card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">Recent Dashboards</h5>
<a href="{% url 'analytics:dashboard_list' %}" class="btn btn-sm btn-outline-primary">View All</a>
</div>
<div class="card-body">
{% if recent_dashboards %}
{% for dashboard in recent_dashboards %}
<div class="dashboard-card">
<div class="dashboard-icon">
<i class="fas fa-chart-bar"></i>
</div>
<div class="flex-grow-1">
<strong>
<a href="{% url 'analytics:dashboard_detail' dashboard.pk %}">
{{ dashboard.dashboard_name }}
</a>
</strong>
<br>
<small class="text-muted">{{ dashboard.get_category_display }} - {{ dashboard.get_visibility_display }}</small>
</div>
<div class="text-right">
<div class="text-success font-weight-bold">{{ dashboard.created_at|date:"M d" }}</div>
<small class="text-muted">Created</small>
</div>
</div>
{% endfor %}
{% else %}
<p class="text-muted">No recent dashboards.</p>
{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="card activity-card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">Recent Reports</h5>
<a href="{% url 'analytics:report_list' %}" class="btn btn-sm btn-outline-primary">View All</a>
</div>
<div class="card-body">
{% if recent_reports %}
{% for report in recent_reports %}
<div class="dashboard-card">
<div class="dashboard-icon">
<i class="fas fa-file-alt"></i>
</div>
<div class="flex-grow-1">
<strong>
<a href="{% url 'analytics:report_detail' report.pk %}">
{{ report.report_name }}
</a>
</strong>
<br>
<small class="text-muted">{{ report.get_category_display }} - {{ report.data_source.source_name }}</small>
</div>
<div class="text-right">
<div class="text-success font-weight-bold">{{ report.created_at|date:"M d" }}</div>
<small class="text-muted">Created</small>
</div>
</div>
{% endfor %}
{% else %}
<p class="text-muted">No recent reports.</p>
{% endif %}
</div>
</div>
</div>
</div>
<!-- Recent Executions and Data Source Health -->
<div class="row mt-4">
<div class="col-md-6">
<div class="card activity-card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">Recent Executions</h5>
<a href="{% url 'analytics:report_execution_list' %}" class="btn btn-sm btn-outline-primary">View All</a>
</div>
<div class="card-body">
{% if recent_executions %}
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>Report</th>
<th>Status</th>
<th>Duration</th>
<th>Time</th>
</tr>
</thead>
<tbody>
{% for execution in recent_executions %}
<tr>
<td>
<a href="{% url 'analytics:report_execution_detail' execution.pk %}">
{{ execution.report.report_name|truncatechars:20 }}
</a>
</td>
<td>
<span class="execution-status {% if execution.status == 'SUCCESS' %}success{% elif execution.status == 'FAILED' %}failed{% else %}running{% endif %}">
{{ execution.get_status_display }}
</span>
</td>
<td>
{% if execution.completion_time %}
{{ execution.completion_time|timesince:execution.execution_time }}
{% else %}
-
{% endif %}
</td>
<td>{{ execution.execution_time|date:"H:i" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p class="text-muted">No recent executions.</p>
{% endif %}
</div>
</div>
</div>
<div class="col-md-6">
<div class="card activity-card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">Data Source Health</h5>
<a href="{% url 'analytics:data_source_list' %}" class="btn btn-sm btn-outline-primary">View All</a>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<div class="metric-card">
<div class="d-flex justify-content-between align-items-center">
<div>
<h4 class="text-success mb-0">{{ healthy_data_sources }}</h4>
<small class="text-muted">Healthy Sources</small>
</div>
<i class="fas fa-check-circle fa-2x text-success"></i>
</div>
</div>
</div>
<div class="col-md-6">
<div class="metric-card" style="border-left-color: #dc3545;">
<div class="d-flex justify-content-between align-items-center">
<div>
<h4 class="text-danger mb-0">{{ unhealthy_data_sources }}</h4>
<small class="text-muted">Unhealthy Sources</small>
</div>
<i class="fas fa-exclamation-circle fa-2x text-danger"></i>
</div>
</div>
</div>
</div>
<!-- Quick health check actions -->
<div class="mt-3">
<button class="btn btn-sm btn-outline-success" onclick="testAllDataSources()">
<i class="fas fa-heartbeat"></i> Test All Sources
</button>
<button class="btn btn-sm btn-outline-info" onclick="refreshHealthStatus()">
<i class="fas fa-sync"></i> Refresh Status
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Quick Actions -->
<div class="row mt-4">
<div class="col-12">
<div class="card">
<div class="card-header">
<h5 class="mb-0">Quick Actions</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-2">
<a href="{% url 'analytics:dashboard_list' %}" class="btn btn-outline-primary btn-block">
<i class="fas fa-chart-bar"></i><br>
All Dashboards
</a>
</div>
<div class="col-md-2">
<a href="{% url 'analytics:report_list' %}" class="btn btn-outline-success btn-block">
<i class="fas fa-file-alt"></i><br>
All Reports
</a>
</div>
<div class="col-md-2">
<a href="{% url 'analytics:data_source_list' %}" class="btn btn-outline-info btn-block">
<i class="fas fa-database"></i><br>
Data Sources
</a>
</div>
<div class="col-md-2">
<a href="{% url 'analytics:metric_definition_list' %}" class="btn btn-outline-warning btn-block">
<i class="fas fa-tachometer-alt"></i><br>
Metrics
</a>
</div>
<div class="col-md-2">
<a href="{% url 'analytics:report_execution_list' %}" class="btn btn-outline-secondary btn-block">
<i class="fas fa-play"></i><br>
Executions
</a>
</div>
<div class="col-md-2">
<a href="{% url 'analytics:dashboard_widget_list' %}" class="btn btn-outline-dark btn-block">
<i class="fas fa-th"></i><br>
Widgets
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Performance Summary -->
<div class="row mt-4">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h5 class="mb-0">System Performance Summary</h5>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-3">
<div class="text-center">
<h3 class="text-primary">{{ total_dashboards }}</h3>
<p class="text-muted">Active Dashboards</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<h3 class="text-success">{{ total_reports }}</h3>
<p class="text-muted">Available Reports</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<h3 class="text-info">{{ executions_today }}</h3>
<p class="text-muted">Executions Today</p>
</div>
</div>
<div class="col-md-3">
<div class="text-center">
<h3 class="text-warning">{{ total_metrics }}</h3>
<p class="text-muted">Tracked Metrics</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function testAllDataSources() {
// Implement AJAX call to test all data sources
alert('Testing all data sources...');
}
function refreshHealthStatus() {
// Implement AJAX call to refresh health status
location.reload();
}
</script>
{% endblock %}