"""Overview blueprint routes (Chapter 08 / Chapter 11's route table).""" from __future__ import annotations from flask import current_app, jsonify, request from app.blueprints.overview import bp from app.blueprints.overview.queries import ( get_browser_breakdown, get_kpis, get_status_code_breakdown, get_top_referrers, get_top_urls, get_traffic_chart_series, ) from app.services.background import resume_incomplete_files from app.utils.dates import parse_date_range from app.utils.htmx import render_htmx_aware from app.utils.pagination import parse_pagination @bp.route("/overview") def overview(): """Full page on first load, HTMX partial on tab switch / range change (Ch04). Also opportunistically resumes any log_files stuck in queued/processing (Ch12 simplification: the replacement for cron's "there's always a next tick" guarantee — see app/services/background.py). """ resume_incomplete_files(current_app._get_current_object()) from_date, to_date = parse_date_range(request) return render_htmx_aware( request, full_template="overview/index.html", partial_template="overview/_content.html", from_date=from_date, to_date=to_date, ) @bp.get("/api/overview/kpis") def api_kpis(): from_date, to_date = parse_date_range(request) return jsonify(data=get_kpis(from_date, to_date), meta={"from": from_date.isoformat(), "to": to_date.isoformat()}) @bp.get("/api/overview/traffic-chart") def api_traffic_chart(): from_date, to_date = parse_date_range(request) return jsonify( data=get_traffic_chart_series(from_date, to_date), meta={"from": from_date.isoformat(), "to": to_date.isoformat()}, ) @bp.get("/api/overview/status-codes") def api_status_codes(): from_date, to_date = parse_date_range(request) return jsonify( data=get_status_code_breakdown(from_date, to_date), meta={"from": from_date.isoformat(), "to": to_date.isoformat()}, ) @bp.get("/api/overview/top-urls") def api_top_urls(): from_date, to_date = parse_date_range(request) page, per_page = parse_pagination(request) rows, total = get_top_urls(from_date, to_date, page, per_page) return jsonify( data={"rows": rows, "total": total}, meta={"from": from_date.isoformat(), "to": to_date.isoformat(), "page": page, "per_page": per_page}, ) @bp.get("/api/overview/top-referrers") def api_top_referrers(): from_date, to_date = parse_date_range(request) page, per_page = parse_pagination(request) rows, total = get_top_referrers(from_date, to_date, page, per_page) return jsonify( data={"rows": rows, "total": total}, meta={"from": from_date.isoformat(), "to": to_date.isoformat(), "page": page, "per_page": per_page}, ) @bp.get("/api/overview/browser-breakdown") def api_browser_breakdown(): """Chapter 11 addition (Method A, Ch08 follow-up) — not in the original route table; see docs/api-contract-final.md.""" from_date, to_date = parse_date_range(request) return jsonify( data=get_browser_breakdown(from_date, to_date), meta={"from": from_date.isoformat(), "to": to_date.isoformat()}, )