from flask import abort, flash, redirect, render_template, request, url_for from flask_login import current_user, login_required from . import bp from .forms import ActionForm, STATUS_LABELS, SubtaskForm, TaskForm from .models import TASK_STATUSES from .services import ( TaskNotFoundError, add_subtask, create_task, delete_task, get_task, list_tasks, list_today_tasks, toggle_subtask, update_task, ) def _owned_task_or_404(task_id: int): try: return get_task(task_id, current_user.id) except TaskNotFoundError: abort(404) @bp.get("/") @login_required def index(): selected_status = request.args.get("status") or None if selected_status not in {None, *TASK_STATUSES}: abort(400) tasks = list_tasks(current_user.id, selected_status) return render_template( "tasks/list.html", tasks=tasks, selected_status=selected_status, status_labels=STATUS_LABELS, ) @bp.get("/today") @login_required def today(): tasks = list_today_tasks(current_user.id) return render_template("tasks/today.html", tasks=tasks) @bp.route("/new", methods=["GET", "POST"]) @login_required def create(): form = TaskForm() if form.validate_on_submit(): task = create_task( current_user.id, title=form.title.data, description=form.description.data, status=form.status.data, priority=form.priority.data, due_date=form.due_date.data, ) flash("Task captured.", "success") return redirect(url_for("tasks.detail", task_id=task.id)) return render_template("tasks/form.html", form=form, heading="New task") @bp.get("/") @login_required def detail(task_id: int): task = _owned_task_or_404(task_id) return render_template( "tasks/detail.html", task=task, subtask_form=SubtaskForm(), action_form=ActionForm(), ) @bp.route("//edit", methods=["GET", "POST"]) @login_required def edit(task_id: int): task = _owned_task_or_404(task_id) form = TaskForm(obj=task) if form.validate_on_submit(): update_task( task, title=form.title.data, description=form.description.data, status=form.status.data, priority=form.priority.data, due_date=form.due_date.data, ) flash("Task updated.", "success") return redirect(url_for("tasks.detail", task_id=task.id)) return render_template("tasks/form.html", form=form, heading="Edit task") @bp.post("//delete") @login_required def delete(task_id: int): task = _owned_task_or_404(task_id) form = ActionForm() if not form.validate_on_submit(): abort(400) delete_task(task) flash("Task deleted.", "info") return redirect(url_for("tasks.index")) @bp.post("//subtasks") @login_required def create_subtask(task_id: int): task = _owned_task_or_404(task_id) form = SubtaskForm() if form.validate_on_submit(): add_subtask(task, form.title.data) flash("Small step added.", "success") else: for errors in form.errors.values(): for error in errors: flash(error, "error") return redirect(url_for("tasks.detail", task_id=task.id)) @bp.post("//subtasks//toggle") @login_required def toggle_subtask_status(task_id: int, subtask_id: int): task = _owned_task_or_404(task_id) form = ActionForm() if not form.validate_on_submit(): abort(400) try: toggle_subtask(task, subtask_id) except TaskNotFoundError: abort(404) return redirect(url_for("tasks.detail", task_id=task.id))