{% extends "base.html" %} {% block title %}Dashboard{% endblock %} {% block breadcrumb %}Dashboard{% endblock %} {% block content %} {# ═══════════════════════════════════════════════════════════════════ AQUILIA ADMIN — INDUSTRY-GRADE DASHBOARD Greeting → Health bar → Stat cards → Grid (charts, activity, model distribution, active users, environment, quick access) ═══════════════════════════════════════════════════════════════════ #} {# ── Personalised greeting with time-of-day ── #}

Welcome back, {{ identity_name }}

Here's what's happening across your application

{# ── System health bar ── #} {% set health = system_health %} {% if health.checks is defined and health.checks|length > 0 %}
System {% for check in health.checks %}
{{ check.name }} {% if check.detail is defined %} {{ check.detail }} {% endif %}
{% endfor %}
{% endif %} {# ── Mega Search trigger bar ── #} {# ═══ METRIC CARDS ROW ═══════════════════════════════════════════ #}
Overview
0
Models
{{ app_list|length }} app{{ 's' if app_list|length != 1 else '' }} registered
0
Records
Across all models
0
Audit Events
{% if audit_summary.logins_24h is defined and audit_summary.logins_24h > 0 %} ↑ {{ audit_summary.logins_24h }} logins today {% else %} All-time entries {% endif %}
0
Logins
{% if audit_summary.failed_logins is defined and audit_summary.failed_logins > 0 %} {{ audit_summary.failed_logins }} failed {% else %} No failed attempts {% endif %}
{# ═══ LIVE STATS ROW — Users Today · Active Sessions · Errors ═══ #}
0
Users Today
{% if audit_summary.unique_users_24h is defined and audit_summary.unique_users_24h > 0 %} {{ audit_summary.unique_users_24h }} unique users {% else %} Unique daily visitors {% endif %}
0
Active Sessions
Currently connected
0
Errors
{% if errors_last_hour is defined and errors_last_hour > 0 %} {{ errors_last_hour }} last hour {% else %} Last 24 hours {% endif %}
0
Active Tasks
{{ tasks_pending|default(0) }} pending
{# ═══ INFRASTRUCTURE OVERVIEW ════════════════════════════════════ #} {% set ac = admin_config|default({}) %} {% set modules = ac.get('modules', {}) if ac is mapping else {} %} {% if modules.get('containers', false) or modules.get('pods', false) %}
Infrastructure
{# ── Docker Containers widget ── #} {% if modules.get('containers', false) %}
Docker Containers Manage →
{% if containers_summary.get('available', false) %}
{{ containers_summary.get('total', 0) }}
Containers
{{ containers_summary.get('running', 0) }} / {{ containers_summary.get('stopped', 0) }}
Running / Stopped
{{ containers_summary.get('images', 0) }} images
{{ containers_summary.get('volumes', 0) }} volumes
{{ containers_summary.get('networks', 0) }} networks
{% if containers_summary.get('version', '') %}
Docker {{ containers_summary.get('version', '') }}
{% endif %} {% elif containers_summary.get('error', '') %}
{{ containers_summary.get('error', 'Docker unavailable') }}
{% else %}
Docker is not available on this host
{% endif %}
{% endif %} {# ── Kubernetes Pods widget ── #} {% if modules.get('pods', false) %}
Kubernetes Manage →
{% if pods_summary.get('available', false) %}
{{ pods_summary.get('running_pods', 0) }} / {{ pods_summary.get('total_pods', 0) }}
Pods Running
{{ pods_summary.get('deployments', 0) }}
Deployments
{{ pods_summary.get('services', 0) }} services
{{ pods_summary.get('namespaces', 0) }} namespaces
{% elif pods_summary.get('error', '') %}
{{ pods_summary.get('error', 'kubectl unavailable') }}
{% else %}
kubectl is not available on this host
{% endif %}
{% endif %}
{% endif %} {# ═══ MLOPS OVERVIEW ══════════════════════════════════════════════ #} {% set mlops = mlops_summary|default({}) %} {% if mlops.get('available', false) or mlops.get('total_models', 0) > 0 %}
MLOps
{# ── Model Registry Summary ── #}
Model Registry Dashboard →
0
Models
0
Inferences
{{ mlops.get('total_errors', 0) }} errors
{% if mlops.get('avg_latency', 0) > 0 %}
{{ "%.1f"|format(mlops.get('avg_latency', 0)) }}ms avg
{% endif %}
{{ mlops.get('inference_history_count', 0) }} history
{% if mlops.get('triggered_alerts_count', 0) > 0 %}
{{ mlops.get('triggered_alerts_count', 0) }} active alert{{ 's' if mlops.get('triggered_alerts_count', 0) != 1 else '' }}
{% endif %}
{# ── Registered Models list ── #}
Registered Models {{ mlops.get('total_models', 0) }} total
{% set mlops_models = mlops.get('models', []) %} {% if mlops_models|length > 0 %}
{% for m in mlops_models %}
{{ m.name }}
{{ m.version }}{% if m.framework %} · {{ m.framework }}{% endif %}
{% set state = m.state|lower %} {% if state in ('serving', 'active', 'running', 'ready') %} {{ m.state }} {% elif state in ('idle', 'loaded', 'registered') %} {{ m.state }} {% elif state in ('error', 'failed', 'unhealthy') %} {{ m.state }} {% else %} {{ m.state }} {% endif %}
{% endfor %}
{% if mlops.get('total_models', 0) > mlops_models|length %}
+ {{ mlops.get('total_models', 0) - mlops_models|length }} more models →
{% endif %} {% else %}
No ML models registered
{% endif %}
{% endif %} {# ═══ ORM OVERVIEW ═══════════════════════════════════════════════ #} {% set orm = orm_metadata|default({}) %} {% set orm_stats = orm.get('stats', {}) %} {% set orm_db = orm.get('database', {}) %} {% set orm_backend = orm.get('backend', {}) %} {% set orm_dep_graph = orm.get('dependency_graph', {}) %} {% set orm_models = orm.get('models', []) %} {% if orm_stats.get('total_models', 0) > 0 %}
ORM Overview
{# ── Row 1: Database info + Schema stats ── #}
{# ── Database Backend card ── #}
Database Backend ORM →
{% if orm_db.get('dialect', '') %}
{% set dialect = orm_db.get('dialect', '')|lower %} {% if 'sqlite' in dialect %} {% elif 'postgres' in dialect %} {% elif 'mysql' in dialect %} {% elif 'oracle' in dialect %} {% else %} {% endif %}
{{ orm_db.get('dialect', 'Unknown') }}
{{ orm_db.get('driver', '') }}
{% if orm_db.get('connected', false) %}
Connected
{% endif %}
{% if orm_db.get('url', '') %}
{{ orm_db.get('url', '') }}
{% endif %} {% if orm_db.get('config_type', '') %}
Config: {{ orm_db.get('config_type', '') }}
{% endif %} {% else %}
No database configured
{% endif %}
{# ── Schema Stats card ── #}
Schema Stats
0
Fields
0
Relations
0
Indexes
0
Constraints
0
M2M Fields
{# ── Row 2: Backend capabilities + Model dependency overview ── #}
{# ── Backend Capabilities card ── #} {% if orm_backend|length > 0 %}
Backend Capabilities
{% set capabilities = [ ('RETURNING', orm_backend.get('supports_returning', false)), ('JSON', orm_backend.get('supports_json', false)), ('Arrays', orm_backend.get('supports_arrays', false)), ('Upsert', orm_backend.get('supports_upsert', false)), ('Window Fn', orm_backend.get('supports_window_functions', false)), ('CTE', orm_backend.get('supports_cte', false)), ('Partial Idx', orm_backend.get('supports_partial_indexes', false)), ('Transactions', orm_backend.get('supports_transactions', false)), ] %}
{% for cap_name, cap_val in capabilities %}
{% if cap_val %}
{% else %}
{% endif %} {{ cap_name }}
{% endfor %}
{% if orm_backend.get('param_style', '') %}
Param style: {{ orm_backend.get('param_style', '?') }} {% if orm_backend.get('max_identifier_length', 0) > 0 %}  ·  Max identifier: {{ orm_backend.get('max_identifier_length', 0) }} {% endif %}
{% endif %}
{% endif %} {# ── Model Dependencies card ── #}
Model Dependencies Full graph →
{% set has_deps = false %} {% for model_name, deps in orm_dep_graph.items() %} {% if deps|length > 0 %}{% set has_deps = true %}{% endif %} {% endfor %} {% set dep_models = [] %} {% for model_name, deps in orm_dep_graph.items() %} {% if deps|length > 0 %} {% if dep_models.append({'name': model_name, 'deps': deps}) %}{% endif %} {% endif %} {% endfor %} {% if dep_models|length > 0 %}
{% for item in dep_models[:6] %}
{{ item.name }}
{% for dep in item.deps %} {{ dep }} {% endfor %}
{% endfor %} {% if dep_models|length > 6 %}
+ {{ dep_models|length - 6 }} more with dependencies
{% endif %}
{% else %}
No inter-model dependencies (FK/M2M)
{% endif %}
{# ── Row 3: Model summary table (condensed) ── #} {% if orm_models|length > 0 %}
Model Schema Summary {{ orm_models|length }} model{{ 's' if orm_models|length != 1 else '' }}
{% for m in orm_models %} {% endfor %}
Model Table Fields Relations Indexes PK
{{ m.name }} {% if m.get('app_label', '') %} {{ m.app_label }} {% endif %} {{ m.table }} {{ m.field_count }} {% if m.relation_count > 0 %} {{ m.relation_count }} {% else %} {% endif %} {% if m.index_count > 0 %} {{ m.index_count }} {% else %} {% endif %} {{ m.pk }}
{% endif %} {% endif %} {# ═══ STORAGE OVERVIEW ═══════════════════════════════════════════ #} {% set sto = storage_summary|default({}) %} {% if sto.get('available', false) %}
Storage
{# ── Storage Summary Card ── #}
Storage Overview Dashboard →
0
Backends
0
Files
{{ sto.get('total_size_human', '0 B') }}
Total Size
{% if sto.get('unhealthy_count', 0) == 0 %} All {{ sto.get('total_backends', 0) }} healthy {% else %} {{ sto.get('unhealthy_count', 0) }} unhealthy {% endif %}
Default: {{ sto.get('default_alias', 'default') }}
{# ── Backend Breakdown Card ── #}
Backend Breakdown {{ sto.get('total_backends', 0) }} total
{% set sto_backends = sto.get('backends', []) %} {% if sto_backends|length > 0 %}
{% for b in sto_backends %}
{{ b.get('alias', '') }}
{{ b.get('type', '') }} · {{ b.get('file_count', 0) }} files · {{ b.get('size_human', '0 B') }}
{% if b.get('healthy', false) %} HEALTHY {% else %} DOWN {% endif %}
{% endfor %}
{% else %}
No storage backends configured
{% endif %}
{% endif %} {# ═══ MAIN DASHBOARD GRID ═══════════════════════════════════════ #}
Analytics
{# ── LEFT: Activity breakdown (donut + legend) ── #}
Activity Breakdown
{# SVG Donut chart #} {% set creates = audit_summary.creates|default(0) %} {% set updates = audit_summary.updates|default(0) %} {% set deletes = audit_summary.deletes|default(0) %} {% set logins = audit_summary.logins|default(0) %} {% set exports = audit_summary.exports|default(0) %} {% set total_act = creates + updates + deletes + logins + exports %}
{% if total_act > 0 %} {% set r = 15.9 %} {% set circ = 99.9 %} {% set p_create = (creates / total_act * 100) %} {% set p_update = (updates / total_act * 100) %} {% set p_delete = (deletes / total_act * 100) %} {% set p_login = (logins / total_act * 100) %} {% set off1 = 25 %} {% set off2 = off1 - p_create * circ / 100 %} {% set off3 = off2 - p_update * circ / 100 %} {% set off4 = off3 - p_delete * circ / 100 %} {% endif %}
{{ total_act }} Events
{# Legend #}
Creates {{ creates }}
Updates {{ updates }}
Deletes {{ deletes }}
Logins {{ logins }}
Exports {{ exports }}
{# ── RIGHT: Hourly activity chart ── #}
Activity — Last 24h
{% set hourly = audit_summary.hourly_activity|default({}) %} {% if hourly|length > 0 %} {% set max_h = hourly.values()|max if hourly.values()|list|length > 0 else 1 %}
{% for hour, count in hourly.items() %}
{% if loop.index0 % 4 == 0 %} {{ hour }} {% endif %}
{% endfor %}
{% else %}
No activity in the last 24 hours
{% endif %}
{# ── LEFT: Top models by record count ── #}
Top Models View all →
{% set colors = ['green', 'blue', 'purple', 'amber', 'green', 'blue'] %} {% if top_models|length > 0 %} {% set max_count = top_models[0].count if top_models[0].count > 0 else 1 %} {% for model in top_models %}
{{ model.count }}
{% endfor %} {% else %}
No models registered
{% endif %}
{# ── RIGHT: Active users ── #}
Most Active Users Manage →
{% if active_users|length > 0 %} {% for user in active_users %}
{{ user.username[:1]|upper }}
{{ user.username }}
{% endfor %} {% else %}
No user activity recorded yet
{% endif %}
{# ═══ RECENT ACTIVITY TIMELINE ══════════════════════════════════ #}
Recent Activity
{% if recent_actions %}
{% for entry in recent_actions[:10] %}
{% set dot_cls = 'create' if entry.action in ('create', 'login') else ('update' if entry.action in ('update', 'bulk_action') else ('delete' if entry.action == 'delete' else 'login')) %}
{% set action_cls = 'audit-create' if entry.action in ('create', 'login') else ('audit-update' if entry.action in ('update', 'bulk_action') else ('audit-delete' if entry.action == 'delete' else 'audit-login')) %} {{ entry.action }} {{ entry.username|default('') }} {% if entry.model_name %}on {{ entry.model_name }}{% endif %} {% if entry.record_pk %} #{{ entry.record_pk }} {% endif %} {{ entry.timestamp|default('')|string|truncate(19, True, '') }}
{% endfor %}
{% if audit_summary.total_entries|default(0) > 10 %}
View all {{ audit_summary.total_entries }} audit entries →
{% endif %}
{% else %}
No recent activity recorded yet
{% endif %} {# ═══ QUICK ACCESS + ENVIRONMENT ════════════════════════════════ #}
{# ── Quick Access navigation cards ── #}
{# ── Environment info panel ── #}
Python
{{ environment.python_version|default('--') }}
Platform
{{ environment.platform|default('--') }}
Arch
{{ environment.architecture|default('--') }}
Uptime
{{ environment.uptime|default('--') }}
Memory
{{ environment.memory_mb|default('--') }} MB
PID
{{ environment.pid|default('--') }}
{# ═══ REGISTERED MODELS TABLE ═══════════════════════════════════ #} {% if app_list %}
Registered Models
{% for app_info in app_list %} {% for model_info in app_info.models|default([]) %} {% endfor %} {% endfor %}
Model App Records Actions
{{ model_info.verbose_name|default(model_info.name|default('')) }} {{ app_info.app_label|default('') }} {{ model_counts.get(model_info.model_name|default(''), '?') if model_counts is mapping else '?' }} Add
{% endif %} {% endblock %} {% block extra_js %} // ── Animated stat counters ── (function() { document.querySelectorAll('[data-count]').forEach(function(el) { var target = parseInt(el.getAttribute('data-count'), 10); if (isNaN(target) || target <= 0) { el.textContent = target || '0'; return; } var duration = 900; var start = null; function step(ts) { if (!start) start = ts; var progress = Math.min((ts - start) / duration, 1); var ease = 1 - Math.pow(1 - progress, 3); el.textContent = Math.floor(ease * target).toLocaleString(); if (progress < 1) requestAnimationFrame(step); else el.textContent = target.toLocaleString(); } requestAnimationFrame(step); }); })(); // ── Relative timestamps ── (function() { function relativeTime(ts) { if (!ts) return ''; var d = new Date(ts); if (isNaN(d.getTime())) return ts; var now = Date.now(); var diff = (now - d.getTime()) / 1000; if (diff < 60) return 'just now'; if (diff < 3600) return Math.floor(diff / 60) + 'm ago'; if (diff < 86400) return Math.floor(diff / 3600) + 'h ago'; if (diff < 604800) return Math.floor(diff / 86400) + 'd ago'; return ts.substring(0, 10); } document.querySelectorAll('[data-timestamp]').forEach(function(el) { var ts = el.getAttribute('data-timestamp'); var rel = relativeTime(ts); if (rel) el.textContent = rel; }); })(); // ── Greeting based on time of day ── (function() { var h = new Date().getHours(); var g = h < 12 ? 'Good morning' : (h < 17 ? 'Good afternoon' : 'Good evening'); var el = document.getElementById('dash-greeting-text'); if (el) el.textContent = g; // Date display var dateEl = document.getElementById('dash-date'); if (dateEl) { var now = new Date(); var opts = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }; dateEl.textContent = '— ' + now.toLocaleDateString(undefined, opts); } })(); // ── Live clock in health bar ── (function() { var clockEl = document.getElementById('dash-clock'); if (!clockEl) return; function tick() { var now = new Date(); clockEl.textContent = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' }); } tick(); setInterval(tick, 1000); })(); // ── Model card hover glow tracking ── (function() { document.querySelectorAll('.model-card, .quick-access-card').forEach(function(card) { card.addEventListener('mousemove', function(e) { var rect = card.getBoundingClientRect(); card.style.setProperty('--mouse-x', (e.clientX - rect.left) + 'px'); card.style.setProperty('--mouse-y', (e.clientY - rect.top) + 'px'); }); }); })(); // ── Distribution bars animate on scroll ── (function() { var observer = new IntersectionObserver(function(entries) { entries.forEach(function(e) { if (e.isIntersecting) { e.target.style.transition = 'width 0.8s cubic-bezier(0.4,0,0.2,1)'; } }); }, { threshold: 0.2 }); document.querySelectorAll('.dist-bar-fill').forEach(function(bar) { observer.observe(bar); }); })(); // ── Dashboard search bar pulse animation ── (function() { var bar = document.querySelector('.dash-search-bar'); if (!bar) return; bar.addEventListener('mouseenter', function() { this.classList.add('dash-search-hover'); }); bar.addEventListener('mouseleave', function() { this.classList.remove('dash-search-hover'); }); })(); {% endblock %}