from datetime import datetime from flask import Blueprint, jsonify, request from ..models import ActivityLog, ActivityCategory, PaperMetadata from .. import db bp = Blueprint("api", __name__, url_prefix="/api") @bp.route("/activity_logs") def get_activity_logs(): """Get activity logs with filtering options.""" # Get query parameters categories = request.args.getlist("category") # Changed to getlist for multiple values action = request.args.get("action") after = request.args.get("after") limit = request.args.get("limit", 20, type=int) # Build query query = ActivityLog.query if categories: # Filter by multiple categories using in_() for SQL IN clause query = query.filter(ActivityLog.category.in_(categories)) if action: query = query.filter(ActivityLog.action == action) if after: try: after_date = datetime.fromisoformat(after.replace("Z", "+00:00")) query = query.filter(ActivityLog.timestamp > after_date) except (ValueError, TypeError): pass # Order by most recent first and limit results logs = query.order_by(ActivityLog.timestamp.desc()).limit(limit).all() # Format the results result = [] for log in logs: log_data = { "id": log.id, "timestamp": log.timestamp.isoformat(), "category": log.category, "action": log.action, "description": log.description, "status": log.status, "paper_id": log.paper_id, "extra_data": log.extra_data } result.append(log_data) return jsonify(result) @bp.route("/papers") def search_papers(): """ Search for papers by title, DOI, or ID. Query parameters: - query: Search term (required) - limit: Maximum number of results (default: 10) """ query = request.args.get('query', '') limit = int(request.args.get('limit', 10)) if not query: return jsonify({ "success": False, "message": "Search query is required", "papers": [] }) # Try to parse query as an ID first try: paper_id = int(query) paper_by_id = PaperMetadata.query.get(paper_id) if paper_by_id: return jsonify({ "success": True, "papers": [{ "id": paper_by_id.id, "title": paper_by_id.title, "doi": paper_by_id.doi, "journal": paper_by_id.journal, "status": paper_by_id.status, "created_at": paper_by_id.created_at.isoformat() if paper_by_id.created_at else None, "updated_at": paper_by_id.updated_at.isoformat() if paper_by_id.updated_at else None }] }) except ValueError: pass # Not an ID, continue with text search # Search in title and DOI search_term = f"%{query}%" papers = PaperMetadata.query.filter( db.or_( PaperMetadata.title.ilike(search_term), PaperMetadata.doi.ilike(search_term) ) ).limit(limit).all() return jsonify({ "success": True, "papers": [{ "id": paper.id, "title": paper.title, "doi": paper.doi, "journal": paper.journal, "status": paper.status, "created_at": paper.created_at.isoformat() if paper.created_at else None, "updated_at": paper.updated_at.isoformat() if paper.updated_at else None } for paper in papers] }) @bp.route("/papers/") def get_paper(paper_id): """Get details of a single paper by ID.""" paper = PaperMetadata.query.get(paper_id) if not paper: return jsonify({ "success": False, "message": f"Paper with ID {paper_id} not found" }) return jsonify({ "success": True, "paper": { "id": paper.id, "title": paper.title, "doi": paper.doi, "journal": paper.journal, "status": paper.status, "error_msg": paper.error_msg, "file_path": paper.file_path, "created_at": paper.created_at.isoformat() if paper.created_at else None, "updated_at": paper.updated_at.isoformat() if paper.updated_at else None } })