283 lines
12 KiB
HTML
283 lines
12 KiB
HTML
{# ==============================================================================
|
|
Formeleon - Multi-tenant Form Generator
|
|
Author: Björn Runden <br@runden.net>
|
|
Template: admin/dashboard.html
|
|
Description: Admin dashboard overview page with statistics and quick access.
|
|
============================================================================== #}
|
|
|
|
{% extends "base.html" %}
|
|
|
|
{% block title %}Dashboard - Formeleon{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="container">
|
|
<div class="row mb-4">
|
|
<div class="col-12">
|
|
<h1><i class="bi bi-speedometer2"></i> Dashboard</h1>
|
|
<p class="text-muted">Welcome, <strong>{{ user.name }}</strong>! | Role: <span class="badge bg-{{ 'primary' if user.role.value == 'admin' else 'secondary' }}">{{ user.role.value }}</span></p>
|
|
</div>
|
|
</div>
|
|
|
|
{# Statistics Cards #}
|
|
<div class="row mb-4">
|
|
<div class="col-md-3 col-6 mb-3">
|
|
<div class="card bg-primary text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<i class="bi bi-buildings display-6"></i>
|
|
<div class="ms-3">
|
|
<h3 class="mb-0">{{ tenant_count }}</h3>
|
|
<p class="mb-0">Tenants</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-3 col-6 mb-3">
|
|
<div class="card bg-success text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<i class="bi bi-file-earmark-text display-6"></i>
|
|
<div class="ms-3">
|
|
<h3 class="mb-0">{{ form_count }}</h3>
|
|
<p class="mb-0">Forms</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-3 col-6 mb-3">
|
|
<div class="card bg-info text-white">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<i class="bi bi-inbox display-6"></i>
|
|
<div class="ms-3">
|
|
<h3 class="mb-0">{{ submission_count }}</h3>
|
|
<p class="mb-0">Submissions</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-3 col-6 mb-3">
|
|
<div class="card bg-warning text-dark">
|
|
<div class="card-body">
|
|
<div class="d-flex align-items-center">
|
|
<i class="bi bi-activity display-6"></i>
|
|
<div class="ms-3">
|
|
<h3 class="mb-0">100%</h3>
|
|
<p class="mb-0">Uptime</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
{# Recent Submissions #}
|
|
<div class="col-lg-6 mb-4">
|
|
<div class="card">
|
|
<div class="card-header bg-light">
|
|
<h5><i class="bi bi-inbox"></i> Recent Submissions</h5>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
{% if recent_submissions %}
|
|
<div class="table-responsive">
|
|
<table class="table table-hover mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Form</th>
|
|
<th>Date</th>
|
|
<th>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for submission in recent_submissions %}
|
|
<tr>
|
|
<td>{{ submission.id[:12] }}...</td>
|
|
<td>{{ submission.form_config.name if submission.form_config else 'N/A' }}</td>
|
|
<td>{{ submission.created_at.strftime('%Y-%m-%d %H:%M') if submission.created_at else 'N/A' }}</td>
|
|
<td>
|
|
<span class="badge bg-{{ 'success' if submission.status.value == 'processed' else 'warning' if submission.status.value == 'pending' else 'danger' }}">
|
|
{{ submission.status.value }}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<a href="{{ url_for('admin.view_submission', submission_id=submission.id) }}" class="btn btn-sm btn-outline-secondary">
|
|
<i class="bi bi-eye"></i>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<div class="p-4 text-center text-muted">
|
|
<i class="bi bi-inbox display-4"></i>
|
|
<p>No recent submissions</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="card-footer bg-light">
|
|
<a href="{{ url_for('admin.list_submissions') }}" class="btn btn-sm btn-outline-primary">
|
|
<i class="bi bi-list"></i> View All Submissions
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{# Recent Forms #}
|
|
<div class="col-lg-6 mb-4">
|
|
<div class="card">
|
|
<div class="card-header bg-light">
|
|
<h5><i class="bi bi-file-earmark-text"></i> Recent Forms</h5>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
{% if recent_forms %}
|
|
<div class="table-responsive">
|
|
<table class="table table-hover mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Tenant</th>
|
|
<th>Status</th>
|
|
<th>Created</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for form in recent_forms %}
|
|
<tr>
|
|
<td>{{ form.name }}</td>
|
|
<td>{{ form.tenant.name if form.tenant else 'N/A' }}</td>
|
|
<td>
|
|
<span class="badge bg-{{ 'success' if form.is_active else 'secondary' }}">
|
|
{{ 'Active' if form.is_active else 'Inactive' }}
|
|
</span>
|
|
</td>
|
|
<td>{{ form.created_at.strftime('%Y-%m-%d') if form.created_at else 'N/A' }}</td>
|
|
<td>
|
|
<a href="{{ url_for('admin.view_form', form_id=form.id) }}" class="btn btn-sm btn-outline-secondary">
|
|
<i class="bi bi-eye"></i>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<div class="p-4 text-center text-muted">
|
|
<i class="bi bi-file-earmark-text display-4"></i>
|
|
<p>No recent forms</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="card-footer bg-light">
|
|
<a href="{{ url_for('admin.list_forms') }}" class="btn btn-sm btn-outline-primary">
|
|
<i class="bi bi-list"></i> View All Forms
|
|
</a>
|
|
<a href="{{ url_for('admin.create_form') }}" class="btn btn-sm btn-primary">
|
|
<i class="bi bi-plus"></i> Create Form
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% if user.is_admin() %}
|
|
{# Tenants Overview #}
|
|
<div class="row">
|
|
<div class="col-12 mb-4">
|
|
<div class="card">
|
|
<div class="card-header bg-light">
|
|
<h5><i class="bi bi-buildings"></i> Tenants Overview</h5>
|
|
</div>
|
|
<div class="card-body p-0">
|
|
{% if tenants %}
|
|
<div class="table-responsive">
|
|
<table class="table table-hover mb-0">
|
|
<thead class="table-light">
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>ID</th>
|
|
<th>Status</th>
|
|
<th>Forms</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for tenant in tenants %}
|
|
<tr>
|
|
<td>{{ tenant.name }}</td>
|
|
<td><code>{{ tenant.id }}</code></td>
|
|
<td>
|
|
<span class="badge bg-{{ 'success' if tenant.status.value == 'active' else 'warning' if tenant.status.value == 'suspended' else 'danger' }}">
|
|
{{ tenant.status.value }}
|
|
</span>
|
|
</td>
|
|
<td>{{ tenant.forms|length }}</td>
|
|
<td>
|
|
<a href="{{ url_for('admin.view_tenant', tenant_id=tenant.id) }}" class="btn btn-sm btn-outline-secondary">
|
|
<i class="bi bi-eye"></i>
|
|
</a>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% else %}
|
|
<div class="p-4 text-center text-muted">
|
|
<i class="bi bi-buildings display-4"></i>
|
|
<p>No tenants yet</p>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
<div class="card-footer bg-light">
|
|
<a href="{{ url_for('admin.list_tenants') }}" class="btn btn-sm btn-outline-primary">
|
|
<i class="bi bi-list"></i> View All Tenants
|
|
</a>
|
|
<a href="{{ url_for('admin.create_tenant') }}" class="btn btn-sm btn-primary">
|
|
<i class="bi bi-plus"></i> Create Tenant
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
<style>
|
|
.dev-mode-banner {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
right: 0;
|
|
background: #ffc107;
|
|
color: #000;
|
|
padding: 10px 20px;
|
|
font-size: 0.9rem;
|
|
z-index: 1000;
|
|
box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
|
|
}
|
|
|
|
.card {
|
|
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
|
}
|
|
|
|
.display-6 {
|
|
font-size: calc(1.2525rem + 0.975vw);
|
|
}
|
|
</style>
|
|
{% endblock %}
|