sort of working, more changes

This commit is contained in:
2025-06-09 05:45:58 -05:00
parent d442cad0bb
commit f0b1abd622
102 changed files with 1448 additions and 2264 deletions

View File

@ -1,43 +1,205 @@
from flask import Blueprint, render_template, redirect, url_for, request, flash
from uuid import uuid4
from flask import (
Blueprint,
render_template,
redirect,
url_for,
request,
flash,
)
from flask_login import login_required, current_user
from app import db
from .models import Plant
from .models import Plant, PlantCommonName, PlantScientificName
from .forms import PlantForm
from plugins.media.models import Media
from plugins.media.utils import save_media_file, delete_media_file, rotate_media_file, generate_image_url
bp = Blueprint('plant', __name__, template_folder='templates')
bp = Blueprint(
'plant',
__name__,
url_prefix='/plants',
template_folder='templates'
)
@bp.route('/plants/')
# -----------------------------------------------------------------------------
# Make generate_image_url available in all templates
# -----------------------------------------------------------------------------
@bp.app_context_processor
def inject_image_helper():
return dict(generate_image_url=generate_image_url)
# ─── LIST ─────────────────────────────────────────────────────────────────────
@bp.route('/', methods=['GET'])
@login_required
def index():
plants = Plant.query.order_by(Plant.created_at.desc()).all()
return render_template('plant/index.html', plants=plants)
plants = (
Plant.query
.filter_by(owner_id=current_user.id)
.order_by(Plant.created_at.desc())
.all()
)
stats = {
'user_plants': Plant.query.filter_by(owner_id=current_user.id).count(),
'user_images': Media.query.filter_by(uploader_id=current_user.id).count(),
'total_plants': Plant.query.count(),
'total_images': Media.query.count(),
}
return render_template('plant/index.html', plants=plants, stats=stats)
@bp.route('/plants/<int:plant_id>')
def detail(plant_id):
plant = Plant.query.get_or_404(plant_id)
return render_template('plant/detail.html', plant=plant)
@bp.route('/plants/new', methods=['GET', 'POST'])
# ─── CREATE ───────────────────────────────────────────────────────────────────
@bp.route('/create', methods=['GET', 'POST'])
@login_required
def create():
form = PlantForm()
if form.validate_on_submit():
plant = Plant(
name=form.name.data,
type=form.type.data,
notes=form.notes.data,
is_active=form.is_active.data
)
db.session.add(plant)
db.session.commit()
flash('Plant created successfully.', 'success')
return redirect(url_for('plant.index'))
return render_template('plant/form.html', form=form)
@bp.route('/plants/<int:plant_id>/edit', methods=['GET', 'POST'])
def edit(plant_id):
plant = Plant.query.get_or_404(plant_id)
form = PlantForm(obj=plant)
# ─── dropdown choices ───────────────────────────────────────────────────────
form.plant_type.choices = [
('plant', 'Plant'),
('cutting', 'Cutting'),
('seed', 'Seed'),
('tissue_culture', 'Tissue Culture'),
('division', 'Division'),
]
form.common_name.choices = [
(c.id, c.name)
for c in PlantCommonName.query.order_by(PlantCommonName.name)
]
form.scientific_name.choices = [
(s.id, s.name)
for s in PlantScientificName.query.order_by(PlantScientificName.name)
]
form.mother_uuid.choices = [('N/A', 'None')] + [
(p.uuid, f"{p.common_name.name if p.common_name else 'Unnamed'} {p.uuid}")
for p in Plant.query.order_by(Plant.created_at.desc()).all()
]
if form.validate_on_submit():
form.populate_obj(plant)
new_plant = Plant(
uuid=str(uuid4()),
owner_id=current_user.id,
plant_type=form.plant_type.data,
common_id=form.common_name.data,
scientific_id=form.scientific_name.data,
mother_uuid=(
form.mother_uuid.data
if form.mother_uuid.data != 'N/A'
else None
),
custom_slug=form.custom_slug.data,
notes=form.notes.data,
data_verified=form.data_verified.data,
is_active=form.is_active.data,
)
db.session.add(new_plant)
db.session.commit()
flash('New plant created successfully.', 'success')
return redirect(url_for('plant.edit', uuid_val=new_plant.uuid))
return render_template('plant/create.html', form=form)
# ─── DETAIL ───────────────────────────────────────────────────────────────────
@bp.route('/<uuid:uuid_val>', methods=['GET'])
@login_required
def detail(uuid_val):
plant = Plant.query.filter_by(uuid=str(uuid_val)).first_or_404()
return render_template('plant/detail.html', plant=plant)
# ─── EDIT ─────────────────────────────────────────────────────────────────────
@bp.route('/<uuid:uuid_val>/edit', methods=['GET', 'POST'])
@login_required
def edit(uuid_val):
plant = Plant.query.filter_by(uuid=str(uuid_val)).first_or_404()
form = PlantForm()
form.plant_type.choices = [
('plant', 'Plant'),
('cutting', 'Cutting'),
('seed', 'Seed'),
('tissue_culture', 'Tissue Culture'),
('division', 'Division'),
]
form.common_name.choices = [
(c.id, c.name)
for c in PlantCommonName.query.order_by(PlantCommonName.name)
]
form.scientific_name.choices = [
(s.id, s.name)
for s in PlantScientificName.query.order_by(PlantScientificName.name)
]
form.mother_uuid.choices = [('N/A', 'None')] + [
(p.uuid, f"{p.common_name.name if p.common_name else 'Unnamed'} {p.uuid}")
for p in Plant.query.filter(Plant.uuid != plant.uuid).all()
]
if request.method == 'GET':
form.plant_type.data = plant.plant_type
form.common_name.data = plant.common_id
form.scientific_name.data = plant.scientific_id
form.mother_uuid.data = plant.mother_uuid or 'N/A'
form.custom_slug.data = plant.custom_slug
form.notes.data = plant.notes
form.data_verified.data = plant.data_verified
form.is_active.data = getattr(plant, 'is_active', True)
if form.validate_on_submit():
plant.plant_type = form.plant_type.data
plant.common_id = form.common_name.data
plant.scientific_id = form.scientific_name.data
plant.mother_uuid = (
form.mother_uuid.data
if form.mother_uuid.data != 'N/A'
else None
)
plant.custom_slug = form.custom_slug.data
plant.notes = form.notes.data
plant.data_verified = form.data_verified.data
plant.is_active = form.is_active.data
db.session.commit()
flash('Plant updated successfully.', 'success')
return redirect(url_for('plant.detail', plant_id=plant.id))
return render_template('plant/form.html', form=form, plant=plant)
return redirect(url_for('plant.detail', uuid_val=plant.uuid))
return render_template('plant/edit.html', form=form, plant=plant)
# ─── IMAGE ROUTES ────────────────────────────────────────────────────────────
@bp.route('/<uuid:uuid_val>/upload', methods=['POST'])
@login_required
def upload_image(uuid_val):
plant = Plant.query.filter_by(uuid=uuid_val).first_or_404()
file = request.files.get('file')
if file and file.filename:
save_media_file(
file,
current_user.id,
related_model='plant',
related_uuid=str(plant.uuid)
)
flash('Image uploaded successfully.', 'success')
return redirect(url_for('plant.edit', uuid_val=plant.uuid))
@bp.route('/<uuid:uuid_val>/feature/<int:media_id>', methods=['POST'])
@login_required
def set_featured_image(uuid_val, media_id):
plant = Plant.query.filter_by(uuid=uuid_val).first_or_404()
media = Media.query.get_or_404(media_id)
plant.featured_media_id = media.id
db.session.commit()
flash('Featured image set.', 'success')
return redirect(url_for('plant.edit', uuid_val=plant.uuid))
@bp.route('/<uuid:uuid_val>/delete/<int:media_id>', methods=['POST'])
@login_required
def delete_image(uuid_val, media_id):
plant = Plant.query.filter_by(uuid=uuid_val).first_or_404()
media = Media.query.get_or_404(media_id)
delete_media_file(media)
flash('Image deleted.', 'success')
return redirect(url_for('plant.edit', uuid_val=plant.uuid))
@bp.route('/<uuid:uuid_val>/rotate/<int:media_id>', methods=['POST'])
@login_required
def rotate_image(uuid_val, media_id):
plant = Plant.query.filter_by(uuid=uuid_val).first_or_404()
media = Media.query.get_or_404(media_id)
rotate_media_file(media)
flash('Image rotated.', 'success')
return redirect(url_for('plant.edit', uuid_val=plant.uuid))