Add run deletion with filesystem cleanup

- New POST /run/<id>/delete route removes run from DB and deletes run directory
- Only allows deletion of non-active runs (blocks running/queued)
- Delete Run button shown in run_details.html header for non-active runs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-22 10:04:44 -05:00
parent 203d74f61d
commit af2050160e
2 changed files with 34 additions and 1 deletions

View File

@@ -1,5 +1,6 @@
import os
import json
import shutil
import markdown
from datetime import datetime
from flask import Blueprint, render_template, request, redirect, url_for, flash, session, send_from_directory
@@ -393,6 +394,30 @@ def revise_book(run_id, book_folder):
return redirect(url_for('run.view_run', id=new_run.id))
@run_bp.route('/run/<int:id>/delete', methods=['POST'])
@login_required
def delete_run(id):
run = db.session.get(Run, id)
if not run: return "Run not found", 404
if run.project.user_id != current_user.id: return "Unauthorized", 403
if run.status in ['running', 'queued']:
flash("Cannot delete an active run. Stop it first.")
return redirect(url_for('run.view_run', id=id))
project_id = run.project_id
run_dir = os.path.join(run.project.folder_path, "runs", f"run_{run.id}")
if os.path.exists(run_dir):
shutil.rmtree(run_dir)
db.session.delete(run)
db.session.commit()
flash(f"Run #{id} deleted successfully.")
return redirect(url_for('project.view_project', id=project_id))
@run_bp.route('/run/<int:id>/download_bible')
@login_required
def download_bible(id):