140 lines
3.9 KiB
Python

"""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("/<int:paper_id>/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)