diff --git a/advlabdb/assistantModelViews.py b/advlabdb/assistantModelViews.py index 1fee7c6..bec6629 100644 --- a/advlabdb/assistantModelViews.py +++ b/advlabdb/assistantModelViews.py @@ -1,7 +1,7 @@ -from flask import flash +from flask import flash, redirect, request, url_for from flask_admin import expose from flask_security import admin_change_password, current_user -from wtforms import Form +from flask_wtf import FlaskForm from wtforms.fields import TextAreaField from wtforms.validators import Optional @@ -15,13 +15,14 @@ from .advlabdb_independent_funs import ( ) from .customClasses import SecureAssistantBaseView, SecureAssistantModelView from .exceptions import DataBaseException, ModelViewException +from .forms import assistant_group_experiment_form_factory from .model_dependent_funs import ( generate_new_password_field, initActiveSemesterMenuLinks, mark_field, user_info_fields, ) -from .model_independent_funs import randomPassword +from .model_independent_funs import randomPassword, reportBadAttempt from .models import ( MAX_MARK, MIN_MARK, @@ -35,7 +36,7 @@ from .models import ( class AssistantGroupExperimentView(SecureAssistantModelView): - class EditForm(Form): + class EditForm(FlaskForm): note = TextAreaField( "Note", validators=[Optional()], @@ -66,6 +67,58 @@ class AssistantGroupExperimentView(SecureAssistantModelView): .where(Assistant.user == current_user) ) + @expose("/form/", methods=("GET", "POST")) + def form_view(self): + group_experiment_id_str = request.args.get("id") + + try: + group_experiment = db.session.get(GroupExperiment, int(group_experiment_id_str)) + except: + red = url_for("index") + "assistant/group_experiment" + flash("No valid group experiment id") + return redirect(red) + + if group_experiment not in self.get_query(): + reportBadAttempt("Assistant {current_user} tried to edit {group_experiment}") + raise ModelViewException("Unauthorized action!") + + form, appointments, experiment_marks = assistant_group_experiment_form_factory(current_user, group_experiment) + + num_appointments = len(appointments) + appointment_fields = [ + getattr(form, f"appointment_{appointment_num}") for appointment_num in range(1, num_appointments + 1) + ] + + num_experiment_marks = len(experiment_marks) + experiment_mark_students = [experiment_mark.part_student.student for experiment_mark in experiment_marks] + oral_experiment_mark_fields = [ + getattr(form, f"oral_experiment_mark_{experiment_mark_num}") + for experiment_mark_num in range(1, num_experiment_marks + 1) + ] + protocol_experiment_mark_fields = [ + getattr(form, f"protocol_experiment_mark_{experiment_mark_num}") + for experiment_mark_num in range(1, num_experiment_marks + 1) + ] + + if form.validate_on_submit(): + for ind, appointment in enumerate(appointments): + appointment.date = appointment_fields[ind].data + + group_experiment.note = form.note.data + + db.session.commit() + + return self.render( + "assistant_group_experiment_form.html", + form=form, + experiment_label=group_experiment.semester_experiment.experiment.str(), + group_number=group_experiment.group.number, + appointment_fields=appointment_fields, + experiment_mark_zip=zip( + experiment_mark_students, oral_experiment_mark_fields, protocol_experiment_mark_fields + ), + ) + class AssistantAppointmentView(SecureAssistantModelView): can_edit = True @@ -115,7 +168,7 @@ class AssistantAppointmentView(SecureAssistantModelView): class AssistantExperimentMarkView(SecureAssistantModelView): - class EditForm(Form): + class EditForm(FlaskForm): oral_mark = mark_field("Oral") protocol_mark = mark_field("Protocol") @@ -193,7 +246,7 @@ class AssistantExperimentMarkView(SecureAssistantModelView): class AssistantUserView(SecureAssistantModelView): - class EditForm(Form): + class EditForm(FlaskForm): phone_number, mobile_phone_number, building, room = user_info_fields() generate_new_password = generate_new_password_field() diff --git a/advlabdb/forms.py b/advlabdb/forms.py new file mode 100644 index 0000000..3e81b79 --- /dev/null +++ b/advlabdb/forms.py @@ -0,0 +1,57 @@ +from flask_wtf import FlaskForm +from wtforms.fields import DateField, SubmitField, TextAreaField +from wtforms.validators import DataRequired, Optional + +from .model_dependent_funs import mark_field + + +class AssistantGroupExperimentFormBase(FlaskForm): + submit = SubmitField(label="Submit", render_kw={"class": "btn btn-success"}) + + +def assistant_group_experiment_form_factory(current_user, group_experiment): + class AssistantGroupExperimentForm(AssistantGroupExperimentFormBase): + note = TextAreaField( + "Note", + default=group_experiment.note, + validators=[Optional()], + description="This note is optional and can be seen and edited by admins and assistants that are responsible for this semester experiment. This note is for information related to the experiment and group. Examples: Protocol received, submission until ..., etc.", + ) + + appointments = group_experiment.appointments + appointment_num = 1 + for appointment in appointments: + description = None + if appointment.special: + description = "Yes" + else: + description = "No" + + setattr( + AssistantGroupExperimentForm, + "appointment_" + str(appointment_num), + DateField( + str(appointment_num), + default=appointment.date, + validators=[DataRequired()], + description=description, + ), + ) + appointment_num += 1 + + experiment_marks = group_experiment.experiment_marks + experiment_mark_num = 1 + for experiment_mark in experiment_marks: + setattr( + AssistantGroupExperimentForm, + "oral_experiment_mark_" + str(experiment_mark_num), + mark_field("Oral", experiment_mark.oral_mark), + ) + setattr( + AssistantGroupExperimentForm, + "protocol_experiment_mark_" + str(experiment_mark_num), + mark_field("Protocol", experiment_mark.protocol_mark), + ) + experiment_mark_num += 1 + + return (AssistantGroupExperimentForm(), appointments, experiment_marks) diff --git a/advlabdb/templates/assistant_group_experiment_form.html b/advlabdb/templates/assistant_group_experiment_form.html new file mode 100644 index 0000000..2cfa113 --- /dev/null +++ b/advlabdb/templates/assistant_group_experiment_form.html @@ -0,0 +1,126 @@ +{% from "macros.html" import information %} +{% extends "admin/master.html" %} + +{% block body %} + {{ information(current_user, active_semester_str, role="assistant") }} + +
+ +
+ + + + + + + + + + + +
+ Experiment + + {{ experiment_label }} +
+ Group number + + {{ group_number }} +
+
+ +
+ +
+ {{ form.csrf_token }} +
+ + + + + + + + + + {% for appointment_field in appointment_fields %} + + + + + {% endfor %} + +
+ Appointment date + + Should be in break +
+ {{ appointment_field }} + + {{ appointment_field.description }} +
+
+ +
+ +
+ + + + + + + + + + + {% for student, oral_experiment_mark, protocol_experiment_mark in experiment_mark_zip %} + + + + + + {% endfor %} + +
+ Student + + Oral mark + + Protocol mark +
+ {{ student }} + + {{ oral_experiment_mark }} + + {{ protocol_experiment_mark }} +
+
+ +
+ +
+ + + + + + + +
+ {{ form.note.label }} + + {{ form.note }} +
+
+ +
+ + + + {{ form.submit }} + + +
+ {{ footer|safe }} +{% endblock body %}