From 579d4681f8d219060c03dac1dbf056b88b3a8b42 Mon Sep 17 00:00:00 2001 From: Andrea Callia D'Iddio <ac4014@ic.ac.uk> Date: Mon, 13 Feb 2023 17:10:47 +0000 Subject: [PATCH] Feat: add new non-mandatory fields. --- app/forms/project.py | 56 ++++++++++++------- app/models/project.py | 9 ++- app/templates/pages/project-form.html | 11 +++- app/templates/pages/staff/project-view.html | 9 +++ app/templates/pages/student/project-view.html | 9 +++ app/views/staff.py | 15 +++++ ...7f_add_new_non_mandatory_project_fields.py | 39 +++++++++++++ 7 files changed, 125 insertions(+), 23 deletions(-) create mode 100644 migrations/versions/592ed715cb7f_add_new_non_mandatory_project_fields.py diff --git a/app/forms/project.py b/app/forms/project.py index aa46ffc..9cddae3 100644 --- a/app/forms/project.py +++ b/app/forms/project.py @@ -14,20 +14,54 @@ from wtforms.validators import DataRequired, ValidationError class ProjectForm(FlaskForm): title = StringField("Title", validators=[DataRequired()]) description = TextAreaField("Description", validators=[DataRequired()]) + background_skills = TextAreaField("Background skills") is_student_proposal = BooleanField("Student Proposal", default=False) on_behalf = StringField("from", default=None) category = SelectField("Category", coerce=str) + meeting_modes = [("", "N/A"), ("remote", "Remote"), ("in-person", "In person")] meeting_mode = SelectField( "Meeting type", - choices=[("", "N/A"), ("remote", "Remote"), ("in-person", "In person")], + choices=meeting_modes, coerce=str, - validators=[validators.Optional()], + validators=[ + validators.Optional(), + validators.AnyOf([c[0] for c in meeting_modes]), + ], ) proposed_start_date = DateField( "Proposed start date", validators=[validators.Optional()] ) duration_in_weeks = IntegerField( - "Duration (in weeks)", validators=[validators.Optional()] + "Duration (in weeks)", + validators=[validators.Optional(), validators.NumberRange(min=0)], + ) + time_commitments = [ + ("", "N/A"), + ("full-time", "Full-time"), + ("part-time", "Part-time"), + ] + time_commitment = SelectField( + "Time Commitment", + choices=time_commitments, + coerce=str, + validators=[ + validators.Optional(), + validators.AnyOf([c[0] for c in time_commitments]), + ], + ) + lab_usages = [ + ("", "N/A"), + ("lab-based", "Lab-based project"), + ("non-lab-based", "Not lab-based"), + ] + lab_usage = SelectField( + "Lab usage", + choices=lab_usages, + coerce=str, + validators=[ + validators.Optional(), + validators.AnyOf([c[0] for c in lab_usages]), + ], ) def validate_on_behalf(self, field): @@ -40,19 +74,3 @@ class ProjectForm(FlaskForm): 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.") - - def validate_meeting_mode(self, field): - if field == self.category and field.data not in ["", "remote", "in-person"]: - self.meeting_mode.errors += "Invalid meeting mode." - raise ValidationError( - "The meeting mode for the project is invalid. Choose a valid value or leave it blank." - ) - - def validate_duration(self, field): - if all( - (field == self.duration_in_weeks, field.data is not None, field.data < 0) - ): - self.meeting_mode.errors += "Invalid duration." - raise ValidationError( - "The duration for the project is invalid. Choose a valid value or leave it blank." - ) diff --git a/app/models/project.py b/app/models/project.py index 0b65856..0b57c87 100644 --- a/app/models/project.py +++ b/app/models/project.py @@ -5,14 +5,17 @@ from .dialect_compatibility import utcnow class Project(db.Model): id = db.Column(db.Integer, primary_key=True) - proposer = db.Column(db.String) + proposer = db.Column(db.String, nullable=False) on_behalf = db.Column(db.String) - title = db.Column(db.String) - description = db.Column(db.String) + title = db.Column(db.String, nullable=False) + description = db.Column(db.String, nullable=False) + background_skills = db.Column(db.String) category = db.Column(db.String, db.ForeignKey(Category.code), nullable=False) is_remote = db.Column(db.Boolean) proposed_start_date = db.Column(db.Date) duration_in_weeks = db.Column(db.Integer) + is_part_time = db.Column(db.Boolean) + is_lab_based = db.Column(db.Boolean) timestamp = db.Column(db.DateTime, nullable=False, server_default=utcnow()) deleted = db.Column(db.DateTime) diff --git a/app/templates/pages/project-form.html b/app/templates/pages/project-form.html index 72af50b..05662b7 100644 --- a/app/templates/pages/project-form.html +++ b/app/templates/pages/project-form.html @@ -13,7 +13,10 @@ {{ form.title.label }} {{ form.title(placeholder="Project title", class="w3-input w3-border") }} </section> <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") }} + {{ form.description.label }} {{ form.description(placeholder="Please add here a 200-word description of your project, followed by information about external partners (e.g. industry, etc.).", rows="10", class="w3-input w3-border") }} + </section> + <section class="w3-section"> + {{ form.background_skills.label }} {{ form.background_skills(placeholder="(Optional) Please add here a 100-word description of the background skills required for your project.", rows="5", class="w3-input w3-border") }} </section> <section class="w3-section"> {{ form.category.label }} {{ form.category() }} @@ -27,6 +30,12 @@ <section class="w3-section"> {{ form.duration_in_weeks.label }} {{ form.duration_in_weeks() }} </section> + <section class="w3-section"> + {{ form.time_commitment.label }} {{ form.time_commitment() }} + </section> + <section class="w3-section"> + {{ form.lab_usage.label }} {{ form.lab_usage() }} + </section> <section class="w3-section"> <div class="w3-quarter"> {{ form.is_student_proposal(class="w3-check", id="is-student-proposal") }} {{ form.is_student_proposal.label }} diff --git a/app/templates/pages/staff/project-view.html b/app/templates/pages/staff/project-view.html index 4711ea3..15d3073 100644 --- a/app/templates/pages/staff/project-view.html +++ b/app/templates/pages/staff/project-view.html @@ -19,6 +19,9 @@ {{ project_details_section('Title', project.title) }} {{ project_details_section('Proposer', person.full_name if person.full_name else person.username) }} {{ project_details_section('Description', project.description) }} + {% if project.background_skills %} + {{ project_details_section('Background skills', project.background_skills) }} + {% endif %} {% if project.is_remote %} {{ project_details_section('Meeting mode', "Remote" if project.is_remote else "In person") }} {% endif %} @@ -28,6 +31,12 @@ {% if project.duration_in_weeks %} {{ project_details_section('Duration in weeks', project.duration_in_weeks) }} {% endif %} + {% if project.is_part_time %} + {{ project_details_section('Time commitment', "Part-time" if project.is_part_time else "Full-time") }} + {% endif %} + {% if project.is_lab_based %} + {{ project_details_section('Lab usage', "Lab-based" if project.is_lab_based else "Not lab-based") }} + {% endif %} </div> </div> diff --git a/app/templates/pages/student/project-view.html b/app/templates/pages/student/project-view.html index 529e160..adba413 100644 --- a/app/templates/pages/student/project-view.html +++ b/app/templates/pages/student/project-view.html @@ -19,6 +19,9 @@ {{ project_details_section('Title', project.title) }} {{ project_details_section('Proposer', person.full_name if person.full_name else person.username) }} {{ project_details_section('Description', project.description) }} + {% if project.background_skills %} + {{ project_details_section('Background skills', project.background_skills) }} + {% endif %} {% if project.is_remote %} {{ project_details_section('Meeting mode', "Remote" if project.is_remote else "In person") }} {% endif %} @@ -28,6 +31,12 @@ {% if project.duration_in_weeks %} {{ project_details_section('Duration in weeks', project.duration_in_weeks) }} {% endif %} + {% if project.is_part_time %} + {{ project_details_section('Time commitment', "Part-time" if project.is_part_time else "Full-time") }} + {% endif %} + {% if project.is_lab_based %} + {{ project_details_section('Lab usage', "Lab-based" if project.is_lab_based else "Not lab-based") }} + {% endif %} </div> </div> diff --git a/app/views/staff.py b/app/views/staff.py index c427c24..fa4c80e 100644 --- a/app/views/staff.py +++ b/app/views/staff.py @@ -82,6 +82,9 @@ def create_project(): project = Project( title=form.title.data, description=form.description.data, + background_skills=form.background_skills.data + if form.background_skills.data not in [None, ""] + else None, proposer=current_user.username, on_behalf=form.on_behalf.data if form.is_student_proposal.data else None, category=form.category.data, @@ -90,6 +93,16 @@ def create_project(): if form.meeting_mode.data is not None else None ), + is_part_time=( + form.time_commitment.data == "part-time" + if form.time_commitment.data is not None + else None + ), + is_lab_based=( + form.lab_usage.data == "lab-based" + if form.lab_usage.data is not None + else None + ), proposed_start_date=form.proposed_start_date.data, duration_in_weeks=form.duration_in_weeks.data, ) @@ -167,6 +180,8 @@ def edit_project(project_id): return redirect(url_for("staff.projects")) form = ProjectForm(obj=project) form.meeting_mode.data = "remote" if project.is_remote is True else "" + form.time_commitment.data = "part-time" if project.is_part_time is True else "" + form.lab_usage.data = "lab-based" if project.is_lab_based is True else "" form.category.choices = [(c.code, c.name) for c in categories] if project.on_behalf is not None: diff --git a/migrations/versions/592ed715cb7f_add_new_non_mandatory_project_fields.py b/migrations/versions/592ed715cb7f_add_new_non_mandatory_project_fields.py new file mode 100644 index 0000000..95d6ffc --- /dev/null +++ b/migrations/versions/592ed715cb7f_add_new_non_mandatory_project_fields.py @@ -0,0 +1,39 @@ +"""Add new non-mandatory project fields. + +Revision ID: 592ed715cb7f +Revises: 272f89c13a48 +Create Date: 2023-02-13 14:47:22.105560 + +""" +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision = "592ed715cb7f" +down_revision = "272f89c13a48" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column("project", sa.Column("background_skills", sa.String(), nullable=True)) + op.add_column("project", sa.Column("is_part_time", sa.Boolean(), nullable=True)) + op.add_column("project", sa.Column("is_lab_based", sa.Boolean(), nullable=True)) + op.alter_column("project", "proposer", existing_type=sa.VARCHAR(), nullable=False) + op.alter_column("project", "title", existing_type=sa.VARCHAR(), nullable=False) + op.alter_column( + "project", "description", existing_type=sa.VARCHAR(), nullable=False + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column("project", "description", existing_type=sa.VARCHAR(), nullable=True) + op.alter_column("project", "title", existing_type=sa.VARCHAR(), nullable=True) + op.alter_column("project", "proposer", existing_type=sa.VARCHAR(), nullable=True) + op.drop_column("project", "is_lab_based") + op.drop_column("project", "is_part_time") + op.drop_column("project", "background_skills") + # ### end Alembic commands ### -- GitLab