From be0f88a2e9b390e886a6897a75a6a76b3f2fcaa0 Mon Sep 17 00:00:00 2001
From: Andrea Callia D'Iddio <ac4014@ic.ac.uk>
Date: Mon, 6 Feb 2023 14:52:59 +0000
Subject: [PATCH] Feat: add checks about validity of project category.

---
 app/forms/project.py             |  5 +++++
 app/messages/__init__.py         |  3 +++
 app/messages/message_builders.py | 10 ++++++++++
 app/views/staff.py               | 13 +++++++++----
 4 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/app/forms/project.py b/app/forms/project.py
index fd3982b..8bc9f11 100644
--- a/app/forms/project.py
+++ b/app/forms/project.py
@@ -15,3 +15,8 @@ class ProjectForm(FlaskForm):
             raise ValidationError(
                 "Student proposer cannot be empty if project is marked as student proposal."
             )
+
+    def validate_category(self, field):
+        if field == self.category and field.data == "":
+            self.category.errors += "Please choose a category for the project."
+            raise ValidationError("Please choose a category for the project.")
diff --git a/app/messages/__init__.py b/app/messages/__init__.py
index f721558..62f5274 100644
--- a/app/messages/__init__.py
+++ b/app/messages/__init__.py
@@ -1,6 +1,7 @@
 from .message_builders import (
     deadline_expired_for_staff,
     deadline_expired_for_students,
+    invalid_category,
     login_manager_message,
     login_unsuccessful_error,
     project_not_found,
@@ -17,5 +18,7 @@ LOGIN_MANAGER_MESSAGE = login_manager_message()
 PROJECT_NOT_FOUND = project_not_found()
 SHORTLIST_NOT_FOUND = shortlist_not_found()
 
+INVALID_CATEGORY = invalid_category()
+
 DEADLINE_EXPIRED_FOR_STUDENTS = deadline_expired_for_students()
 DEADLINE_EXPIRED_FOR_STAFF = deadline_expired_for_staff()
diff --git a/app/messages/message_builders.py b/app/messages/message_builders.py
index 9f81dff..de3184e 100644
--- a/app/messages/message_builders.py
+++ b/app/messages/message_builders.py
@@ -66,6 +66,16 @@ def shortlist_not_found():
     )
 
 
+def invalid_category():
+    return MessageEncoder.encode(
+        Message(
+            header="<h3><strong>Invalid category</strong></h3>",
+            body="<p>Please select a valid category for the project.</p>",
+            style=ERROR,
+        )
+    )
+
+
 def deadline_expired_for_students():
     return MessageEncoder.encode(
         Message(
diff --git a/app/views/staff.py b/app/views/staff.py
index d23bf52..e400f5d 100644
--- a/app/views/staff.py
+++ b/app/views/staff.py
@@ -75,7 +75,9 @@ def create_project():
         Category.code.in_(category_codes)
     ).all()
     form = ProjectForm()
-    form.category.choices = [(c.code, c.name) for c in categories]
+    form.category.choices = [("", "Choose an option")] + [
+        (c.code, c.name) for c in categories
+    ]
     if form.validate_on_submit():
         project = Project(
             title=form.title.data,
@@ -89,6 +91,9 @@ def create_project():
         if project.on_behalf:
             shortlist_proposer(project)
         return redirect(url_for("staff.projects"))
+    elif request.method == "POST":
+        if form.category.data not in category_codes:
+            flash(messages.INVALID_CATEGORY)
     return render_template(
         "pages/project-form.html", form=form, person=Person(), categories=categories
     )
@@ -194,7 +199,7 @@ def view_project(project_id):
 @login_required
 @staff_only
 def projects_ranking():
-    projects: list[Shortlisting] = (
+    own_projects: list[Shortlisting] = (
         Shortlisting.query.join(Project)
         .filter(Project.proposer == current_user.username)
         .order_by(Shortlisting.staff_ranking)
@@ -203,7 +208,7 @@ def projects_ranking():
 
     full_names = {}
 
-    for shortlisting in projects:
+    for shortlisting in own_projects:
         person = Person.query.filter(
             Person.username == shortlisting.student
         ).first() or Person(username=shortlisting.student, firstname="", lastname="")
@@ -214,7 +219,7 @@ def projects_ranking():
 
     return render_template(
         "pages/staff/shortlisted-projects.html",
-        projects=projects,
+        projects=own_projects,
         full_names=full_names,
     )
 
-- 
GitLab