112 lines
3.5 KiB
Python
112 lines
3.5 KiB
Python
"""Logger view."""
|
|
import csv
|
|
import io
|
|
import datetime
|
|
from flask import Blueprint, render_template, request, send_file
|
|
from ..db import db
|
|
from ..models import ActivityLog, ActivityCategory
|
|
|
|
bp = Blueprint("logger", __name__, url_prefix="/logs")
|
|
|
|
|
|
@bp.route("/")
|
|
def list_logs():
|
|
page = request.args.get("page", 1, type=int)
|
|
per_page = 50
|
|
|
|
# Filters
|
|
category = request.args.get("category")
|
|
start_date = request.args.get("start_date")
|
|
end_date = request.args.get("end_date")
|
|
search_term = request.args.get("search_term")
|
|
|
|
if search_term == "None":
|
|
search_term = None
|
|
|
|
|
|
query = ActivityLog.query
|
|
|
|
if category:
|
|
query = query.filter(ActivityLog.category == category)
|
|
if start_date:
|
|
start_date_dt = datetime.datetime.strptime(start_date, "%Y-%m-%d")
|
|
query = query.filter(ActivityLog.timestamp >= start_date_dt)
|
|
if end_date:
|
|
end_date_dt = datetime.datetime.strptime(end_date, "%Y-%m-%d") + datetime.timedelta(days=1)
|
|
query = query.filter(ActivityLog.timestamp <= end_date_dt)
|
|
if search_term:
|
|
query = query.filter(db.or_(
|
|
ActivityLog.action.contains(search_term),
|
|
ActivityLog.description.contains(search_term)
|
|
))
|
|
|
|
pagination = query.order_by(ActivityLog.timestamp.desc()).paginate(page=page, per_page=per_page, error_out=False)
|
|
|
|
categories = [e.value for e in ActivityCategory]
|
|
|
|
return render_template(
|
|
"logger.html.jinja",
|
|
logs=pagination.items,
|
|
pagination=pagination,
|
|
categories=categories,
|
|
category=category,
|
|
start_date=start_date,
|
|
end_date=end_date,
|
|
search_term=search_term,
|
|
app_title="PaperScraper",
|
|
)
|
|
|
|
|
|
@bp.route("/download")
|
|
def download_logs():
|
|
# Filters - reuse logic from list_logs
|
|
category = request.args.get("category")
|
|
start_date = request.args.get("start_date")
|
|
end_date = request.args.get("end_date")
|
|
search_term = request.args.get("search_term")
|
|
|
|
query = ActivityLog.query
|
|
|
|
if category:
|
|
query = query.filter(ActivityLog.category == category)
|
|
if start_date:
|
|
start_date_dt = datetime.datetime.strptime(start_date, "%Y-%m-%d")
|
|
query = query.filter(ActivityLog.timestamp >= start_date_dt)
|
|
if end_date:
|
|
end_date_dt = datetime.datetime.strptime(end_date, "%Y-%m-%d") + datetime.timedelta(days=1)
|
|
query = query.filter(ActivityLog.timestamp <= end_date_dt)
|
|
if search_term:
|
|
query = query.filter(db.or_(
|
|
ActivityLog.action.contains(search_term),
|
|
ActivityLog.description.contains(search_term)
|
|
))
|
|
|
|
logs = query.order_by(ActivityLog.timestamp.desc()).all()
|
|
|
|
# Prepare CSV data
|
|
csv_data = io.StringIO()
|
|
csv_writer = csv.writer(csv_data)
|
|
csv_writer.writerow(["Timestamp", "Category", "Action", "Description", "Extra Data"]) # Header
|
|
|
|
for log in logs:
|
|
csv_writer.writerow([
|
|
log.timestamp,
|
|
log.category,
|
|
log.action,
|
|
log.description,
|
|
log.extra_data # Consider formatting this better
|
|
])
|
|
|
|
# Create response
|
|
filename = f"logs_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
|
|
return send_file(
|
|
io.StringIO(csv_data.getvalue()),
|
|
mimetype="text/csv",
|
|
as_attachment=True,
|
|
download_name=filename
|
|
)
|
|
|
|
@bp.route("/<int:log_id>/detail")
|
|
def log_detail(log_id):
|
|
log = ActivityLog.query.get_or_404(log_id)
|
|
return render_template("partials/log_detail_modal.html.jinja", log=log) |