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
This commit is contained in:
133
routes/home.py
Normal file
133
routes/home.py
Normal file
@@ -0,0 +1,133 @@
|
||||
from flask import Blueprint, render_template, request
|
||||
from flask_login import login_required, current_user
|
||||
from extensions import db, htmx, environment
|
||||
from jinja2_fragments import render_block
|
||||
|
||||
home = Blueprint('home', __name__)
|
||||
|
||||
|
||||
@home.route('/')
|
||||
@login_required
|
||||
def index():
|
||||
# Fetch user statistics
|
||||
stats = db.execute("""
|
||||
WITH timer_stats AS (
|
||||
SELECT
|
||||
COUNT(*) as total_timer_functions,
|
||||
COUNT(*) FILTER (WHERE enabled = true) as active_timer_functions,
|
||||
(SELECT COUNT(*) FROM timer_function_invocations tfi
|
||||
JOIN timer_functions tf ON tf.id = tfi.timer_function_id
|
||||
WHERE tf.user_id = %s) as timer_invocations,
|
||||
(SELECT COUNT(*) FROM timer_function_invocations tfi
|
||||
JOIN timer_functions tf ON tf.id = tfi.timer_function_id
|
||||
WHERE tf.user_id = %s AND tfi.status = 'SUCCESS') as timer_successful_invocations,
|
||||
MAX(last_run) as last_timer_invocation
|
||||
FROM timer_functions
|
||||
WHERE user_id = %s
|
||||
),
|
||||
http_stats AS (
|
||||
SELECT
|
||||
COUNT(*) as total_http_functions,
|
||||
COUNT(*) FILTER (WHERE is_public = true) as public_http_functions,
|
||||
SUM(invoked_count) as http_invocations,
|
||||
(SELECT COUNT(*) FROM http_function_invocations hfi
|
||||
JOIN http_functions hf ON hf.id = hfi.http_function_id
|
||||
WHERE hf.user_id = %s AND hfi.status = 'SUCCESS') as http_successful_invocations,
|
||||
(SELECT MAX(invocation_time)
|
||||
FROM http_function_invocations hfi
|
||||
JOIN http_functions hf ON hf.id = hfi.http_function_id
|
||||
WHERE hf.user_id = %s) as last_http_invocation
|
||||
FROM http_functions
|
||||
WHERE user_id = %s
|
||||
)
|
||||
SELECT
|
||||
*,
|
||||
CASE
|
||||
WHEN timer_invocations > 0 THEN
|
||||
(timer_successful_invocations * 100.0 / timer_invocations)::numeric(5,1)
|
||||
ELSE 0.0
|
||||
END as timer_success_rate,
|
||||
CASE
|
||||
WHEN http_invocations > 0 THEN
|
||||
(http_successful_invocations * 100.0 / http_invocations)::numeric(5,1)
|
||||
ELSE 0.0
|
||||
END as http_success_rate
|
||||
FROM timer_stats, http_stats
|
||||
""", [current_user.id, current_user.id, current_user.id, current_user.id, current_user.id, current_user.id], one=True)
|
||||
|
||||
# Get 24-hour distribution
|
||||
hour_distribution = db.execute("""
|
||||
WITH all_invocations AS (
|
||||
SELECT date_trunc('hour', tfi.invocation_time) as hour_bucket
|
||||
FROM timer_function_invocations tfi
|
||||
JOIN timer_functions tf ON tf.id = tfi.timer_function_id
|
||||
WHERE tf.user_id = %s
|
||||
AND tfi.invocation_time > NOW() - INTERVAL '24 hours'
|
||||
UNION ALL
|
||||
SELECT date_trunc('hour', hfi.invocation_time) as hour_bucket
|
||||
FROM http_function_invocations hfi
|
||||
JOIN http_functions hf ON hf.id = hfi.http_function_id
|
||||
WHERE hf.user_id = %s
|
||||
AND hfi.invocation_time > NOW() - INTERVAL '24 hours'
|
||||
)
|
||||
SELECT
|
||||
EXTRACT(HOUR FROM hour_bucket) as hour,
|
||||
COUNT(*) as count
|
||||
FROM all_invocations
|
||||
GROUP BY hour
|
||||
ORDER BY hour
|
||||
""", [current_user.id, current_user.id])
|
||||
|
||||
# Get 7-day success rate trend
|
||||
success_trend = db.execute("""
|
||||
WITH daily_stats AS (
|
||||
WITH timer_daily AS (
|
||||
SELECT
|
||||
date_trunc('day', tfi.invocation_time) as day,
|
||||
COUNT(*) as total,
|
||||
COUNT(*) FILTER (WHERE tfi.status = 'SUCCESS') as successes
|
||||
FROM timer_function_invocations tfi
|
||||
JOIN timer_functions tf ON tf.id = tfi.timer_function_id
|
||||
WHERE tf.user_id = %s
|
||||
AND tfi.invocation_time > NOW() - INTERVAL '7 days'
|
||||
GROUP BY day
|
||||
),
|
||||
http_daily AS (
|
||||
SELECT
|
||||
date_trunc('day', hfi.invocation_time) as day,
|
||||
COUNT(*) as total,
|
||||
COUNT(*) FILTER (WHERE hfi.status = 'SUCCESS') as successes
|
||||
FROM http_function_invocations hfi
|
||||
JOIN http_functions hf ON hf.id = hfi.http_function_id
|
||||
WHERE hf.user_id = %s
|
||||
AND hfi.invocation_time > NOW() - INTERVAL '7 days'
|
||||
GROUP BY day
|
||||
)
|
||||
SELECT
|
||||
COALESCE(t.day, h.day) as day,
|
||||
COALESCE(t.total, 0) + COALESCE(h.total, 0) as total,
|
||||
COALESCE(t.successes, 0) + COALESCE(h.successes, 0) as successes
|
||||
FROM timer_daily t
|
||||
FULL OUTER JOIN http_daily h ON t.day = h.day
|
||||
)
|
||||
SELECT
|
||||
to_char(day, 'Dy') as day_name,
|
||||
CASE
|
||||
WHEN total > 0 THEN
|
||||
(successes * 100.0 / total)::float
|
||||
ELSE 0.0
|
||||
END as success_rate
|
||||
FROM daily_stats
|
||||
ORDER BY day DESC
|
||||
LIMIT 7
|
||||
""", [current_user.id, current_user.id])
|
||||
|
||||
if htmx:
|
||||
return render_block(environment, 'dashboard/home.html', 'page',
|
||||
stats=stats,
|
||||
hour_distribution=hour_distribution,
|
||||
success_trend=success_trend)
|
||||
return render_template('dashboard/home.html',
|
||||
stats=stats,
|
||||
hour_distribution=hour_distribution,
|
||||
success_trend=success_trend)
|
||||
48
routes/test.py
Normal file
48
routes/test.py
Normal file
@@ -0,0 +1,48 @@
|
||||
from flask import Blueprint, render_template, redirect, url_for, flash, request, jsonify
|
||||
from jinja2_fragments import render_block
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
from flask_login import current_user, login_required
|
||||
from extensions import db, htmx, environment
|
||||
from datetime import datetime, timezone, timedelta
|
||||
from lib.mithril import Mithril
|
||||
import json
|
||||
|
||||
test = Blueprint('test', __name__)
|
||||
|
||||
@test.route('/mithril/<int:function_id>')
|
||||
@login_required
|
||||
def mithril(function_id):
|
||||
# Fetch the timer function to verify ownership
|
||||
timer_function = db.execute("""
|
||||
SELECT id, name, code, version_number
|
||||
FROM timer_functions
|
||||
WHERE id = %s AND user_id = %s
|
||||
""", [function_id, current_user.id], one=True)
|
||||
|
||||
if not timer_function:
|
||||
flash('Timer function not found', 'error')
|
||||
return redirect(url_for('timer.overview'))
|
||||
|
||||
# Fetch all versions
|
||||
versions = db.execute("""
|
||||
SELECT version_number, script, versioned_at
|
||||
FROM timer_function_versions
|
||||
WHERE timer_function_id = %s
|
||||
ORDER BY version_number DESC
|
||||
""", [function_id])
|
||||
|
||||
# Convert datetime objects to ISO format strings
|
||||
for version in versions:
|
||||
version['versioned_at'] = version['versioned_at'].isoformat() if version['versioned_at'] else None
|
||||
|
||||
args = {
|
||||
'user_id': current_user.id,
|
||||
'function_id': function_id,
|
||||
'timer_function': timer_function,
|
||||
'versions': versions
|
||||
}
|
||||
|
||||
return Mithril.render('DiffView', args)
|
||||
|
||||
#return render_template('mithril_loader.html', args=args)
|
||||
|
||||
@@ -153,7 +153,7 @@ def overview():
|
||||
timer_functions = db.execute("""
|
||||
SELECT id, name, code, environment, trigger_type,
|
||||
frequency_minutes, run_date, next_run,
|
||||
last_run, enabled
|
||||
last_run, enabled, invocation_count
|
||||
FROM timer_functions
|
||||
WHERE user_id = %s
|
||||
ORDER BY id DESC
|
||||
@@ -237,7 +237,7 @@ def edit(function_id):
|
||||
timer_function = db.execute("""
|
||||
SELECT id, name, code, environment, version_number, trigger_type,
|
||||
frequency_minutes, run_date, next_run,
|
||||
last_run, enabled
|
||||
last_run, enabled, invocation_count
|
||||
FROM timer_functions
|
||||
WHERE id = %s AND user_id = %s
|
||||
""", [function_id, current_user.id], one=True)
|
||||
@@ -369,7 +369,7 @@ def toggle(function_id):
|
||||
timer_functions = db.execute("""
|
||||
SELECT id, name, code, environment, trigger_type,
|
||||
frequency_minutes, run_date, next_run,
|
||||
last_run, enabled
|
||||
last_run, enabled, invocation_count
|
||||
FROM timer_functions
|
||||
WHERE user_id = %s
|
||||
ORDER BY id DESC
|
||||
|
||||
Reference in New Issue
Block a user