Files
natureinpots_community/plugins/growlog/routes.py
2025-06-27 17:43:50 -05:00

177 lines
5.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from uuid import UUID as _UUID
from werkzeug.exceptions import NotFound
from flask import (
Blueprint, render_template, abort, redirect, url_for, request, flash
)
from flask_login import login_required, current_user
from app import db
from .models import GrowLog
from .forms import GrowLogForm
from plugins.plant.models import Plant, PlantCommonName
bp = Blueprint(
'growlog',
__name__,
url_prefix='/growlogs',
template_folder='templates',
)
def _get_plant_by_uuid(uuid_val):
"""
uuid_val may already be a uuid.UUID (from a <uuid:> route converter)
or a string (from form POST). Normalize & validate it, then lookup.
"""
# 1) If Flask route gave us a UUID instance, just stringify it
if isinstance(uuid_val, _UUID):
val = str(uuid_val)
else:
# 2) Otherwise try to parse it as a hex string
try:
val = str(_UUID(uuid_val))
except (ValueError, TypeError):
# invalid format → 404
abort(404)
# 3) Only return plants owned by current_user
return (
Plant.query
.filter_by(uuid=val, owner_id=current_user.id)
.first_or_404()
)
def _user_plant_choices():
# join to the commonname table and sort by its name
plants = (
Plant.query
.filter_by(owner_id=current_user.id)
.join(PlantCommonName, Plant.common_id == PlantCommonName.id)
.order_by(PlantCommonName.name)
.all()
)
return [
(p.uuid, f"{p.common_name.name} {p.uuid}")
for p in plants
]
@bp.route('/add', methods=['GET','POST'])
@bp.route('/<uuid:plant_uuid>/add', methods=['GET','POST'])
@login_required
def add_log(plant_uuid=None):
form = GrowLogForm()
# 1) always populate the dropdown behind the scenes
form.plant_uuid.choices = _user_plant_choices()
plant = None
hide_select = False
# 2) if URL had a plant_uuid, load & pre-select it, hide dropdown
if plant_uuid:
plant = _get_plant_by_uuid(plant_uuid)
form.plant_uuid.data = str(plant_uuid)
hide_select = True
if form.validate_on_submit():
# 3) on POST, resolve via form.plant_uuid
plant = _get_plant_by_uuid(form.plant_uuid.data)
log = GrowLog(
plant_id = plant.id,
event_type = form.event_type.data,
title = form.title.data,
notes = form.notes.data,
is_public = form.is_public.data,
)
db.session.add(log)
db.session.commit()
flash('Grow log added.', 'success')
return redirect(
url_for('growlog.list_logs', plant_uuid=plant.uuid)
)
return render_template(
'growlog/log_form.html',
form = form,
plant = plant,
hide_plant_select = hide_select
)
@bp.route('/', defaults={'plant_uuid': None})
@bp.route('/<uuid:plant_uuid>')
@login_required
def list_logs(plant_uuid):
# how many to show?
limit = request.args.get('limit', default=10, type=int)
if plant_uuid:
# logs for a single plant
plant = _get_plant_by_uuid(plant_uuid)
query = GrowLog.query.filter_by(plant_id=plant.id)
else:
# logs for all your plants
plant = None
query = (
GrowLog.query
.join(Plant, GrowLog.plant_id == Plant.id)
.filter(Plant.owner_id == current_user.id)
)
logs = (
query
.order_by(GrowLog.created_at.desc())
.limit(limit)
.all()
)
return render_template(
'growlog/log_list.html',
plant=plant,
logs=logs,
limit=limit
)
@bp.route('/<uuid:plant_uuid>/edit/<int:log_id>', methods=['GET', 'POST'])
@login_required
def edit_log(plant_uuid, log_id):
plant = _get_plant_by_uuid(plant_uuid)
log = GrowLog.query.filter_by(id=log_id, plant_id=plant.id).first_or_404()
form = GrowLogForm(obj=log)
# Lock the dropdown to this one plant
form.plant_uuid.choices = [(plant.uuid, plant.common_name.name)]
form.plant_uuid.data = plant.uuid
if form.validate_on_submit():
log.event_type = form.event_type.data
log.title = form.title.data
log.notes = form.notes.data
log.is_public = form.is_public.data
db.session.commit()
flash('Grow log updated.', 'success')
return redirect(url_for('growlog.list_logs', plant_uuid=plant_uuid))
return render_template(
'growlog/log_form.html',
form=form,
plant_uuid=plant_uuid,
plant=plant,
log=log
)
@bp.route('/<uuid:plant_uuid>/delete/<int:log_id>', methods=['POST'])
@login_required
def delete_log(plant_uuid, log_id):
plant = _get_plant_by_uuid(plant_uuid)
log = GrowLog.query.filter_by(id=log_id, plant_id=plant.id).first_or_404()
db.session.delete(log)
db.session.commit()
flash('Grow log deleted.', 'warning')
return redirect(url_for('growlog.list_logs', plant_uuid=plant_uuid))