"""Paper management routes.""" import csv import datetime import io from flask import ( Blueprint, render_template, request, send_file, ) from sqlalchemy import asc, desc from ..db import db from ..models import PaperMetadata bp = Blueprint("papers", __name__) @bp.route("/") def list_papers(): page = request.args.get("page", 1, type=int) per_page = 50 # Filters status = request.args.get("status") created_from = request.args.get("created_from") created_to = request.args.get("created_to") updated_from = request.args.get("updated_from") updated_to = request.args.get("updated_to") sort_by = request.args.get("sort_by", "created_at") sort_dir = request.args.get("sort_dir", "desc") query = PaperMetadata.query # Apply filters if status: query = query.filter(PaperMetadata.status == status) def parse_date(val): from datetime import datetime try: return datetime.strptime(val, "%Y-%m-%d") except (ValueError, TypeError): return None if created_from := parse_date(created_from): query = query.filter(PaperMetadata.created_at >= created_from) if created_to := parse_date(created_to): query = query.filter(PaperMetadata.created_at <= created_to) if updated_from := parse_date(updated_from): query = query.filter(PaperMetadata.updated_at >= updated_from) if updated_to := parse_date(updated_to): query = query.filter(PaperMetadata.updated_at <= updated_to) # Sorting sort_col = getattr(PaperMetadata, sort_by, PaperMetadata.created_at) sort_func = desc if sort_dir == "desc" else asc query = query.order_by(sort_func(sort_col)) # Pagination pagination = query.paginate(page=page, per_page=per_page, error_out=False) # Statistics total_papers = PaperMetadata.query.count() status_counts = ( db.session.query(PaperMetadata.status, db.func.count(PaperMetadata.status)) .group_by(PaperMetadata.status) .all() ) status_counts = {status: count for status, count in status_counts} return render_template( "papers.html.jinja", papers=pagination.items, pagination=pagination, total_papers=total_papers, status_counts=status_counts, sort_by=sort_by, sort_dir=sort_dir, ) @bp.route("/export") def export_papers(): # Filters status = request.args.get("status") created_from = request.args.get("created_from") created_to = request.args.get("created_to") updated_from = request.args.get("updated_from") updated_to = request.args.get("updated_to") sort_by = request.args.get("sort_by", "created_at") sort_dir = request.args.get("sort_dir", "desc") query = PaperMetadata.query # Apply filters if status: query = query.filter(PaperMetadata.status == status) def parse_date(val): try: return datetime.datetime.strptime(val, "%Y-%m-%d") except Exception: return None output = io.StringIO() writer = csv.writer(output) writer.writerow( ["ID", "Title", "Journal", "DOI", "ISSN", "Status", "Created At", "Updated At"] ) for paper in query: writer.writerow( [ paper.id, paper.title, paper.journal, paper.doi, paper.issn, paper.status, paper.created_at, paper.updated_at, ] ) output.seek(0) return send_file( io.BytesIO(output.read().encode("utf-8")), mimetype="text/csv", as_attachment=True, download_name="papers.csv", ) @bp.route("//detail") def paper_detail(paper_id): paper = PaperMetadata.query.get_or_404(paper_id) return render_template("partials/paper_detail_modal.html.jinja", paper=paper)