from flask import Blueprint, render_template, request from flask_login import login_required, current_user 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, (SELECT AVG(tfi.execution_time) FROM timer_function_invocations tfi JOIN timer_functions tf ON tf.id = tfi.timer_function_id WHERE tf.user_id = %s) as avg_timer_execution_time, 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, (SELECT COUNT(*) FROM http_function_invocations hfi JOIN http_functions hf ON hf.id = hfi.http_function_id WHERE hf.user_id = %s) 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 AVG(hfi.execution_time) FROM http_function_invocations hfi JOIN http_functions hf ON hf.id = hfi.http_function_id WHERE hf.user_id = %s) as avg_http_execution_time, (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 *, (timer_invocations - timer_successful_invocations) as timer_failed_invocations, (http_invocations - http_successful_invocations) as http_failed_invocations, 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, 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]) # Top 5 Most Invoked Functions top_functions = db.execute(""" WITH all_functions AS ( SELECT tf.name, 'Timer' as type, COUNT(tfi.id) as invocation_count FROM timer_functions tf JOIN timer_function_invocations tfi ON tf.id = tfi.timer_function_id WHERE tf.user_id = %s GROUP BY tf.name UNION ALL SELECT hf.name, 'HTTP' as type, COUNT(hfi.id) as invocation_count FROM http_functions hf JOIN http_function_invocations hfi ON hf.id = hfi.http_function_id WHERE hf.user_id = %s GROUP BY hf.name ) SELECT * FROM all_functions ORDER BY invocation_count DESC LIMIT 5 """, [current_user.id, current_user.id]) # Recent Activity (Last 10) recent_activity = db.execute(""" WITH all_activity AS ( SELECT tf.name, 'Timer' as type, tfi.status, tfi.invocation_time, tfi.execution_time FROM timer_function_invocations tfi JOIN timer_functions tf ON tf.id = tfi.timer_function_id WHERE tf.user_id = %s UNION ALL SELECT hf.name, 'HTTP' as type, hfi.status, hfi.invocation_time, hfi.execution_time FROM http_function_invocations hfi JOIN http_functions hf ON hf.id = hfi.http_function_id WHERE hf.user_id = %s ) SELECT * FROM all_activity ORDER BY invocation_time DESC LIMIT 10 """, [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, top_functions=top_functions, recent_activity=recent_activity) return render_template('dashboard/home.html', stats=stats, hour_distribution=hour_distribution, success_trend=success_trend, top_functions=top_functions, recent_activity=recent_activity)