Skip to content
Snippets Groups Projects
Commit 338819b6 authored by Andrea Callia D'Iddio's avatar Andrea Callia D'Iddio
Browse files

Feat: add support for categories in the whole web interface.

parent fdfd0ecd
No related branches found
No related tags found
1 merge request!14WIP: Support group based restriction
This commit is part of merge request !14. Comments created here will be created in the context of that merge request.
from flask_wtf import FlaskForm
from wtforms import BooleanField, StringField, TextAreaField
from wtforms import BooleanField, SelectField, StringField, TextAreaField
from wtforms.validators import DataRequired, ValidationError
......@@ -8,6 +8,7 @@ class ProjectForm(FlaskForm):
description = TextAreaField("Description", validators=[DataRequired()])
is_student_proposal = BooleanField("Student Proposal", default=False)
on_behalf = StringField("from", default=None)
category = SelectField("Category", coerce=str)
def validate_on_behalf(self, field):
if self.is_student_proposal.data and not field.data:
......
......@@ -17,5 +17,6 @@ class Project(db.Model):
"Shortlisting", backref="project", lazy=True, cascade="all,delete-orphan"
)
@property
def is_student_proposal(self) -> bool:
return self.on_behalf is not None
return self.on_behalf is not None and self.on_behalf != ""
......@@ -15,6 +15,9 @@
<section class="w3-section">
{{ form.description.label }} {{ form.description(placeholder="Please add here a 200-word description of your project, followed by a list of required skills and, if applicable, by information about external partners (e.g. industry, etc.).", rows="10", class="w3-input w3-border") }}
</section>
<section class="w3-section">
{{ form.category.label }} {{ form.category() }}
</section>
<section class="w3-section">
<div class="w3-quarter">
{{ form.is_student_proposal(class="w3-check", id="is-student-proposal") }}&ensp;{{ form.is_student_proposal.label }}
......
......@@ -8,6 +8,7 @@ from app import messages
from app.constants import DEADLINE_FOR_STAFF_CHANGES
from app.database import db
from app.forms.project import ProjectForm
from app.models.category import Category
from app.models.person import Person
from app.models.project import Project
from app.models.shortlist import Shortlisting
......@@ -37,20 +38,20 @@ def unshortlist_old_proposer(project: Project):
@login_required
@staff_only
def projects():
categories: list[str] = (
category_codes: list[str] = (
Person.query.filter_by(username=current_user.username).first().categories
)
allow_edit = True if datetime.utcnow() <= DEADLINE_FOR_STAFF_CHANGES else False
own_projects: list[Project]
own_projects: list[Project] = (
Project.query.filter_by(proposer=current_user.username)
.filter(Project.category.in_(categories))
.filter(Project.category.in_(category_codes))
.filter(Project.deleted.is_(None))
.all()
)
other_projects: list[Project] = (
Project.query.filter(Project.proposer != current_user.username)
.filter(Project.category.in_(categories))
.filter(Project.category.in_(category_codes))
.filter(Project.deleted.is_(None))
.all()
)
......@@ -67,20 +68,30 @@ def projects():
@staff_only
@only_before_deadline_for_staff
def create_project():
category_codes: list[str] = (
Person.query.filter_by(username=current_user.username).first().categories
)
categories: list[Category] = Category.query.filter(
Category.code.in_(category_codes)
).all()
form = ProjectForm()
form.category.choices = [(c.code, c.name) for c in categories]
if form.validate_on_submit():
project = Project(
title=form.title.data,
description=form.description.data,
proposer=current_user.username,
on_behalf=form.on_behalf.data if form.on_behalf.data != "" else None,
on_behalf=form.on_behalf.data if form.is_student_proposal.data else None,
category=form.category.data,
)
db.session.add(project)
db.session.commit()
if project.on_behalf:
shortlist_proposer(project)
return redirect(url_for("staff.projects"))
return render_template("pages/project-form.html", form=form, person=Person())
return render_template(
"pages/project-form.html", form=form, person=Person(), categories=categories
)
@bp.route("/projects/<project_id>/delete")
......@@ -88,7 +99,16 @@ def create_project():
@staff_only
@only_before_deadline_for_staff
def delete_project(project_id):
if project := Project.query.get(project_id):
can_delete = True
category_codes: list[str] = (
Person.query.filter_by(username=current_user.username).first().categories
)
project = Project.query.get(project_id)
if not project:
can_delete = False
elif project.category not in category_codes:
can_delete = False
if can_delete:
project.deleted = datetime.utcnow()
db.session.commit()
else:
......@@ -104,20 +124,37 @@ def edit_project(project_id):
# show_box is a boolean used to decide if we show the text box for student full name. by default this is not shown
show_box = False
person = None
if project := Project.query.get(project_id):
can_edit = True
category_codes: list[str] = (
Person.query.filter_by(username=current_user.username).first().categories
)
categories: list[Category] = Category.query.filter(
Category.code.in_(category_codes)
).all()
project = Project.query.get(project_id)
if not project:
can_edit = False
elif project.category not in category_codes:
can_edit = False
if can_edit:
form = ProjectForm()
form.category.choices = [(c.code, c.name) for c in categories]
on_behalf_changed = project.on_behalf != form.on_behalf.data
if on_behalf_changed and project.on_behalf:
unshortlist_old_proposer(project)
if form.validate_on_submit():
project.title = form.title.data
project.description = form.description.data
project.on_behalf = form.on_behalf.data
project.on_behalf = (
form.on_behalf.data if form.is_student_proposal.data else None
)
project.category = form.category.data
db.session.commit()
if project.on_behalf and on_behalf_changed:
shortlist_proposer(project)
return redirect(url_for("staff.projects"))
form = ProjectForm(obj=project)
form.category.choices = [(c.code, c.name) for c in categories]
if project.on_behalf is not None:
person = Person.query.filter(Person.username == project.on_behalf).first()
......
......@@ -16,10 +16,14 @@ bp = Blueprint("student", __name__, url_prefix="/student")
@login_required
@students_only
def projects():
category_codes: list[str] = (
Person.query.filter_by(username=current_user.username).first().categories
)
active_projects: list[Project] = (
Project.query.filter(
or_(Project.on_behalf.is_(None), Project.on_behalf == current_user.username)
)
.filter(Project.category.in_(category_codes))
.filter(Project.deleted.is_(None))
.all()
)
......@@ -86,7 +90,16 @@ def update_ranking():
@login_required
@students_only
def view_project(project_id):
if project := Project.query.get(project_id):
can_view = True
category_codes: list[str] = (
Person.query.filter_by(username=current_user.username).first().categories
)
project = Project.query.get(project_id)
if not project:
can_view = False
elif project.category not in category_codes:
can_view = False
if can_view:
username = project.proposer if project.on_behalf is None else project.on_behalf
person = Person.query.filter(Person.username == username).first() or Person(
......@@ -105,7 +118,16 @@ def view_project(project_id):
@students_only
@only_before_deadline_for_students
def shortlist_project(project_id):
if Project.query.get(project_id):
can_shortlist = True
category_codes: list[str] = (
Person.query.filter_by(username=current_user.username).first().categories
)
project = Project.query.get(project_id)
if not project:
can_shortlist = False
elif project.category not in category_codes:
can_shortlist = False
if can_shortlist:
shortlisting = Shortlisting(
student=current_user.username, project_id=project_id
)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment