Files
function/templates/dashboard/home.html
Peter Stockings d4c0c0f262 Add home dashboard and Mithril rendering support
- Create new home route with comprehensive dashboard statistics
- Implement Mithril rendering support with new `mithril_loader.html` template
- Add new routes for home and test pages in `app.py`
- Create `lib/mithril.py` with Mithril rendering and error handling utilities
- Update dashboard template to use new home route
- Add detailed dashboard view with timer and HTTP function statistics
2025-02-20 23:35:46 +11:00

282 lines
15 KiB
HTML

{% extends 'dashboard.html' %}
{% block page %}
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div class="mb-8">
<h1 class="text-2xl font-bold text-gray-900">Dashboard Overview</h1>
</div>
<!-- Timer Functions Stats -->
<div class="mb-8">
<h2 class="text-lg font-semibold text-gray-700 mb-4">Timer Functions</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<!-- Total Timer Functions Card -->
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<div class="flex items-center">
<div class="p-3 rounded-full bg-blue-100">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-blue-600" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="ml-4">
<h2 class="text-sm font-medium text-gray-500">Total Timer Functions</h2>
<p class="text-2xl font-semibold text-gray-900">{{ stats.total_timer_functions }}</p>
</div>
</div>
</div>
<!-- Active Timer Functions Card -->
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<div class="flex items-center">
<div class="p-3 rounded-full bg-green-100">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-green-600" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" />
</svg>
</div>
<div class="ml-4">
<h2 class="text-sm font-medium text-gray-500">Active Timer Functions</h2>
<p class="text-2xl font-semibold text-gray-900">{{ stats.active_timer_functions }}</p>
</div>
</div>
</div>
<!-- Timer Function Invocations Card -->
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<div class="flex items-center">
<div class="p-3 rounded-full bg-purple-100">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-purple-600" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
</div>
<div class="ml-4">
<h2 class="text-sm font-medium text-gray-500">Timer Invocations</h2>
<p class="text-2xl font-semibold text-gray-900">{{ stats.timer_invocations }}</p>
</div>
</div>
</div>
<!-- Timer Success Rate Card -->
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<div class="flex items-center">
<div class="p-3 rounded-full bg-emerald-100">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-emerald-600" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="ml-4">
<h2 class="text-sm font-medium text-gray-500">Success Rate</h2>
<div class="flex items-baseline">
<p class="text-2xl font-semibold text-gray-900">{{ stats.timer_success_rate }}%</p>
<p class="ml-2 text-sm text-gray-500">({{ stats.timer_successful_invocations }}/{{
stats.timer_invocations }})</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- HTTP Functions Stats -->
<div class="mb-8">
<h2 class="text-lg font-semibold text-gray-700 mb-4">HTTP Functions</h2>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
<!-- Total HTTP Functions Card -->
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<div class="flex items-center">
<div class="p-3 rounded-full bg-indigo-100">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-indigo-600" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" />
</svg>
</div>
<div class="ml-4">
<h2 class="text-sm font-medium text-gray-500">Total HTTP Functions</h2>
<p class="text-2xl font-semibold text-gray-900">{{ stats.total_http_functions }}</p>
</div>
</div>
</div>
<!-- Public HTTP Functions Card -->
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<div class="flex items-center">
<div class="p-3 rounded-full bg-yellow-100">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-yellow-600" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064" />
</svg>
</div>
<div class="ml-4">
<h2 class="text-sm font-medium text-gray-500">Public HTTP Functions</h2>
<p class="text-2xl font-semibold text-gray-900">{{ stats.public_http_functions }}</p>
</div>
</div>
</div>
<!-- HTTP Function Invocations Card -->
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<div class="flex items-center">
<div class="p-3 rounded-full bg-red-100">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-red-600" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
</div>
<div class="ml-4">
<h2 class="text-sm font-medium text-gray-500">HTTP Invocations</h2>
<p class="text-2xl font-semibold text-gray-900">{{ stats.http_invocations }}</p>
</div>
</div>
</div>
<!-- HTTP Success Rate Card -->
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<div class="flex items-center">
<div class="p-3 rounded-full bg-emerald-100">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-emerald-600" fill="none"
viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<div class="ml-4">
<h2 class="text-sm font-medium text-gray-500">Success Rate</h2>
<div class="flex items-baseline">
<p class="text-2xl font-semibold text-gray-900">{{ stats.http_success_rate }}%</p>
<p class="ml-2 text-sm text-gray-500">({{ stats.http_successful_invocations }}/{{
stats.http_invocations }})</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Add this after the stats cards and before the Last Activity section -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
<!-- 24-Hour Distribution -->
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">24-Hour Invocation Distribution</h3>
<div class="relative h-64">
<svg class="w-full h-full" viewBox="0 0 400 200" preserveAspectRatio="none">
<!-- Y-axis -->
<line x1="40" y1="20" x2="40" y2="180" stroke="#E5E7EB" stroke-width="1" />
<!-- X-axis -->
<line x1="40" y1="180" x2="380" y2="180" stroke="#E5E7EB" stroke-width="1" />
{% set max_count = namespace(value=1) %}
{% for hour in hour_distribution %}
{% if hour.count > max_count.value %}
{% set max_count.value = hour.count %}
{% endif %}
{% endfor %}
<!-- Hour bars -->
{% for hour in hour_distribution %}
{% set x = 40 + (hour.hour * 14) %}
{% set height = (hour.count / max_count.value) * 160 %}
{% set y = 180 - height %}
<rect x="{{ x }}" y="{{ y }}" width="12" height="{{ height }}" fill="#60A5FA" opacity="0.8">
<title>{{ hour.hour }}:00 - {{ hour.count }} invocations</title>
</rect>
{% endfor %}
<!-- Hour labels (every 6 hours) -->
{% for h in [0, 6, 12, 18, 23] %}
<text x="{{ 40 + (h * 14) }}" y="195" text-anchor="middle" class="text-xs text-gray-500">{{ h
}}h</text>
{% endfor %}
</svg>
</div>
</div>
<!-- 7-Day Success Rate Trend -->
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<h3 class="text-lg font-medium text-gray-900 mb-4">7-Day Success Rate Trend</h3>
<div class="relative h-64">
<svg class="w-full h-full" viewBox="0 0 400 200" preserveAspectRatio="none">
<!-- Y-axis -->
<line x1="40" y1="20" x2="40" y2="180" stroke="#E5E7EB" stroke-width="1" />
<!-- X-axis -->
<line x1="40" y1="180" x2="380" y2="180" stroke="#E5E7EB" stroke-width="1" />
<!-- Success rate line -->
{% set path = namespace(d='M') %}
{% for day in success_trend %}
{% set x = 380 - (loop.index0 * 48) %}
{% set y = 180 - (day.success_rate * 1.6) %}
{% if loop.first %}
{% set path.d = path.d ~ x ~ "," ~ y %}
{% else %}
{% set path.d = path.d ~ " L" ~ x ~ "," ~ y %}
{% endif %}
{% endfor %}
<path d="{{ path.d }}" stroke="#10B981" stroke-width="2" fill="none" />
<!-- Data points -->
{% for day in success_trend %}
{% set x = 380 - (loop.index0 * 48) %}
{% set y = 180 - (day.success_rate * 1.6) %}
<circle cx="{{ x }}" cy="{{ y }}" r="4" fill="#10B981">
<title>{{ day.day_name }}: {{ day.success_rate }}% success rate</title>
</circle>
<!-- Day labels -->
<text x="{{ x }}" y="195" text-anchor="middle" class="text-xs text-gray-500">{{ day.day_name
}}</text>
{% endfor %}
<!-- Y-axis labels -->
{% for percent in [0, 25, 50, 75, 100] %}
<text x="35" y="{{ 180 - (percent * 1.6) }}" text-anchor="end" class="text-xs text-gray-500">{{
percent }}%</text>
{% endfor %}
</svg>
</div>
</div>
</div>
<!-- Last Activity -->
<div class="bg-white border border-gray-200 rounded-lg shadow-sm p-6">
<div class="flex items-center justify-between">
<div>
<h2 class="text-lg font-medium text-gray-900">Last Activity</h2>
<div class="mt-1 space-y-1">
{% if stats.last_timer_invocation %}
<p class="text-sm text-gray-500">
Last Timer Invocation: {{ stats.last_timer_invocation.strftime('%Y-%m-%d %H:%M') }}
</p>
{% endif %}
{% if stats.last_http_invocation %}
<p class="text-sm text-gray-500">
Last HTTP Invocation: {{ stats.last_http_invocation.strftime('%Y-%m-%d %H:%M') }}
</p>
{% endif %}
</div>
</div>
<div class="space-x-4">
<a href="{{ url_for('timer.overview') }}"
class="inline-flex items-center px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors duration-200">
View Timer Functions
</a>
<a href="{{ url_for('dashboard_http_functions') }}"
class="inline-flex items-center px-4 py-2 bg-indigo-600 hover:bg-indigo-700 text-white font-medium rounded-lg transition-colors duration-200">
View HTTP Functions
</a>
</div>
</div>
</div>
</div>
{% endblock %}