# plugins/submission/routes.py from flask import ( Blueprint, render_template, request, redirect, url_for, flash, jsonify ) from flask_login import login_required, current_user from app import db from .models import Submission, SubmissionImage from .forms import SubmissionForm from datetime import datetime import os from werkzeug.utils import secure_filename from plugins.media.utils import generate_random_filename, strip_metadata_and_save bp = Blueprint("submission", __name__, template_folder="templates", url_prefix="/submission") # We store only "YYYY/MM/DD/.ext" in SubmissionImage.file_url. # All files live under "/app/static/uploads/YYYY/MM/DD/.ext" in the container. BASE_UPLOAD_FOLDER = "static/uploads" ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg", "gif"} def allowed_file(filename): return ( "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS ) @bp.route("/", methods=["GET"]) @login_required def submission_index(): return redirect(url_for("submission.new_submission")) @bp.route("/new", methods=["GET", "POST"]) @bp.route("/new/", methods=["GET", "POST"]) @login_required def new_submission(): form = SubmissionForm() if form.validate_on_submit(): plant_types = {"market_price", "name_correction", "new_plant", "mutation"} t = form.submission_type.data # Only require plant_name if the type is plant‐related if t in plant_types and not form.plant_name.data.strip(): flash("Common Name is required for this submission type.", "danger") return render_template("submission/new.html", form=form) submission = Submission( user_id=current_user.id, submitted_at=datetime.utcnow(), submission_type=t, plant_name=form.plant_name.data, scientific_name=form.scientific_name.data, notes=form.notes.data, price=form.price.data if form.price.data else None, source=form.source.data, vendor_name=form.vendor_name.data, rating=form.rating.data, old_vendor=form.old_vendor.data, new_vendor=form.new_vendor.data, alias_reason=form.alias_reason.data, approved=None ) db.session.add(submission) db.session.flush() # date subfolder: "YYYY/MM/DD" today = datetime.utcnow().strftime("%Y/%m/%d") # Write into "/app/static/uploads/YYYY/MM/DD", not "/app/app/static/uploads..." save_dir = os.path.join(os.getcwd(), BASE_UPLOAD_FOLDER, today) os.makedirs(save_dir, exist_ok=True) files = request.files.getlist("images") for f in files: if f and allowed_file(f.filename): orig_name = secure_filename(f.filename) rand_name = generate_random_filename(orig_name) # Temporarily save under "/app/temp_.ext" temp_path = os.path.join(os.getcwd(), "temp_" + rand_name) f.save(temp_path) final_path = os.path.join(save_dir, rand_name) strip_metadata_and_save(temp_path, final_path) os.remove(temp_path) # Store only "YYYY/MM/DD/.ext" rel_url = f"{today}/{rand_name}" img = SubmissionImage( submission_id=submission.id, file_url=rel_url, uploaded_at=datetime.utcnow() ) db.session.add(img) db.session.commit() flash("Submission received. Thank you!", "success") return redirect(url_for("submission.new_submission")) return render_template("submission/new.html", form=form) @bp.route("/list", methods=["GET"]) @bp.route("/list/", methods=["GET"]) @login_required def list_submissions(): selected_type = request.args.get("type", None) query = Submission.query.filter_by(user_id=current_user.id) if selected_type: query = query.filter_by(submission_type=selected_type) subs = query.order_by(Submission.submitted_at.desc()).all() all_types = [ ("", "All"), ("market_price", "Market Price"), ("name_correction", "Name Correction"), ("new_plant", "New Plant Suggestion"), ("mutation", "Mutation Discovery"), ("vendor_rating", "Vendor Rating/Review"), ("vendor_alias", "Vendor Alias Submission"), ] return render_template( "submission/list.html", submissions=subs, selected_type=selected_type, all_types=all_types ) @bp.route("/view/", methods=["GET"]) @bp.route("/view//", methods=["GET"]) @login_required def view_submission(submission_id): sub = Submission.query.get_or_404(submission_id) if sub.user_id != current_user.id and current_user.role != "admin": flash("Not authorized to view this submission.", "danger") return redirect(url_for("submission.list_submissions")) images = SubmissionImage.query.filter_by(submission_id=sub.id).all() return render_template("submission/view.html", submission=sub, images=images)