diff --git a/nip.zip b/nip.zip index a36fa77..922fc06 100644 Binary files a/nip.zip and b/nip.zip differ diff --git a/plugins/media/routes.py b/plugins/media/routes.py index 269331c..0b6edad 100644 --- a/plugins/media/routes.py +++ b/plugins/media/routes.py @@ -232,15 +232,6 @@ def serve(plugin, filename): return send_from_directory(disk_dir, filename) -@bp.route("/files/") -def media_file(filename): - base = current_app.config["UPLOAD_FOLDER"] - full = os.path.normpath(os.path.join(base, filename)) - if not full.startswith(os.path.abspath(base)): - abort(404) - return send_from_directory(base, filename) - - @bp.route("/") def media_public(filename): base = current_app.config["UPLOAD_FOLDER"] @@ -286,32 +277,64 @@ def add_media(plant_uuid): return redirect(request.referrer or url_for("plant.edit", uuid_val=plant_uuid)) -@bp.route("/feature///", methods=["POST"]) -@login_required -def set_featured_image(context, context_id, media_id): - media = Media.query.get_or_404(media_id) - if media.uploader_id != current_user.id and current_user.role != "admin": - return jsonify({"error": "Not authorized"}), 403 +@bp.route("///") +def media_file(context, context_id, filename): + # your existing serve_context_media logic here + # (unchanged) + from flask import current_app, send_from_directory + import os + valid = {"user", "plant", "growlog", "vendor"} + if context in valid: + plugin = context + elif context.endswith("s") and context[:-1] in valid: + plugin = context[:-1] + else: + abort(404) + media = Media.query.filter_by( + plugin=plugin, + related_id=context_id, + filename=filename + ).first_or_404() + + base = current_app.config["UPLOAD_FOLDER"] + directory = os.path.join(base, plugin, str(context_id)) + return send_from_directory(directory, filename) + +@bp.route('/featured///', methods=['POST']) +def set_featured_image(context, context_id, media_id): + """ + Single‐select “featured” toggle for any plugin (plants, grow_logs, etc). + """ + # normalize to plural + plugin_ctx = context if context.endswith('s') else context + 's' + if plugin_ctx not in ('plants', 'grow_logs', 'users', 'vendors'): + abort(404) + + # must own that media row + media = Media.query.filter_by( + plugin=plugin_ctx, + related_id=context_id, + id=media_id + ).first_or_404() + + # clear out any existing FeaturedImage.query.filter_by( - context=context, + context=plugin_ctx, context_id=context_id ).delete() - feat = FeaturedImage( + # insert new featured row + fi = FeaturedImage( media_id=media.id, - context=context, + context=plugin_ctx, context_id=context_id, is_featured=True ) - db.session.add(feat) - - if context == "plant": - plant = Plant.query.get_or_404(context_id) - plant.featured_media_id = media.id - + db.session.add(fi) db.session.commit() - return jsonify({"status": "success", "media_id": media.id}) + + return jsonify({"media_id": media.id}) @bp.route("/delete/", methods=["POST"]) diff --git a/plugins/plant/templates/plant/edit.html b/plugins/plant/templates/plant/edit.html index d5fe03e..a5ab9d2 100644 --- a/plugins/plant/templates/plant/edit.html +++ b/plugins/plant/templates/plant/edit.html @@ -5,6 +5,7 @@

Edit Plant

+ {# ——— Plant Edit Form ——— #}
{{ form.hidden_tag() }} @@ -54,6 +55,7 @@
+ {# ——— Upload New Image ——— #}

Upload Image

+ {# ——— Existing Images & Featured Toggle ——— #}

Existing Images

-
{{ form.csrf_token }}
- {% for media in plant.media %} + {% for media in plant.media_items %}
Plant Image
+ {# Featured radio driven off media.featured #}
-
- + {# Rotate button #} + -
- - -
+ {# Delete checkbox #} +
+ +
-
@@ -132,43 +141,42 @@ {% endblock %} {% block scripts %} - + {% endblock %}