Skip to content

Commit

Permalink
refactored codebase so tasks_controller is a separate module. Control…
Browse files Browse the repository at this point in the history
…ler logic was formerly in the view component, i.e., main.py
  • Loading branch information
Morgan-Sell committed Nov 17, 2024
1 parent e1c0718 commit 857d2e9
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 163 deletions.
21 changes: 0 additions & 21 deletions src/controllers/task_controller.py

This file was deleted.

131 changes: 131 additions & 0 deletions src/controllers/tasks_controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
from flask import Blueprint, flash, jsonify, redirect, render_template, url_for
from flask_login import login_required, current_user
from src.forms.task_form import AddTaskForm, DeleteTaskForm, EditTaskForm
from src.models import SessionLocal, Tasks
from src.repository.tasks_repository import TasksRespository

tasks_blueprint = Blueprint("tasks", __name__)


@tasks_blueprint.route("/<int:user_id>", methods=["GET", "POST"])
@login_required
def view_tasks(user_id):
session = SessionLocal()
task_repo = TasksRespository(session)
tasks = task_repo.find_tasks_by_user(user_id)
session.close()
return render_template("view_tasks.html", tasks=tasks)


@tasks_blueprint.route("/add/<int:user_id>", methods=["GET", "POST"])
@login_required
def add_task(user_id):
form = AddTaskForm()

if form.validate_on_submit():
title = form.title.data
description = form.description.data
status = form.status.data

session = SessionLocal()
task_repo = TasksRespository(session)

task = Tasks(
title=title, description=description, status=status, user_id=user_id
)
task_repo.add_task(task)
session.close()

flash("Task successfully created.", "success")
return redirect(url_for("tasks.view_tasks", user_id=user_id))

return render_template("add_task.html", form=form, user_id=user_id)


@tasks_blueprint.route("/edit/<int:user_id>", methods=["GET", "POST"])
@login_required
def edit_task(user_id):
form = EditTaskForm()

if form.validate_on_submit():
# gather data from the form
task_id = form.id.data
new_title = form.title.data or None # Convert blank to None
new_description = form.description.data or None # Convert blank to None
new_status = form.status.data or None # Convert blank to None

# initiate DB and collect relevant data
session = SessionLocal()
task_repo = TasksRespository(session)
tasks = task_repo.find_tasks_by_user(user_id)
all_ids = [task.id for task in tasks]

# Check is username has access to the selected task
if task_id not in all_ids:
flash(
f"Task # {task_id} is not associated with this user. Enter another task ID.",
"danger",
)
session.close()
return redirect(url_for("tasks.edit_task", user_id=user_id))

# User is able to edit task
task_repo.edit_task(
task_id=task_id,
title=new_title,
description=new_description,
status=new_status,
)
flash("Task successfully created.", "success")
return redirect(url_for("tasks.view_tasks", user_id=user_id))

return render_template("edit_task.html", form=form, user_id=user_id)


@tasks_blueprint.route("/delete/<int:user_id>", methods=["GET", "POST"])
@login_required
def delete_task(user_id):
form = DeleteTaskForm()

if form.validate_on_submit():
task_id = form.id.data

# initiate DB and collect relevant data
session = SessionLocal()
task_repo = TasksRespository(session)
tasks = task_repo.find_tasks_by_user(user_id)
all_ids = [task.id for task in tasks]

# Check if task belongs to the user
if task_id not in all_ids:
flash(
f"Task # {task_id} is not associated with this user. Enter another task ID.",
"danger",
)
session.close()
return redirect(url_for("tasks.delete_task", user_id=user_id))

return render_template("delete_task.html", form=form, user_id=user_id)


@tasks_blueprint.route("/api/<int:task_id>")
@login_required
def get_task_details(task_id):
session = SessionLocal()
task_repo = TasksRespository(session)
task = task_repo.find_task_by_id(task_id)
session.close()

if task is not None:
return jsonify(
{
"title": task.title,
"description": task.description,
"status": task.status,
}
)
else:
return (
jsonify({"error": f"Task ID {task_id} does not exist for this user."}),
404,
)
140 changes: 6 additions & 134 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from flask import Flask, flash, jsonify, redirect, render_template, request, url_for
from flask import Flask, flash, redirect, render_template, url_for
from flask_login import LoginManager, login_required, login_user, logout_user

from src.forms.task_form import AddTaskForm, DeleteTaskForm, EditTaskForm
from src.forms.user_forms import LogInForm, RegisterForm
from src.models import Base, SessionLocal, Tasks, Users, engine
from src.repository.tasks_repository import TasksRespository
from src.repository.users_repository import UsersRepository
from src.security import generate_password_hash

from src.controllers.tasks_controller import tasks_blueprint

app = Flask(__name__, static_folder="../static", template_folder="../templates")
app.config["SECRET_KEY"] = "shhhh_dont_tell_anyone"
Expand All @@ -20,6 +20,8 @@
# Ensure tables are created
Base.metadata.create_all(bind=engine)

# Register blueprints to for tasks and users controllers
app.register_blueprint(tasks_blueprint, url_prefix="/tasks")

@login_manager.user_loader
def load_user(user_id):
Expand Down Expand Up @@ -53,7 +55,7 @@ def login():
else:
login_user(user)
session.close()
return redirect(url_for("view_tasks", user_id=user.id))
return redirect(url_for("tasks.view_tasks", user_id=user.id))

return render_template("login.html", form=form)

Expand All @@ -66,12 +68,6 @@ def logout():
return redirect(url_for("login"))


@app.route("/dashboard")
@login_required
def dashboard():
return "Welcome to your dashboard!"


@app.route("/register", methods=["GET", "POST"])
def register():
form = RegisterForm()
Expand All @@ -96,129 +92,5 @@ def register():
return render_template("register.html", form=form)


@app.route("/tasks/<int:user_id>")
@login_required
def view_tasks(user_id):
session = SessionLocal()
task_repo = TasksRespository(session)
tasks = task_repo.find_tasks_by_user(user_id)
session.close()
return render_template("view_tasks.html", tasks=tasks)


@app.route("/add_task/<int:user_id>", methods=["GET", "POST"])
@login_required
def add_task(user_id):
form = AddTaskForm()

if form.validate_on_submit():
title = form.title.data
description = form.description.data
status = form.status.data

session = SessionLocal()
task_repo = TasksRespository(session)

task = Tasks(
title=title, description=description, status=status, user_id=user_id
)
task_repo.add_task(task)
session.close()

flash("Task successfully created.", "success")
return redirect(url_for("view_tasks", user_id=user_id))

return render_template("add_task.html", form=form, user_id=user_id)


@app.route("/edit_task/<int:user_id>", methods=["GET", "POST"])
@login_required
def edit_task(user_id):
form = EditTaskForm()

if form.validate_on_submit():
# gather data from the form
task_id = form.id.data
new_title = form.title.data or None # Convert blank to None
new_description = form.description.data or None # Convert blank to None
new_status = form.status.data or None # Convert blank to None

# initiate DB and collect relevant data
session = SessionLocal()
task_repo = TasksRespository(session)
tasks = task_repo.find_tasks_by_user(user_id)
all_ids = [task.id for task in tasks]

# Check is username has access to the selected task
if task_id not in all_ids:
flash(
f"Task # {task_id} is not associated with this user. Enter another task ID.",
"danger",
)
session.close()
return redirect(url_for("edit_task", user_id=user_id))

# User is able to edit task
task_repo.edit_task(
task_id=task_id,
title=new_title,
description=new_description,
status=new_status,
)
flash("Task successfully created.", "success")
return redirect(url_for("view_tasks", user_id=user_id))

return render_template("edit_task.html", form=form, user_id=user_id)


@app.route("/delete_task/<int:user_id>", methods=["GET", "POST"])
@login_required
def delete_task(user_id):
form = DeleteTaskForm()

if form.validate_on_submit():
task_id = form.id.data

# initiate DB and collect relevant data
session = SessionLocal()
task_repo = TasksRespository(session)
tasks = task_repo.find_tasks_by_user(user_id)
all_ids = [task.id for task in tasks]

# Check if task belongs to the user
if task_id not in all_ids:
flash(
f"Task # {task_id} is not associated with this user. Enter another task ID.",
"danger",
)
session.close()
return redirect(url_for("delete_task", user_id=user_id))

return render_template("delete_task.html", form=form, user_id=user_id)


@app.route("/api/task/<int:task_id>")
@login_required
def get_task_details(task_id):
session = SessionLocal()
task_repo = TasksRespository(session)
task = task_repo.find_task_by_id(task_id)
session.close()

if task is not None:
return jsonify(
{
"title": task.title,
"description": task.description,
"status": task.status,
}
)
else:
return (
jsonify({"error": f"Task ID {task_id} does not exist for this user."}),
404,
)


if __name__ == "__main__":
app.run(debug=True, port=5001)
2 changes: 1 addition & 1 deletion templates/add_task.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<div class="text-center mb-4">
<h2 class="mt-2" style="font-family: 'Lobster', cursive; font-size: 2rem; color: #333;">Add a Task to Your ToDo List</h2>
</div>
<form method="POST" action="{{ url_for('add_task', user_id=user_id) }}">
<form method="POST" action="{{ url_for('tasks.add_task', user_id=user_id) }}">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.title.label }}
Expand Down
8 changes: 4 additions & 4 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
Settings
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="{{ url_for('view_tasks', user_id=current_user.id) }}">View Tasks</a>
<a class="dropdown-item" href="{{ url_for('add_task', user_id=current_user.id) }}">Add Task</a>
<a class="dropdown-item" href="{{ url_for('edit_task', user_id=current_user.id) }}">Edit Task</a>
<a class="dropdown-item" href="{{ url_for('delete_task', user_id=current_user.id) }}">Delete Task</a>
<a class="dropdown-item" href="{{ url_for('tasks.view_tasks', user_id=current_user.id) }}">View Tasks</a>
<a class="dropdown-item" href="{{ url_for('tasks.add_task', user_id=current_user.id) }}">Add Task</a>
<a class="dropdown-item" href="{{ url_for('tasks.edit_task', user_id=current_user.id) }}">Edit Task</a>
<a class="dropdown-item" href="{{ url_for('tasks.delete_task', user_id=current_user.id) }}">Delete Task</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger" href="{{ url_for('logout') }}">Log Out</a>
</div>
Expand Down
4 changes: 2 additions & 2 deletions templates/delete_task.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ <h4 class="subheader mt-2">
then the selected task is not associated with the active user.
</h4>
</div>
<form method="POST" action="{{ url_for('delete_task', user_id=user_id) }}">
<form method="POST" action="{{ url_for('tasks.delete_task', user_id=user_id) }}">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.id.label }}
Expand Down Expand Up @@ -50,7 +50,7 @@ <h4 class="subheader mt-2">
const taskId = this.value;

// Fetch task details via an API (adjust URL as needed)
fetch(`/api/task/${taskId}`)
fetch(`/tasks/api/${taskId}`)
.then(response => response.json())
.then(data => {
// Populate the fields with task details
Expand Down
2 changes: 1 addition & 1 deletion templates/edit_task.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<div class="text-center mb-4">
<h2 class="mt-2" style="font-family: 'Lobster', cursive; font-size: 2rem; color: #333;">Edit Your Task</h2>
</div>
<form method="POST" action="{{ url_for('edit_task', user_id=user_id) }}">
<form method="POST" action="{{ url_for('tasks.edit_task', user_id=user_id) }}">
{{ form.hidden_tag() }}
<div class="form-group">
{{ form.id.label }}
Expand Down

0 comments on commit 857d2e9

Please sign in to comment.